別段大した事もないのだが、愚直にPHPでdatabaseのmodelを書いたので、反面教師を書きつけておく。
以下のcodeの欠点は、
- PDO (PHP Data Object) を使ってゐない。PDOを優先して使ってゐないのはbugだと思ふ。
- prepared statement (placeholder) を使ってゐない。此れは明確にbugである。防げる筈のSQL injection攻撃をまるで防いでゐない。
- error messageが直書きされてゐる。国際化する時面倒に成る。
- 繰り返し多過ぎ。好いORMを使えば回避できる点も有る。
「教育的配慮」により既存のORMは許可されてゐなかった。あとは、「教育的配慮」に沿って進めた結果、書き直しが面倒だったので上記bugを放おっておいた。此ういった「教育的配慮」は、教育を道徳的に考へたり経済領域で考へたりしたときの、悪い面がよく出てゐる。
cf. Java, C# からMySQLへの接続に関する発展的な補足。RAII, class, ORM - c4se記:さっちゃんですよ☆ http://c4se.hatenablog.com/entry/2013/02/24/042848
DBConnection.php
<?php // create database storedb default character set utf8 default collate utf8_general_ci; // use storedb; // c:\xampp\mysql\bin\mysqldump.exe -u root -p storedb > storedb.sql class DBConnection { static $connection; static function init() { if (self::$connection) return self::$connection; self::$connection = mysqli_connect('localhost', 'store', 'admin'); if (! self::$connection) return false; mysqli_set_charset(self::$connection, 'utf-8'); if (! mysqli_select_db(self::$connection, 'storedb')) return false; return self::$connection; } } DBConnection::init();
User.php
<?php class User { /** * @param {int} $id * @return {User} */ static function find($id) { $result = mysqli_query(DBConnection::$connection, "select * from user where id = $id"); if (! $result) return null; $row = mysqli_fetch_array($result); if ($row) return self::from_row($row); else return null; } /** * @param {string} $where * @return {User[]} */ static function find_all($where='') { $query = 'select * from user'; if ($where) $query .= " where $where"; $result = mysqli_query(DBConnection::$connection, $query); $users = array(); if (! $result) return $users; while ($row = mysqli_fetch_array($result)) $users[] = self::from_row($row); return $users; } /** * @param {string} $name * @return {User} */ static function find_by_name($name) { $result = mysqli_query(DBConnection::$connection, "select * from user where name = '$name'"); if (! $result) return null; $row = mysqli_fetch_array($result); if ($row) return self::from_row($row); else return null; } /** * @param {mixed} $row * @return {User} */ static function from_row($row) { $user = new self; if ($row) { $user->id = $row['id'] - 0; $user->name = $row['name']; $user->password = $row['password']; $user->auth = $row['auth'] - 0; } return $user; } /** @type {int} */ var $id = 0; /** @type {string} */ var $name = ''; /** @type {string} */ var $password = ''; /** @type {int} */ var $auth = 1; /** * @return {User} */ function save() { if ($this->id === 0 and $this->validate() !== true) return $this; if ($this->id === 0) $this->insert(); else $this->update(); return $this; } /** * @return {User} */ function delete() { mysqli_query(DBConnection::$connection, "delete from user where id = $this->id"); $this->id = 0; return $this; } /** * @return {boolean|string} */ function validate() { if ($this->name === '') // not null return 'ユーザー名は必須です。'; if (count($this->name) > 20) return 'ユーザー名が長過ぎます。'; if (count(self::find_all("id != $this->id and name = '$this->name'"))) // unique return 'そのユーザー名は既に存在します。'; if ($this->password === '') // not null return 'パスワードは必須です。'; if (count($this->password) > 20) return 'パスワードが長過ぎます。'; return true; } /** * @param {string} $password * @return {boolean} */ function is_correct_password($password) { return $this->password === $password; } /** */ private function insert() { mysqli_query(DBConnection::$connection, "insert into user(name, password, auth) values ('$this->name', '$this->password', $this->auth)"); $result = mysqli_query(DBConnection::$connection, 'select count(last_insert_id()) from user'); $row = mysqli_fetch_array($result); $this->id = $row[0] - 0; } /** */ private function update() { mysqli_query(DBConnection::$connection, "update user set name = '$this->name', password = '$this->password', auth = $this->auth where id = $this->id"); } }