PHP クラスの覚書

PHP クラスの覚書

<?php
/*
http://www.tohoho-web.com/php/class.html
*/

//class の使い方
// 1.定義

class A {
  //定数の定義
  const PI = 3.14;
  //プロパティの宣言
  public $a;//どこからでもアクセスできる
  protected $b;//クラス自身、継承したクラス、親クラスからアクセスできる
  private $c;//そのクラス自身だけ参照可

  //インスタンス化すると暗黙に最初に呼ばれる
  function __construct ($a, $b, $c) {
    $this->a = $a; // 4.
    $this->b = $b;
    $this->c = $c;
  }

  //以下メソッドの定義...
  public function dispA () {
    echo self::PI. "\n";//定数の参照
    echo $this-> a; 
  }

  //final 継承されたものからの上書きを禁止
  final public function dispB () {
    echo $this-> b;
  }

  //インスタンス化しない状態で呼び出す
  static function dispC () {
    echo "func dispC";
//    echo $this-> c;
  }
}

// クラスの継承
class B extends A { // 親となる A を継承することを意味する

  function __construct ($a, $b, $c) {
    parent::__construct ($a, $b, $c);//明示的に継承元を呼び出す必要あり
  }

  //オブジェクト消滅時に呼び出される
  function __destruct () {
    parent::__destruct ();//継承元へも呼び出す
  }

  public function dispA () {
    echo $this-> a; //継承もとのメソッドのオーバーライド dsipB は禁止状態
  }
}


$b = new B ('a', 'b', 'c');// 3.インスタンス化する

$_a = clone $b; // オブジェクトの複製
$_c = $_a; //参照元が同じなので同等
B::dispC ();

//______________________________
//抽象クラス (サブクラスDが必ず定義しなくてはならない抽象メソッドを定義します)

abstract class C {
  abstract public function dispA ();
  abstract public function dispB ();
  public function dispC () { echo $this-> a; }
}

class D extends C {
  public function dispA () { echo $this-> a; }
  public function dispB () { echo $this-> b; }
}

//new C (); #単独でこれはできない
new D (); #OK

//______________________________
//インタフェース (実装クラスが必ず定義しなくてはならないメソッドを定義します)
interface E {
  public function dispA ($arg);//変数も指定すること
  public function dispB ($arg, $arg2);//引数の名前は適当でよいが数は合わせる必要あり
  public function dispC ();
}

class F implements E {
  public function dispA ($arg) { echo $this-> a; }
  public function dispB ($arg0, $arg1) { echo $this-> b; }
  public function dispC () { echo $this-> c; }
}

new F ();

//______________________________
//タイプヒンティング
class A { }
class B {
  public function test (A $arg) {
    ;
  }
}

//______________________________
//オートローディング
spl_autoload_register (function ($class_name) {
  include("{$class_name}.php");//G.php が読み込まれる
});

$g = new G();
?>

MySQLPHP を経由して、JavaScript にデータを送るための

<?php

//_____________________________
//MySQL Driver PDO クラス生成
interface DBDriver { //このクラスを継承させること
  public function send ($sql, $prm, $type, $multi);
}


//_____
class MySQL implements DBDriver {
  
  const DBNAME = '**********';  //DB名前
  const HOST   = 'localhost'; //DBホスト名
  const USER   = 'root';      //DB使用ユーザー名
  const PASS   = '***********';  //DB暗証番号
  //MySQLの設定値(php5.3 では定数として配列が使えない)
  private static $opt = array (
    PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, //error時のthrowが有効になる
    PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, //fetch 時の取得方法
    PDO::ATTR_EMULATE_PREPARES=>false,
    PDO::ATTR_PERSISTENT=> true, //接続を維持する
    PDO::MYSQL_ATTR_USE_BUFFERED_QUERY=> true //バッファを利用する
  );
 
  //_____
  protected $pdo = null;//PDOの実態

  //_____
  //初回定義時
  function __construct ($name= self::DBNAME, $host= self::HOST, $user= self::USER, $pass= self::PASS, $opt= array ()) {
    try {
      $option = $opt + self::$opt; //$opt は上書きされない
      $db = sprintf ('mysql:dbname=%s; host=%s; charset=utf8mb4', $name, $host);
      $this->pdo = new PDO ($db, $user, $pass, $option);
    }
    catch (PDOException $err) {//MySQL でエラー発生
      if (DEBUG) {
        header ('Content-Type: text/plain; charset=UTF-8', true, 403);
        echo $err;
      }
      die ();
    }
    catch (Exception $ex) {
      die ();
    } 
  }
  //_____
  //送信
  public function send ($sql, $prm = null, $type = PDO::FETCH_ASSOC, $multi = true) {
    $PDO = $this->pdo;
    try {
      switch (true) {
      case (null === $prm) ://パラメータ無し
        switch ($type) {
        case 'count' : case 'COUNT' : case NULL: case FALSE :
          return $PDO-> exec ($sql);//戻り値は作用した行数
        case 'id' : case 'ID' :
          $hd = $PDO-> query ($sql);
          return $hd ? $PDO-> lastInsertId (): $hd; //結局失敗するとfalse
        default :
          $hd = $PDO-> query ($sql);
          return $multi 
            ? $hd-> fetchAll ($type)
            : $hd-> fetch ($type)
          ;
        }

      default ://パラメータ有り
        if (array_values ($prm) !== $prm)
          $prm = self::addColon ($prm);//連想配列ならコロンを付加

        $hd = $PDO-> prepare ($sql);
        $rst = $hd-> execute ($prm);
        //戻り値が無い場合
        switch ($type) {
          case 'id': case 'ID' : return $rst ? $PDO-> lastInsertId (): $rst;
          case 'count' : case 'COUNT' : return $rst ? $hd-> rowCount (): $rst;//失敗は false
          case NULL : case FALSE : return $rst;
        default:
          return $multi
            ? $hd-> fetchAll ($type)
            : $hd-> fetch ($type)
          ;
        }
      }
    }
    catch (PDOException $err) {
      if (DEBUG) {
        header ('Content-Type: text/plain; charset=UTF-8', true, 403);
        echo $sql."\n";
        echo Array_Deployment($prm)."\n";
        echo $err-> getMessage ()."\n";
      }
      die();
    }
  }


