はじめに
今回phpの学習のためにブログを作成してみました。
まだ今回は最低限の実装だけを行い、アプリケーションを動かすことだけにフォーカスしましたので下記についての実装は行っていません。
- CSRF対策
- 例外処理
この記事は自身のphpでの実装の振り返りと備忘録として記録したいと思います。
何かこれはまずいぞということがありましたら優しくご教授ください。。
CRUD処理に関する各メソッド
<?php
namespace Myapp;
class Blog {
private $_db;
public function __construct() {
$this->_db = new \PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
}
//全件取得。
public function getAll(){
$stmt = $this->_db->query("select * from blogs order by id desc");
return $stmt->fetchAll(\PDO::FETCH_OBJ);
}
//URLからIDを取得しPDOオブジェクトで抽出。
public function show(){
$url = $_SERVER["REQUEST_URI"];
$id = substr($url, -2);
$sql = sprintf("select * from blogs where id = %s", $id );
$stmt = $this->_db->query($sql);
return $stmt->fetch(\PDO::FETCH_OBJ);
}
//挿入
public function create() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$title = $_POST["title"];
$content = $_POST["content"];
$sql = "insert into blogs (title, content) values (:title, :content)";
$stmt = $this->_db->prepare($sql);
$stmt->execute([':title' => $title, ':content' => $content]);
header('Location:http://' . SITE_URL);
}
}
//削除
public function delete(){
$url = $_SERVER["REQUEST_URI"];
$id = substr($url, -2);
$sql = sprintf("delete from blogs where id = %d", $id );
$stmt = $this->_db->query($sql);
}
//更新
public function update() {
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
$url = $_SERVER["REQUEST_URI"];
$id = substr($url, -2);
$title = $_POST["title"];
$content = $_POST["content"];
$sql = "update blogs set title = ?, content = ? where id = ?";
$stmt = $this->_db->prepare($sql);
$stmt->bindValue(1, $title);
$stmt->bindValue(2, $content);
$stmt->bindValue(3, $id);
$stmt->execute();
}
}
}
?>
コンストラクトについて
public function __construct() {
$this->_db = new \PDO(PDO_DSN, DB_USERNAME, DB_PASSWORD);
}
上記のコードはデータベースに接続する際にデータベースの情報を参照しています。細かいコードの内容はconfig.phpにご確認ください。
ini_set("display_errors", 1);
define('PDO_DSN', 'mysql:dbname=blog_app;host=localhost;charset=utf8;unix_socket=/tmp/mysql.sock');
define("SITE_URL", $_SERVER["HTTP_HOST"]);
define('DB_USERNAME', 'admin');
define('DB_PASSWORD', 'admin1234');
ここのPDOクラスの中に入っているmysqlへのデータベースのアクセスがうまく行かずに
SQLSTATE[HY000] [2002] No such file or directory。
とのエラーが出てしまいました。ディレクトリーがないとのことです。
調べてみるとmysqlで指定されているディレクトリのパスが異なっている等の原因と思われます。
なので直接、
unix_socket=/tmp/mysql.sock'
と記述しパスを指定することによってエラーが解決しました。
またはhost:localhostとせずにhost:127.0.0.1とIPアドレスを指定することによってもエラーが解決したのですが、解決できた理由は分かっていないので誰か教えてください。。
queryについて
public function getAll() {
$stmt = $this->_db->query("select * from todos order by id desc");
//結果をオブジェクト形式で返す
return $stmt->fetchAll(\PDO::FETCH_OBJ);
まずはqueryについてですがgetAllメソッドでのsql文はqueryのみを実行しています。queryを使用するのは 『固定SQLを実行する場合はqueryを使う』 という認識でいいようです。なので変数を割り当てないようなシンプルなsql文を使用する際にいいみたいですね。
prepareとexecuteについて
//create処理での変数の扱い
$sql = "insert into blogs (title, content) values (:title, :content)";
$stmt = $this->_db->prepare($sql);
$stmt->execute([':title' => $title, ':content' => $content]);
header('Location:http://' . SITE_URL);
//update処理での変数の扱い
$sql = "update blogs set title = ?, content = ? where id = ?";
$stmt = $this->_db->prepare($sql);
$stmt->bindValue(1, $title);
$stmt->bindValue(2, $content);
$stmt->bindValue(3, $id);
$stmt->execute();
また,prepareとexecuteについてですがこれは基本的にセットで使われるという認識でいいようです。
またこれをセットで扱うことによってこのSQL内のパラメータを指定する部分には「:名前」か疑問符「?」のパラメータマークを書いて処理します。
createでの処理について見てもらうとsql文の変数を:名前のような変数を割り当てています。
prepareメソッドでSQLをセットしexecuteする際に配列な中で値を渡しています。
またupdateの処理を見てみるとこちらは疑問符の「?」を使用しています。
同じようにprepareでsqlをセットしたのちにバインドで値を渡しています。
bindValueの引数は(左からの順番、セットする値)となっています。
その後にexecuteで実行します。
また詳しく調べるとSQLインジェクション対策としても機能するのですがこちらでは割愛します。
URLからのID取得
今回の実装でのポイントですが該当の記事に対する詳細画面に映ることですがどのようにidを取得して移動するのかという事がポイントでした。
railsではparamsで勝手にurlにidが入ってくれていたことを思い出して、urlからidを取得する事から考えました。
まずは一覧ページの詳細ボタンに配置したaタグにidを埋め込んでみました。
<li class="show"><a href="/show.php?id=<?php echo h($blog->id)?>">詳細</a></li>
そこからurlからidを切り取ります。
$url = $_SERVER["REQUEST_URI"];
$id = substr($url, -2);
//urlの中身はこれです。
//http://localhost:8888/show.php?id=88
//substrで後ろから2番目以降の文字である88を取得しています。
ここまで出来たら後はそのidを使ってsqlを扱うだけですね。
またこのような実装の仕方がいいのかはよく分からないですし、他の実装方法等があれば教えてください。
最後に
今回phpを学習して勉強になったのがsqlを操作しデータベースを扱う事です。今更な話ですがsqlの扱い方でパフォーマンスも色々と変わってくるみたいなので今後sqlについての学習も進めていきたいと思います。
僕自身は今までrailsでサーバーサイドを実装している際はActiveRecordにお任せ状態でSQLに関する理解が全然だと改めて再認識です。
ですが今回の学習を通してphpでのCRUD処理(create、read、update、delete)についての底辺的な理解はすることができたのかなと思っています。