パーフェクトPHP 6章のコードが古いのでPHP7に対応できるよう書き換えてみた
こんにちは! この記事を見ている方は、恐らくパーフェクトPHP第6章のひとこと掲示板が上手く表示されない、データが保存されないといった状況に陥っている方が多いと思います。
僕も、第6章でなかなかデータを保存することができず時間がかかったので、PHP7でも実行できるように書き換えたコードをメモとして残しておきます。
mysql_*関数は「非推奨」又は「使えない」
パーフェクトPHPに記載されている、mysql_connect等のmysql_とつく関数はPHP5.5以降は非推奨、PHP7では削除されています。
そのため、PHP7の環境の場合は書籍に書いてあるコードのままでは動作しません。(PHP5系なら一応動くと思います。)
非推奨になった理由としては、セキュリティの脆弱性であったり、mysqlの最新の機能に対応してない等が主な理由らしいです。
こちらのLIGさんの記事がまとめてあって読みやすかったです。
使っちゃいけない! PHPのmysql_* 系関数の取り扱いに関する海外の見解 | 東京のWeb制作会社LIG
mysqli関数を使って書き換えてみる
上記の理由から、PHP7に対応していて、書き方も書籍と似ているmysqli関数を使いたいと思います。
mysqli関数はオブジェクト型と手続き型の2種類の書き方があるのですが、サンプルコードに一番近い形にするため手続き型を使用しています。
以下全体のコード
<?php $link = mysqli_connect('localhost', 'root', ''); if(!$link) { die('データベースに接続できません:' . mysqli_error()); } // データベースを選択する mysqli_select_db($link ,'oneline_bbs'); $errors = array(); // POSTなら保存処理実行 if($_SERVER['REQUEST_METHOD'] === 'POST') { $name = null; if(!isset($_POST['name']) || !strlen($_POST['name'])) { $errors['name'] = '名前を入力してください'; } else if(strlen($_POST) > 40) { $errors['name'] = '名前は40文字以内で入力してください'; } else { $name = $_POST['name']; } // ひとことが正しく入力されているかチェック if(!isset($_POST['comment']) || !strlen($_POST['comment'])) { $errors['comment'] = 'ひとことを入力してください'; } else if(strlen($_POST['comment' ]) > 200) { $errors['comment'] = 'ひとことは200文字以内で入力してください'; } else { $comment = $_POST['comment']; } // エラーがなければ保存 if(count($errors) === 0) { $sql = "insert into post (name, comment, created_at) values ( '" . mysqli_real_escape_string($link,$name) . "','" . mysqli_real_escape_string($link,$comment) . "','" . date('Y-m-d H:i:s') . "')"; // 保存する mysqli_query($link, $sql); mysqli_close($link); header('Location: http://' .$_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']); } } ?> <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>ひとこと掲示板</title> </head> <body> <h1>ひとこと掲示板</h1> <form action="bbs.php" method="post"> <?php if (count($errors) > 0): ?> <ul class="error_list"> <?php foreach($errors as $error): ?> <li> <?php echo htmlspecialchars($error, ENT_QUOTES, 'UTF-8'); ?> </li> <?php endforeach; ?> </ul> <? endif; ?> 名前: <input type="text" name="name" size="60"><br> ひとこと: <input type="text" name="comment"><br> <input type="submit" name="submit" value="送信"> </form> <?php // 投稿された内容を取得するSQLを作成して結果を取得 $sql = "select * from post order by created_at desc;"; $result = mysqli_query($link, $sql); ?> <?php if($result !== false && mysqli_num_rows($result)): ?> <ul> <?php while($post = mysqli_fetch_assoc($result)): ?> <li> <?php echo htmlspecialchars($post['name'], ENT_QUOTES, 'UTF-8'); ?>: <?php echo htmlspecialchars($post['comment'], ENT_QUOTES, 'UTF-8'); ?> - <?php echo htmlspecialchars($post['created_at'], ENT_QUOTES, 'UTF-8'); ?> </li> <?php endwhile; ?> </ul> <?php endif; ?> <?php mysqli_free_result($result); mysqli_close($link); ?> </body> </html>
注意点
ほとんどmysqlがmysqliになっただけのような気がしますが、注意して欲しいのは引数の順番です。
mysqli_select_db($link, 'oneline_bbs');
mysqli_query($link, $sql);
この2箇所は書籍と引数の順番が逆になっています。mysqliでは第一引数に接続先のmysqlオブジェクトが必要です。
また、
$sql = "insert into post (name, comment, created_at) values ( '" . mysqli_real_escape_string($link,$name) . "','" . mysqli_real_escape_string($link,$comment) . "','" . date('Y-m-d H:i:s') . "')";
この文にある、mysqli_real_escape_string関数は手続き型の書き方では引数に文字列と接続先のmysqlオブジェクトが必要です