  //_____
  private function addColon ($ary) {
    $rst = array ();
    foreach ($ary as $key => $val) $rst[':'.$key] = $val;
    return $rst;
  }


}

//_____________________________

interface DBTableController {
//  public function __construct ($pdo, $tb_name, $id_name);
  public function select ($QUERY);
  public function update ($RECODE);
  public function insert ($RECODE);
  public function delete ($ID_LIST);
}

class TableRecorder implements DBTableController {
  private $pdo;
  private $tb_name;
  private $id_name;
  //_____

  function __construct (DBDriver $pdo, $tb_name, $id_name = 'ID') {
    $this->pdo = $pdo;
    $this->tb_name = $tb_name;
    $this->id_name = $id_name;
  }

  //_____



  public function select ($QUERY, $ARG= null, $LIMIT= 0, $OFFSET= 0) {
    $order = array ('%%TABLE%%', '%%ID%%');
    $replace = array ($this->tb_name, $this->id_name);
    $query = str_replace ($order, $replace, $QUERY);

    if ($LIMIT) {
      $query .= ' LIMIT '. strval ($LIMIT);
      //offsetの生成
      if ($OFFSET)
        $query .= ' OFFSET '. strval ($OFFSET);
    }
    $rst = $this->pdo->send ($query, $ARG);

    return array (
      'data'=> $rst,
      'query'=> $query,
      'arg'=> $ARG,
      'error'=> false === $rst
    );
  }

  public function length ($QUERY= 'SELECT COUNT(*) FROM %%TABLE%%', $ARG= null) {
    $rst = $this->pdo->send ($QUERY, $ARG, PDO::FETCH_COLUMN, false);
    return array (
      'length'=> $rst,
      'query'=> $QUERY,
      'arg'=> $ARG,
      'error'=> false === $rst
    );
  }


  public function getOffsetID ($ID, $OFFSET= 0) {
    $query = ($OFFSET > 0)
    ? 'SELECT %2$s FROM %1$s WHERE %2$s>=:ID ORDER BY %2$s LIMIT 1 OFFSET %3$d'
    : 'SELECT %2$s FROM %1$s WHERE %2$s<=:ID ORDER BY %2$s DESC LIMIT 1 OFFSET %3$d';
    $query = sprintf ($query, $this->tb_name, $this->id_name, abs ($OFFSET));

    $rst = $this->pdo->send ($query, array ('ID'=> $ID), PDO::FETCH_COLUMN, false);
    return array (
      'id'=> $rst,
      'query'=> $QUERY,
      'offset'=> abs ($ARG),
      'error'=> false === $rst
    );
  }

  //_____
  //レコードの更新
  public function update ($ID, $RECODE = array ()) {
    $query = sprintf (
      'UPDATE %1$s SET %4$s WHERE %2$s=%3$s',
      $this->tb_name,
      $this->id_name,
      $ID,
      self::convNameList ($RECODE) 
    );
    $rst = $this->pdo->send ($query, $RECODE, null);

    return array (
      'id'=> $RECODE[$this->id_name],
      'query'=> $query,
      'recode'=> $RECODE,
      'error'=> false === $rst
    );
  }


  //_____
  //レコードの挿入
  public function insert ($RECODE) {
    $names = array_keys ($RECODE);
    $query = sprintf (
      'INSERT INTO %s (%s) VALUES(:%s)',
      $this->tb_name,
      implode (',', $names),
      implode (',:', $names)
    );
    $id = count ($RECODE)
      ? $this->pdo->send ($query, $RECODE, 'id')
      : false
    ;
    return array (
      'id'=> $id,
      'query'=> $query,
      'error'=> false === $id
    );
  }


  //_____
  //指定されたIDを削除する
  public function delete ($ID_LIST = array ()) {
    $query = sprintf (
      'DELETE FROM %s WHERE %s IN (%s)',
      $this->tb_name, $this->id_name,
      implode (',', $ID_LIST)//IDを整数限定にしている?
    );
    $cnt = count ($ID_LIST)
      ? $this->pdo->send ($query, null, 'count')
      : false;
    return array (
      'count'=> $cnt,
      'query'=> $query,
      'id'=> $ID_LIST,
      'error'=> false === $cnt
    );
  }


//_____

  public function convNameList ($ary) {
    $rst = array ();
    foreach ($ary as $key => $v) $rst[] = sprintf ('%1$s=:%1$s', $key);
    return implode (',', $rst);
  }
}

/*
header ('Content-type: text/plain; charset=UTF-8');
header ('X-Content-Type-Options: nosniff');

$mysql = new MySQL();
$a = new TableRecorder ($mysql, "shain", "ID");
var_dump($a->select ('SELECT * FROM %%TABLE%% WHERE ?<%%ID%%', array (4)));

*/

?>