0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

データベースとCUIアプリケーションの接続(独学エンジニア レッスン5より)

Posted at

目標

今回やること

  • CUIアプリケーションをデータベースに対応させる

タスクばらし

  • 読書ログを保存するテーブルを作成する
  • PHPからデータベースに接続する
  • 読書ログをデータベースに登録する
  • 読書ログをデータベースから表示する

補足

MySQLの操作の流れ
接続→命令→切断

  • MySQLに接続する
  • MySQLに命令する
    データベースを作成する
    テーブルを作成する
    テーブルにデータを登録する
    テーブルからデータを取得する
  • MySQLとの接続を切断する

接続はMySQLに電話をかけて、相手が「今いいよ」といってから命令を出すイメージ
MySQLとの間に確立された接続のことを「コネクション」という

読書ログを保存するテーブルを作成する

目的

DockerでMySQLに接続し、読書ログを保存するテーブルを作成する

必要な知識

  • MySQLと接続するにはmysqlコマンドを使う

クライアントからmysqlサーバーに接続する

qiita.sql
// -pで値を指定しないとターミナルが入力を求め、入力時に表示されないため、セキュア
mysql -h ホスト名 -u ユーザー名 -D データベース名 -p

appコンテナからdbコンテナのmysqlに接続する

qiita.linux
docker-compose exec app mysql -h db -u book_log -D book_log -p
  • MySQLに命令する
    dev.mysql.comを参考にして、SQL文を作成する

  • ファイルからSQL文を実行することで、毎回手入力せずに済む

テキストファイルにSQL文を保存し、下記コマンドを実行する

qiita.linux
mysql < text_file

Docker上のMySQLに対して実行するなら以下のコマンド

qiita.linux
docker-compose exec app /bin/bash
mysql -h db -u book_log -D book_log -p < text_file

実践

  • Dockerの機能でコンテナを立ち上げた際に、データベースは作成される
    そのため、以下のコマンドを入力すれば、データベースは自動で作成される
qiita.linux
docker-compose exec app mysql -h db -u book_log -D book_log -p
  • MySQLでテーブルを作成する
qiita.sql
CREATE TABLES reviews (
    id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    title VARCHAR(255),
    author VARCHAR(100),
    status VARCHAR(10),
    score INTEGER,
    summary VARCHAR(1000),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARACTER SET=utf8mb4;

次の作業でSQLをファイルから実行するため、一旦作成したテーブルは削除する

qiita.sql
DROP TABLE reviews;
  • ファイルにテーブル作成のSQL文を保存し、そのファイルからSQL文を実行する

保存するテーブルの中身

itinitialize_reviews_table.sql
// reviewsテーブルを初期化
DROP TABLE IF EXISTS reviews;

CREATE TABLES reviews (
    id INTEGER AUTO_INCREMENT NOT NULL PRIMARY KEY,
    title VARCHAR(255),
    author VARCHAR(100),
    status VARCHAR(10),
    score INTEGER,
    summary VARCHAR(1000),
    created_at TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP
) DEFAULT CHARACTER SET=utf8mb4;

ファイルを実行

qiita.linux
docker-compose exec app /bin/bash
mysql -h db -u book_log -D book_log -p < itinitialize_reviews_table.sql

PHPからデータベースに接続する

目的

  • PHPからMySQLに接続する

必要な知識

  • PHPからMySQLを利用する時はMySQLiを使おう
    MySQLに接続するにはmysqli_connect関数使おう
qiita.linux
mysqli_connect('my_host', 'my_user', 'my_password', 'my_db')

読書ログでMySQLに接続するなら

qiita.linux
mysqli_connect('db', 'book_log', 'pass', 'book_log')
  • MySQLの使用が完了したらMySQLとの接続を切る

接続を切るにはmysqli_close関数を使う

qiita.linux
// $link:mysqli_connect()が返すリンクID
mysqli_close($link)

実践

・読書ログでMySQLに接続、切断する

以下をbook_log.phpに追記

book_log.php
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;
    }
    // $linkに格納された値は関数の外でも使用するため、戻り値に指定
    return $link;
}

