ここまでの学習で読書ログサービスのデータベースへの対応について
- 読書ログを保存するテーブルを作成する
- PHPからデータベースに接続する
- 読書ログをデータベースに登録する
ということができるようになりました。
今回は、読書ログをデータベースから表示する方法を学びました。
SQLでデータを取得する方法
テーブルからデータを取得するにはSELECT文を使う
- SELECTにはテーブルから出力したい列名を、FROMにはデータを取り出すテーブルを指定する
SELECT <列名>, ・・・ FROM <テーブル名>;
- 全ての列のデータを取得する場合は SELECT に
*
を書く
SELECT * FROM <テーブル名>;
なお、全ての列を取得すると実行速度が遅くなるため、本番環境ではあまり使われない(らしい)。
必要な列だけ取得するように心掛ける。
PHPからSQLでデータを取得する
SQL文を実行した結果のデータを取得するにはmysqli_fetch_assocを使う
例えば、会社(company)の名前(name)と創業者(founder)についてのテーブルがあり、 会社名と創業者名を取得したい場合は以下のように書く。
// データベースに接続する $link = mysqli_connect('ホスト名', 'ユーザ名', 'パスワード', 'データベース名'); // SQL文を実行 $sql = 'SELECT name, founder FROM companies'; $results = mysqli_query($link, $sql); // 連想配列で結果を取得する while ($company = mysqli_fetch_assoc($results)) { echo '会社名:' . $company['name'] . PHP_EOL; echo '創業者:' . $company['founder'] . PHP_EOL; } // メモリを開放する mysqli_free_result($results);
mysqli_ * 関数について
mysqli_query : データベース上でクエリを実行する
- 成功したら
mysqli_result
オブジェクトを返す
mysqli_query($link, $query)
mysqli_fetch_assoc : 結果の行を連想配列で取得する
- $result :
mysqli_result
オブジェクト
mysqli_fetch_assoc($result)
mysqli_free_result : 結果に関連付けられたメモリを開放する
- $result :
mysqli_result
オブジェクト
mysqli_free_result($result)
ターミナルで挙動を確認してみる
以下のテーブルを事前に用意。
MySQL [book_log]> SELECT * FROM companies; +----+-------------+------------+-----------------------+ | id | name | founder | created_at | +----+-------------+------------+-----------------------+ | 1 | SmartHR Inc | Shoji Miyata | 2022-02-16 19:35:34 | +----+-------------+------------+-----------------------+
ひとまず、var_export
を用いて、どのような結果が出力されているか確認する。
<?php $link = mysqli_connect('db', 'book_log', 'pass', 'book_log'); if (!$link) { echo 'Error: データベースに接続できませんでした' . PHP_EOL; echo 'Debugging error:' . mysqli_connect_error() . PHP_EOL; exit; } echo 'データベースに接続できました' . PHP_EOL; $sql = 'SELECT name, founder FROM companies'; $results = mysqli_query($link, $sql); while ($company = mysqli_fetch_assoc($results)) { var_export($company); }
ターミナルでの実行結果
sk@MacBook-Air part2 % docker-compose exec app php tmp/mysqli.php データベースに接続できました array ( 'name' => 'SmartHR Inc', 'founder' => 'Shoji Miyata',
$company
が連想配列となっていることが確認できた。
会社名、創業者名をecho
してみる。
<?php $link = mysqli_connect('db', 'book_log', 'pass', 'book_log'); if (!$link) { echo 'Error: データベースに接続できませんでした' . PHP_EOL; echo 'Debugging error:' . mysqli_connect_error() . PHP_EOL; exit; } echo 'データベースに接続できました' . PHP_EOL; $sql = 'SELECT name, founder FROM companies'; $results = mysqli_query($link, $sql); while ($company = mysqli_fetch_assoc($results)) { echo '会社名:' . $company['name'] . PHP_EOL; echo '代表者名:' . $company['founder'] . PHP_EOL; } mysqli_free_result($results); mysqli_close($link); echo 'データベースとの接続を切断しました' . PHP_EOL;
ターミナルでの実行結果
sk@MacBook-Air part2 % docker-compose exec app php tmp/mysqli.php
データベースに接続できました
会社名:SmartHR Inc
代表者名:Shoji Miyata
データベースとの接続を切断しました
読書ログサービスに実装
<?php // バリデーション処理を定義 function validate($review) { $errors = []; // 書籍名が正しく入力されているかチェック if (!strlen($review['title'])) { $errors['title'] = '書籍名を入力してください'; } elseif (mb_strlen($review['title']) > 255) { $errors['title'] = '書籍名は255文字以内で入力してください'; } // 著者名が正しく入力されているかチェック if (!strlen($review['author'])) { $errors['author'] = '著者名を入力してください'; } elseif (mb_strlen($review['author']) > 30) { $errors['author'] = '著者名は30文字以下で入力してください'; } // 読書状況が正しく入力されているかチェック if (!strlen($review['status'])) { $errors['status'] = '読書状態を入力してください'; } elseif (!in_array($review['status'], ['未読', '読んでいる', '読了'])) { $errors['status'] = '読書状態は「未読」、「読んでいる」、「読了」のいずれかを入力してください'; } // 評価が正しく入力されているかチェック if (!strlen($review['score'])) { $errors['score'] = '評価を入力してください'; } elseif ($review['score'] < 1 || 5 < $review['score']) { $errors['score'] = '1~5の整数を入力してください'; } // 感想が正しく入力されているかチェック if (!strlen($review['summary'])) { $errors['summary'] = '読書状態を入力してください'; } elseif (mb_strlen($review['summary']) > 500) { $errors['summary'] = '読書状態は30文字以下で入力してください'; } return $errors; } // MySQLへの接続処理を関数として定義 function dbConnect() { $link = mysqli_connect('db', 'book_log', 'pass', 'book_log'); if (!$link) { echo 'Error: データベースに接続できませんでした' . PHP_EOL; echo 'Debugging error:' . mysqli_connect_error() . PHP_EOL; exit; } // データベースと切断する際に、接続情報を使用するため、returnで返す return $link; } // 読書ログ登録の関数を定義 function createReview($link) // 引数で $link を受け取る { $review = []; echo '読書ログを登録してください' . PHP_EOL; echo '書籍名:'; $review['title'] = trim(fgets(STDIN)); echo '著者名:'; $review['author'] = trim(fgets(STDIN)); echo '読書状況(未読、読んでいる、読了):'; $review['status'] = trim(fgets(STDIN)); echo '評価(5点満点の整数):'; $review['score'] = (int) trim(fgets(STDIN)); //整数として変数に格納 echo '感想:'; $review['summary'] = trim(fgets(STDIN)); $validated = validate($review); if (count($validated) > 0) { foreach ($validated as $error) { echo $error . PHP_EOL; } return; } $sql = <<<EOT INSERT INTO reviews ( title, author, status, score, summary ) VALUES ( "{$review['title']}", "{$review['author']}", "{$review['status']}", "{$review['score']}", "{$review['summary']}" ); EOT; // EOT; の前にスペースやインデントをつけてはいけない。 $result = mysqli_query($link, $sql); if ($result) { echo '登録が完了しました' . PHP_EOL . PHP_EOL; } else { echo 'Error: データの追加に失敗しました' . PHP_EOL; echo 'Debugging error:' . mysqli_error($link) . PHP_EOL . PHP_EOL; } } // 読書ログ表示の関数を定義 function getReviews($link) // 引数で $link を受け取る { echo '登録されている読書ログを表示します' . PHP_EOL; $sql = 'SELECT title, author, status, score, summary FROM reviews'; $results = mysqli_query($link, $sql); while ($result = mysqli_fetch_assoc($results)) { echo '書籍名:' . $result['title'] . PHP_EOL; echo '著者名:' . $result['author'] . PHP_EOL; echo '読書状況:' . $result['status'] . PHP_EOL; echo '評価:' . $result['score'] . PHP_EOL; echo '感想:' . $result['summary'] . PHP_EOL; echo '-----------------' . PHP_EOL; } mysqli_free_result($results); // メモリを開放する } // MySQLとの接続処理 // 切断処理をする際に接続情報が必要なため、別途$link変数に格納している $link = dbConnect(); while (true) { echo '1. 読書ログを登録' . PHP_EOL; echo '2. 読書ログを表示' . PHP_EOL; echo '9. アプリケーションを終了' . PHP_EOL; echo '実行したい番号(1,2,9)を入力してください:'; $i = trim(fgets(STDIN)); if ($i === '1') { // 読書ログを登録する createReview($link); // 引数で $link を渡す } elseif ($i === '2') { // 読書ログを表示する getReviews($link); // 引数で $link を渡す } elseif ($i === '9') { // MySQLとの切断処理 mysqli_close($link); break; } }