c4se記:さっちゃんですよ☆

.。oO(さっちゃんですよヾ(〃l _ l)ノ゙☆)

.。oO(此のblogは、主に音樂考察Programming に分類されますよ。ヾ(〃l _ l)ノ゙♬♪♡)

音樂は SoundCloud に公開中です。

考察は現在は主に Scrapbox で公表中です。

Programming は GitHub で開發中です。

愚直にPHPでdatabaseのmodelを書いたので、反面教師を書きつけておく

別段大した事もないのだが、愚直に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");
  }
}