読書ログをデータベースに登録する

目的

  • PHPからMySQLにデータを追加する

必要な知識

  • SQLのINSERT文でテーブルにデータを登録する

INSERT文を使うと、テーブルに一行のデータを挿入する

php
$link : mysql_connect()が返すリンクID
$query : SQL文の文字列

companiesテーブルにデータを登録するなら

php
$link = mysqli_connect('db', 'book_log', 'pass', 'book_log');
$sql = "INSERT INTO compaies (name) VALUES ('SmartHR inc')";
mysqli_query($link, $sql);
  • mysqli_query()は実行時に失敗した場合にFALSEを返すことを利用してエラーメッセージを表示する
php
$link = mysqli_connect('db', 'book_log', 'pass', 'book_log');
$sql = "INSERT INTO compaies (name) VALUES ('SmartHR inc')";
$result = mysqli_query($link, $sql);
if ($result) {
	echo 'データを追加しました' . PHP_EOL;
} else {
	echo 'Error: データの追加に失敗しました' . PHP_EOL;
	echo 'Debugging Error: ' . mysqli_error($link) . PHP_EOL;
}
  • ヒアドキュメントを使うと、複数行の文字列をそのままコード中に記載できるので、SQL文を書くときなどに見やすくなり便利
php
// ヒアドキュメント書く際は必ず左詰め
$sql = <<<EOT
INSERT INTO companies (
	name
) VALUES (
	'SmartHR inc'
)
EOT;
  • バリデーション処理をする

バリデーション処理をしないと、、
予期せぬ値が入力されるかも
セキュリティ上問題があったり、変なデータがデータベースに保存され、プログラムが不具合を起こしたりしかねない

  • よくあるバリデーション処理

値が入力されているか?
文字列の長さは適当な範囲か?
数値が入力されているか?
数値は適切な範囲内の値か?
選択肢から選ばれた値か?
書式が正しいか?(メールアドレス、電話番号など)

  • バリデーションの基本形

strlen関数は全角文字(日本語)をカウントすると、1文字を3文字としてカウントする。
これはstrlenが文字数ではなくバイト数を返しており、日本語は一文字で複数バイトを使うため。
mb_strlen関数だと複数バイトを考慮し、日本語の1文字を1文字としてカウントする。

php
// バリデーションメソッドを用意
function validate($name)
{
	$erros = [];
	if (!strlen($name)) {
		$errors['name'] = '社名を入力してください';
	} elseif (strlen($name) > 100) {
		$errors['name'] = '社名は100文字以内で入力してください';
	}
	// エラー変数を返す
	return $errors;
}

$name = trim(fgets(STDIN));
$validated = validate($name);
if (count($validated) > 0) {
	foreach ($validated as $error) {
		echo $error . PHP_EOL;
	} 
	// 処理を中断する
	return;
}
  • 整数のバリデーション
    文字列を整数に変換することができる
    ユーザーの入力値を適切な型に変換してプログラムで扱う時などに使用する

型キャスト
(int)
(bool)
(string)

文字列を整数へ変換するなら

php
$a = '2';
var_dump( (int) $a )      // int(2)

ex)型キャストの挙動

php
php > var_dump((int)5.8);
int(5)
php > var_dump((int) 'hoge');
int(0)
php >

※php -a
インタラクティブにphpを実行できる
※変数の型を意識する

実践

  • 読書ログをPHPからデータベースに登録する

book_log.phpの関数createReviewsに追記

