[CakePHP]簡単DataSourceの作り方

  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 40.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 41.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 42.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 43.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 44.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 45.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 46.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 47.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 48.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 49.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 50.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 51.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 56.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 57.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 58.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 59.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 60.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 61.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 62.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 63.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 64.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 65.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 66.
  • warning: date() [function.date]: It is not safe to rely on the system's timezone settings. You are *required* to use the date.timezone setting or the date_default_timezone_set() function. In case you used any of those methods and you are still getting this warning, you most likely misspelled the timezone identifier. We selected 'America/Denver' for 'MDT/-6.0/DST' instead in /home/lyniqne/public_html/planetcakephp.org/drupal/sites/all/modules/token/token_node.inc on line 67.

http://bakery.cakephp.org/articles/view/csv-datasource-for-reading-your-csv-files

を参考にしました。

ここではあるディレクトリを参照するデータソースを作ります。

とりあえずapp/config/database.phpに以下を追加

<?php
var $dir = array(
            'datasource' => 'dir',
      'root' => '/path/to'
            ); 
?>

ファイルを作成します

データソースのクラスファイルはapp/models/datasources以下に_sourceを付けた名前で保存し、

DataSourceクラスを継承して作ります。

app/models/datasources/dir_source.php

<?php
class DirSource extends DataSource
{
    var $fields = array(
            'name' => array('type' => 'string',
                            'null' => null,
                            'default' => null,
                            'length' => 255,
                            'key' => 'primary'),
            'size' => array('type' => 'integer',
                            'null' => null,
                            'default' => null,
                            'length' => 10));
    
    function __construct($config = null, $autoConnect = true)
    {
        parent::__construct($config);
        
        if ($autoConnect) {
            return $this->connect();
        } else {
            return true;
        }
    }
    
    function connect()
    {
        $config = $this->config;
        
        uses('Folder');
        
        $this->connection =& new Folder($config['root']);
        if ($this->connection) {
            return true;
        } else {
            return false;
        }
    }
    
    function close()
    {
        $this->connection->close();
    }
    
    function listSources()
    {
       list($folders, $files) = $this->connection->read();
       return $folders;
    }
    
    function describe(&$model)
    {
        $cache = parent::describe($model);
        if ($cache != null) {
            return $cache;
        }
        $fields = $this->fields;
        $this->__cacheDescription($this->fullTableName($model, false), $fields);
        return $fields;
    }
    
    function read(&$model, $query = array(), $recursive = null)
    {
        uses('File');
        
        $path = Folder::addPathElement($this->connection->pwd(), $model->table);
        $root = new Folder($path);
        list($folders, $files) = $root->read();
        
        $results = array();
        foreach ($files as $name) {
            $path = Folder::addPathElement($root->pwd(), $name);
            $file = new File($path);
            $result['name'] = $name;
            $result['size'] = $file->size();
            $results[] = array($model->name => $result);
        }
        
        if (!empty($query['fields']['count'])) {
            $source['count'] = count($results);
            return array(array($model->name => $source));
        }
        
        $results = array_slice($results, $query['limit'] * ($query['page'] - 1), $query['limit']);
        return $results;
    }
    
    function fullTableName(&$model, $quote = true)
    {
        if (is_object($model)) {
            $table = $model->tablePrefix . $model->table;
        } else if (isset($this->config['prefix'])) {
            $table = $this->config['prefix'] . strval($model);
        } else {
            $table = strval($model);
        }
        
        if ($quote) {
            return $this->name($table);
        }
        return $table;
    }
    
    function calculate(&$model, $func, $params = array())
    {
        return array('count' => true);
    }
}
?>

以下各メソッドについて

コンストラクタ

$configにはdatabase.phpに設定した変数の内容が入ってきます。

データベースの場合はdriverやpassword等がありますが、自分が作るデータソースの内容により、

基本何でも設定できるので、この値を元にデータソースを初期化します。

