array_walk で コールバック関数に class内のメソッドを指定するには・・・

配列の全ての要素に関数を適用する array_walk はとても便利なのですが、クラス内のメソッドを指定できなくて少々はまりました。グーグルで調べてみると、同じ疑問を持った方はたくさんいるようで、参考になるページがたくさんありました。
array_walk の引数を配列とするのがポイントです。

class Test()
{
 function Test(){
  print_r($data);
  array_walk($data, array($this, "hoge"));
  print_r($data);

  return true;
 }                                                 
 function hoge(&$v,$k){
  $v = "#".$v."#";
 }
}

こんな感じで書いてみました。

お相撲オンラインとは関係ないのですが、MySQLでコネクションがタイムアウトする時間の確認方法をメモしておきます。

SHOW VARIABLES LIKE '%timeout%';

そして、表示される wait_timeout が通信がないとコネクションが切れてしまう時間のようです。
28800(秒) で、8時間ということのようです。

日付の入力で少しだけ悩みました。

date_create というカラムに現在の日時を入れようとして

$obj->date_create = "now()"; 

と、記述したのですが、、、どうやら「now()」という文字列だと思っているようで正しく入力されませんでした。そこで、DB_DataObject の日時の入力について少し調べてみました。
参考にしたサイトのとおりに

$obj->date_create = DB_DataObject_Cast::Sql('NOW()');

と書いてみたのですが、動きません。というか途中で止まってしまいます。。。
正解は

require_once 'DB/DataObject/Cast.php';
$obj->date_create = DB_DataObject_Cast::Sql('NOW()');

というように DataObject の Cast クラスを別に読み込む必要があります。
少しだけ悩んだので、同じ悩みを持った人の参考になればと思いメモがわりに書いておきます。

インクルードパスについて、少しだけ調べてみました。

パスの表記がメンドウな感じがしたので、include_path にクラスファイルのディレクトリを追加しようと思って少しだけ調べてみました。

[user@hoge class]$ pwd
/home/user/path_to/class
[user@hoge class]$ tree
.
|-- MySmarty.class.php
|-- ctrl
|   |-- HeyaCtrl.class.php
|   `-- PrefCtrl.class.php
|-- db
|   |-- Auth.php
|   |-- Td_pre_reg.php
|   |-- Tm_heya.php
|   |-- Tm_pref.php
|   `-- osumo.ini
`-- model
    `-- Heya.class.php

上記のようなファイル、ディレクトリ構成の場合、MySmarty.class.php に下記のように記述する事によってクラスまでのパスの表記を省略することができます。

set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__)."/model");
set_include_path(get_include_path() . PATH_SEPARATOR . dirname(__FILE__)."/ctrl");

ポイントは PATH_SEPARATOR という区切り文字の定数を使う事で Linux でも Windows でも動くようになっている所だと思います。それから、 get_include_path() なんていうインクルードパスを知るのに便利な関数があったのですね。今までは phpinfo() を使って調べたりしていたので、勉強になりました。


そのような設定をしたことで、クラス名の指定だけでインクルードできるようになりました。

require_once "HeyaCtrl.class.php";
require_once "PrefCtrl.class.php";

$oHeyaCtrl = new HeyaCtrl();
$oPrefCtrl = new PrefCtrl();

DB_DataObject を使ってみたい。

以前から雑誌で読んで気になっていた PEAR の DB_DataObject を使ってみたいと思います。本当に便利なのか確認してみて、便利だったら採用してみようかと思います。


まずはインストールです。PEARで配布されているので、インストールはとても簡単です。

# pear install DB_DataObject

とするだけです。これで、インストールは終了です。インストールの簡単さもPEARが利用される理由のひとつなのかもしれませんね。


インストールして、クラスを require するだけで使えるのが一般的ですが、 DB_DataObject はデーターベースの構造を解析して自動でクラスを作るようなので、事前にデーターベースへの接続情報を教えておく必要があるようです。
このページを参考にしながら、設定ファイルを書きました。
サンプルの database schema_location schema_location を変更しました。オプションの設定はイロイロできるようですが、とりあえず最小限の設定で動作確認してみます。

設定ファイル(dataObject.ini)

[DB_DataObject]
database    = mysql://USER:PASS@localhost/DBNAME
schema_location = /home/USER/path_to/class/db
class_location  = /home/USER/path_to/class/db
require_prefix  = DataObjects/
class_prefix    = DataObjects_
debug=0

この設定ファイルを、自動生成スクリプト (createTables.php)の引数に指定します。

$ php /usr/share/pear/DB/DataObject/createTables.php ./dataObject.ini

