CSVデータの書き込み
CSVデータを1行書き込むには fputcsv() を利用します。
fputcsv()
fputcsv() に配列データを渡すと、ファイルにCSVフォーマットで書き込みます。
fputcsv(リソース, 配列データ);
HTMLフォーム
入力画面
氏名、メールアドレス、パスワードを入力し【確認】で confirm.php にPOST送信します。
input.php
※CSSは Bootstrap5 の CDN を利用しています
<form action="confirm.php" method="post">
<div class="mb-3">
<label class="form-label fw-bold">氏名</label>
<input type="text" name="name" value="<?= @$user['name'] ?>" class="form-control">
<p class="text-danger badge"><?= @$errors['name'] ?></p>
</div>
<div class="mb-3">
<label class="form-label fw-bold">メールアドレス</label>
<input type="text" name="email" value="<?= @$user['email'] ?>" class="form-control">
<p class="text-danger badge"><?= @$errors['email'] ?></p>
</div>
<div class="mb-3">
<label class="form-label fw-bold">パスワード</label>
<input type="password" name="password" class="form-control">
<p class="text-danger badge"><?= @$errors['password'] ?></p>
</div>
<button class="btn btn-primary">確認</button>
</form>
確認画面
確認画面ではPOST送信されたデータを表示します。まあフォームで【登録】ボタンで add.php にPOST送信するようにします。
confirm.php
<form action="add.php" method="post">
<h2 class="h2">会員登録</h2>
<div class="mb-3">
<label class="fw-bold">氏名</label>
<p class="mt-2"><?= $user['name'] ?></p>
</div>
<div class="mb-3">
<label class="fw-bold">メールアドレス</label>
<p class="mt-2"><?= $user['email'] ?></p>
</div>
<div>
<p>この内容でよろしいですか?</p>
<a class="btn btn-outline-primary" href="input.php">戻る</a>
<button class="btn btn-primary">登録</button>
</div>
</form>
CSV初期化
add.php で会員登録処理をします。確認画面でセッションに保存したデータを users.csv に書き込みます。
CSVファイルパスの設定
PHPの定数で、CSVファイルのパスを設定しておきます。ファイルパスは data/users.csv としました。
define('CSV_PATH', 'data/users.csv');
カラムの定義
ユーザデータのカラムを配列で用意しておきます。このデータは CSVファイルの1行目に書き込みます。
$columns = ['name', 'email', 'password'];
CSV初期化
CSVファイルを開く
CSVファイルの初期化関数 initCSV() を定義します。
function initCSV($data)
{
}
CSVファイルを a+ (追記 & 読み込みモード)で開きます。もしファイルがなければ自動的に作成されます。
function initCSV($data)
{
$file = fopen(CSV_PATH, 'a+');
}
初期データの書き込み
もしCSVファイルがなければ作成し、データがなかったら書き込みます。
function initCSV($data)
{
$file = fopen(CSV_PATH, 'a+');
flock($file, LOCK_EX);
if (!fgets($file)) {
fputcsv($file, $data);
}
flock($file, LOCK_UN);
fclose($file);
}
CSV初期化の確認
確認画面から登録して、CSVファイルの初期化をしてみましょう。
define('CSV_PATH', 'data/users.csv');
$columns = ['name', 'email', 'password'];
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
initCSV($columns);
}
data/users.csv ファイルが作成され、name,email,password が書き込まれていることを確認します。
CSVデータ書き込み
CSV書き込み処理 insert() メソッドを定義します。引数にはデータ $data とカラム $columns を渡します。
function insert($data, $columns)
{
}
パスワードの暗号化
パスワードは暗号化しておきましょう。PHPでは password_hash() で簡単に暗号化できます。
password_hash(パスワード, アルゴリズム, ソルト)
アルゴリズム | 説明 |
---|---|
PASSWORD_DEFAULT | bcryptアルゴリズムで PASSWORD_BCRYPT と同じ |
PASSWORD_BCRYPT | bcryptアルゴリズム |
PASSWORD_ARGON2I | Argon2i ハッシュアルゴリズム |
PASSWORD_ARGON2ID | Argon2id ハッシュアルゴリズム |
ソルト
ソルトはパスワードをさらに独自に強化するオプションです。今回は利用しません。
パスワードの暗号化
パスワードを PASSWORD_BCRYPT で暗号化します。
$data['password'] = password_hash($data['password'], PASSWORD_BCRYPT);
CSVデータ書き込み
CSVファイルを a(追記モード)で開き、POSTデータをCSV書き込みします。
function insert($data)
{
foreach ($columns as $column) {
$data[$column] = htmlspecialchars($data[$column]);
}
$data['password'] = password_hash($data['password'], PASSWORD_BCRYPT);
$file = fopen(CSV_PATH, 'a');
flock($file, LOCK_EX);
fputcsv($file, $data);
flock($file, LOCK_UN);
fclose($file);
}
データ書き込みを確認
insert() でセッションデータを渡して実行します。データがない場合は、input.php にリダイレクトします。
if ($_SERVER['REQUEST_METHOD'] == 'POST' && isset($_SESSION['user'])) {
initCSV($columns);
insert($_SESSION['user']);
unset($_SESSION['user']);
unset($_SESSION['errors']);
} else {
header('Location: input.php');
}
HTMLフォームでデータ送信して確認してみましょう。
users.csv にデータが追記されました。
ソース
商品一覧
item_list.php
<?php
$file_path = 'data/items.csv';
$items = loadCSV($file_path);
function loadCSV($file_path)
{
if (!file_exists($file_path)) return;
$items = [];
$file = fopen($file_path, 'r');
$columns = fgetcsv($file);
while ($data = fgetcsv($file)) {
foreach ($columns as $index => $column) {
$item[$column] = $data[$index];
}
$items[] = $item;
}
fclose($file);
return $items;
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h3 class="h3">商品一覧</h3>
<dl>
<?php if ($items) : ?>
<?php foreach ($items as $item) : ?>
<dt><?= $item['name'] ?></dt>
<dd><?= $item['price'] ?>円</dd>
<?php endforeach ?>
<?php endif ?>
</dl>
</div>
</body>
</html>
input.php
<?php
session_start();
$user = ['name' => '', 'email' => '', 'password' => ''];
if (isset($_SESSION['user'])) $user = $_SESSION['user'];
if (isset($_SESSION['errors'])) $errors = $_SESSION['errors'];
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<div class="container">
<h2 class="h2">会員登録</h2>
<form action="confirm.php" method="post">
<div class="mb-3">
<label class="form-label fw-bold">氏名</label>
<input type="text" name="name" value="<?= @$user['name'] ?>"
class="form-control">
<p class="text-danger badge"><?= @$errors['name'] ?></p>
</div>
<div class="mb-3">
<label class="form-label fw-bold">メールアドレス</label>
<input type="text" name="email" value="<?= @$user['email'] ?>"
class="form-control">
<p class="text-danger badge"><?= @$errors['email'] ?></p>
</div>
<div class="mb-3">
<label class="form-label fw-bold">パスワード</label>
<input type="password" name="password"
class="form-control">
<p class="text-danger badge"><?= @$errors['password'] ?></p>
</div>
<button class="btn btn-primary">確認</button>
</form>
</div>
</body>
</html>
confirm.php
<?php
session_start();
if ($_SERVER['REQUEST_METHOD'] == 'POST') {
$user = $_POST;
$errors = validate($user);
$_SESSION['user'] = $user;
$_SESSION['errors'] = $errors;
}
if (empty($user) || !empty($errors)) {
header('Location: input.php');
exit;
}
function validate($user)
{
$errors = [];
if (empty($user['name'])) {
$errors['name'] = '氏名を入力してください';
}
if (empty($user['email'])) {
$errors['email'] = 'メールアドレスを入力してください';
}
if (empty($user['password'])) {
$errors['password'] = 'パスワードを入力してください';
}
return $errors;
}
?>
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<div class="container">
<form action="add.php" method="post">
<h2 class="h2">会員登録</h2>
<div class="mb-3">
<label class="fw-bold">氏名</label>
<p class="mt-2"><?= $user['name'] ?></p>
</div>
<div class="mb-3">
<label class="fw-bold">メールアドレス</label>
<p class="mt-2"><?= $user['email'] ?></p>
</div>
<div>
<p>この内容でよろしいですか?</p>
<a class="btn btn-outline-primary" href="input.php">戻る</a>
<button class="btn btn-primary">登録</button>
</div>
</form>
</div>
</body>
</html>
add.php
<?php
session_start();
define('CSV_PATH', 'data/users.csv');
$columns = ['name', 'email', 'password'];
if ($_SERVER['REQUEST_METHOD'] !== 'POST') {
exit;
}
if (empty($_SESSION['user'])) {
header('Location: input.php');
}
initCSV($columns);
insert($_SESSION['user'], $columns);
unset($_SESSION['user']);
unset($_SESSION['errors']);
function initCSV($data)
{
$file = fopen(CSV_PATH, 'a+');
flock($file, LOCK_EX);
if (!fgets($file)) {
fputcsv($file, $data);
}
flock($file, LOCK_UN);
fclose($file);
}
function insert($data)
{
foreach ($columns as $column) {
$data[$column] = htmlspecialchars($data[$column]);
}
$data['password'] = password_hash($data['password'], PASSWORD_BCRYPT);
$file = fopen(CSV_PATH, 'a');
flock($file, LOCK_EX);
fputcsv($file, $data);
flock($file, LOCK_UN);
fclose($file);
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link
href="https://cdn.jsdelivr.net/npm/bootstrap@5.0.0-beta1/dist/css/bootstrap.min.css"
rel="stylesheet">
</head>
<body>
<div class="container">
<h2 class="h2">会員登録完了</h2>
<p>会員登録が完了しました。</p>
<div>
<a href="input.php" class="btn btn-outline-primary">戻る</a>
</div>
</div>
</body>
</html>