SHINYA TECH

公務員(行政職)から34歳でエンジニア転職した人

#10 PHPからMySQLのデータを取得する方法

f:id:kshinya-tech:20220218032716p:plain

ここまでの学習で読書ログサービスのデータベースへの対応について

  • 読書ログを保存するテーブルを作成する
  • 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;
    }
}

参考URL

www.php.net

www.php.net

www.php.net

www.php.net