指定されたディレクトリ(class_location)にファイルが作成されているかを確認します。私は tm_heya というテーブルを作っておきましたので、 Tm_heya.php というファイルが作られているのを確認しました。


準備はOKなので、動作確認用のプログラムを書いてみます。

動作確認用のプログラム

require_once 'DB/DataObject.php';

// 準備
$config=parse_ini_file('/home/useer/path_to/dataObject.ini',TRUE);
$options=&PEAR::getStaticProperty("DB_DataObject","options");
$options=$config['DB_DataObject'];

// 簡単な検索 部屋IDが 1 のデータを取得
$rooms = DB_DataObject::Factory('tm_heya');
$rooms->get(1);

// 表示して確認
print_r($rooms);

次は部屋クラスで DataObject を利用してデーターをとってくるようにしたいと思います。

部屋表示の部分を作成しました。

ずいぶん時間があいてしまいました。その間、MVCについて少しだけ考えてみました。部屋クラスには部屋に関する情報だけを格納して、それをコントロールするクラスは別に作ってみようと思います。

部屋クラス(Heya.class.php)

<?php
class Heya {
    private $_heyaId;
    private $_heyaName;

    function __construct($inHeyaId,$inHeyaName) {
        if (!is_int($inHeyaId)){
            return null;
        }
        if (strlen($inHeyaName)===0) {
            return null;
        }
        $this->_heyaId = $inHeyaId;
        $this->_heyaName = $inHeyaName;
    }
    function __destruct() {
    }

    public function getHeyaId() {
        $this->_heyaId;
    }
    public function getHeyaName() {
        $this->_heyaName;
    }
}
?>

部屋のIDと名前を格納するだけのクラスです。

部屋コントロールクラス(HeyaCtrl.class.php)

<?php
class HeyaCtrl {
    private $_aryHeya;
    function __construct() {
        $this->_aryHeya = array();
    }
    function getHeyaList(){
        $this->_aryHeya[] = new Heya(1,"heya1");
        $this->_aryHeya[] = new Heya(2,"heya2");
        $this->_aryHeya[] = new Heya(3,"heya3");
        return $this->_aryHeya;
    }
}
?>

部屋クラスの配列を作成するクラスです。テストなので1から3まで固定で入れていますが、実際はデーターベースからとってきます。

テスト用プログラム(test.php)

require_once "class/model/Heya.class.php";
require_once "class/ctrl/HeyaCtrl.class.php";

$oHeyaCtrl = new HeyaCtrl();
print_r($oHeyaCtrl->getHeyaList());

うーん。イマイチしっくりとこないのですが、どこが変なのかもわかりません。

部屋表示の部分を作成しました。途中ですけど。

まず、データーベースに部屋マスターテーブルを作成します。
テーブル名の命名規則

  • 一文字目はタイプ
    • t:テーブル
    • v:ビュー
  • 二文字目はテーブルの種類
    • m:マスタ
    • d:データ

としました。
テーブルを作成して、テストデータをインサートしました。

CREATE TABLE tm_heya (
  heya_id   INT AUTO_INCREMENT,
  heya_name varchar(32) NOT NULL,
  date_create DATETIME,
  date_update DATETIME,
  date_delete DATETIME,

  PRIMARY KEY (heya_id)
)
;
INSERT INTO tm_heya 
  (heya_id,heya_name,date_create) 
  VALUES (1,'白虎部屋',now());
INSERT INTO tm_heya 
  (heya_id,heya_name,date_create) 
  VALUES (2,'玄武部屋',now());
INSERT INTO tm_heya 
  (heya_id,heya_name,date_create) 
  VALUES (3,'青龍部屋',now());
INSERT INTO tm_heya 
  (heya_id,heya_name,date_create) 
  VALUES (4,'朱雀部屋',now());


DATETIME で指定されている作成日、変更日、削除日はなんとなく後で使うかもしれない。かもと思い付けておきました。


続いて、部屋に関する情報を扱う部屋クラス(Heya.class.php)を作成しました。
とりあえず、必要と思われる部屋のリストを返すメソッドを仮の状態で実装してみます。

Heya.class.php

<?php

class Heya
{
    function getHeyaList(){
        return array('heya1','heya2','heya3');
    }

}
?>

Heya.class.php を利用する側のソース

<?php
require_once "../class/Heya.class.php";

$objHeya = new Heya();

print_r( $objHeya->getHeyaList() );

?>

これで、仮に実装した配列('heya1','heya2','heya3')が表示されるのを確認します。
本当はデーターベースに接続して、データをとってきて表示するのですが、本日は時間がないのでここまでとします。
次回は、部屋のリストを返したり、部屋IDから部屋の名前を返すような機能を追加したいと思います。