$autoConnectはわかりませんwおそらく名前通りでしょう。

なお、親コンストラクタは$configを$this->configに保存します。

connect、close

扱う対象データとの接続、切断等を行います。

ここではconnetメソッドでディレクトリをopenし、closeメソッドでcloseしています。

Folderオブジェクトの場合は明示的にcloseする必要な無いですが、

closeメソッドが存在しないとエラーが出ます。

listSources

データソースの一覧を配列で返します。

要はデータベースで言うところのテーブル一覧です。

ここでは$configの$rootに設定したパスに存在するディレクトリ一覧を返しています。

この中にモデルの$useTable($table)に一致するものが無いと、Missing Database Tableになります。

describe

スキーマというかフィールドの情報を返します。

データベースと同じ形式で持っておくとbakeする時とか色々便利かと思います。

とりあえずファイル名をプライマリキーにしておきました。

read

モデルのfindからお呼ばれします。

要は好きなデータを返してやれば良いです。

ここではモデルのテーブル(ディレクトリ)の中にあるファイル一覧とファイルサイズを返します。

返す時はいわゆる['モデル名']['カラム名'] => 値の形で返してやるようにします。

最後に現在ページ分を切り出しています。

ここでは省略しましたが、$queryには検索条件やらPaginatorのパラメータやらが入ってきているので、適宜ソートや抽出処理を追加すると良いです。

fullTableName

DboSouceからのコピペです。

これが無いとbakeできませんでしたので。

calculate

これで無茶苦茶はまりましたorz

というかたぶん根本的な解決にはなっていないような。。

find('count')した時に呼ばれます。

DBの場合はCOUNT文のSQLとかを返しているようなのですが、

ここではそうはいかないので、countの時はcount配列を挿入してます。

戻り値はreadに渡される$query['fields']の中に入ってくるので、

countがあったらカウント値だけ入れて戻す感じです。

Bakeできます

とりあえずこれだけあればBakeできます。

$ cake bake model

Welcome to CakePHP v1.2.3.8166 Console
---------------------------------------------------------------
App : app
Path: /www/cake/app
---------------------------------------------------------------
---------------------------------------------------------------
Bake Model
Path: /www/cake/app/models/
---------------------------------------------------------------
Use Database Config: (default/dir)
[default] > dir
Possible Models based on your current database:
1. hoge
2. hogehoge
3. hogehogehoge
Enter a number from the list above, type in the name of another model, or 'q' to exit
[q] > 1

Given your model named 'Basic', Cake would expect a database table named basics
Do you want to use this table? (y/n)
[y] > n
What is the name of the table (enter "null" to use NO table)?
> hoge
Would you like to supply validation criteria for the fields in your model? (y/n)
[y] > n
What is the primaryKey?
[name] >
Would you like to define model associations (hasMany, hasOne, belongsTo, etc.)? (y/n)
[y] > n

---------------------------------------------------------------
The following Model will be created:
---------------------------------------------------------------
Name:       Hoge
DB Config:  dir
Primary Key: name
Associations:
---------------------------------------------------------------
Look okay? (y/n)
[y] >

Baking model class for Hoge...

Creating file /www/cake/app/models/hoge.php
Wrote /www/cake/app/models/hoge.php
SimpleTest is not installed.  Do you want to bake unit test files anyway? (y/n)
[y] > n

出来上がったモデル

<?php
class Hoge extends AppModel {

	var $name = 'Hoge';
	var $useDbConfig = 'dir';
	var $useTable = 'hoge';
	var $primaryKey = 'name';

}
?>

もちろんコントローラ、ビューのbakeもできます。

indexはページング処理を含めちゃんと動くはずです(ソートは省略してますが)。

データソース楽しい

便利とかいう以前に無茶苦茶楽しい。

特にbakeと組み合わせるとヤバイです。

これはしばらく仕事してる場合じゃないな…