book_log.php
function createReviews($link)
{
..
..
..

INSERT INTO reviews (
    title,
    author,
    status,
    score,
    summary
) VALUES (
    "{$review['title']}",
    "{$review['author']}",
    "{$review['status']}",
    {$review['score']},
    "{$review['summary']}"
)
EOT;

    $result = mysqli_query($link, $sql);

    if($result) {
        echo 'データを追加しました' . PHP_EOL;
    } else {
        echo 'Error: データの追加に失敗しました' . PHP_EOL;
        echo 'Debugging error: ' . mysqli_error($link)  . PHP_EOL;
    }
}
  • 上記の「読書ログをPHPからデータベースに登録する処理」にバリデーション処理を加える

book_log.phpの関数validateを作成し、中に処理を記載

book_log.php
function validate($review)
{
    $errors = [];

    // 書籍名が正しく入力されているかチェック
    if (!strlen($review['title'])) {
        $errors['title'] = '書籍名を入力してください';
    } elseif (strlen($review['title']) > 255) {
        $errors['title'] = '書籍名は255文字以内で入力してください';
    }

    // 著者名が正しく入力されているかチェック
    if (!strlen($review['author'])) {
        $errors['author'] = '著者名を入力してください';
    } elseif (strlen($review['author']) > 100) {
        $errors['author'] = '著者名は100文字以内で入力してください';
    }

    // 読書状況が正しく入力されているかチェック
    $book_status = [
        '未読',
        '読んでる',
        '読了'
    ];
    if (!in_array($review['status'], $book_status, true)) {
        $errors['status'] = '未読,読んでる,読了のいずれかを入力してください';
    }

    // 評価が正しく入力されているかチェック
    if ($review['score'] < 1 || $review['score'] > 5) {
        $errors['score'] = '評価は1以上5点以下で入力してください';
    }

    // 感想が正しく入力されているかチェック
    if (!strlen($review['summary'])) {
        $errors['summary'] = '感想を入力してください';
    } elseif (strlen($review['summary']) > 1000) {
        $errors['summary'] = '感想は1000文字以内で入力してください';
    }

    return $errors;
}

読書ログをデータベースから表示する

目的

  • PHPからMySQLのデータを取得し、表示する

必要な知識

  • mysqli_*関数

mysqli_query:データベース上でクエリを実行する
成功したらmysqli_resultオブジェクトを返す

php
mysqli_query($link, $query)

mysqli_fetch_assoc:結果の行を連想配列で取得する
$result:mysqli_resultオブジェクト

php
mysqli_fetch_assoc($result)

mysqli_free_result:結果に関連付けられたメモリを開放する
$result:mysqli_resultオブジェクト

php
mysqli_free_result($result)
  • PHPからSQLでデータを取得する
php
$link = mysqli_connect('db', 'book_log', 'pass', 'book_log');
$sql = "SELECT * FROM compaies";
$result = mysqli_query($link, $sql);

// 連想配列で結果を取得
while ($company = mysqli_fetch_assoc($results)) {
	echo '会社名: ' . $company['name'] . PHP_EOL;
	echo '代表者: ' . $company['founder'] . PHP_EOL;
}

// メモリを開放する
mysqli_free_result($result);

実践

book_log.phpの関数viewReviewsに処理を追記

book_log.php
function viewReviews($link)
{
    var_dump($link) . PHP_EOL;
    $sql = 'SELECT id, title, author, status, score, summary FROM reviews';
    $results =  mysqli_query($link, $sql);

    echo '登録されている読書ログを表示します' . PHP_EOL;

    while ($review = mysqli_fetch_assoc($results)) {
        echo '書籍名:' . $review['title'] . PHP_EOL;
        echo '著者名:' . $review['author'] . PHP_EOL;
        echo '読書状況(未読,読んでる,読了):' . $review['status'] . PHP_EOL;
        echo '評価(5点満点の整数):' . $review['score'] . PHP_EOL;
        echo '感想:' . $review['summary'] . PHP_EOL;
        echo '---------------------' . PHP_EOL;
    }

    mysqli_free_result($results);
}

参考にしたサイト

独学エンジニア

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?