CakePHP で配列をモデルとして定義するための DataSource

CakePHP には外部のリソースを呼び出すための便利なフレームワークがある。DataSource を実装すれば、データベース以外のリソース(たとえばテキストファイルなど)がモデルとして利用できるようになる。

http://d.hatena.ne.jp/gapao/20090521/1242907727
を参考に、配列をモデルとして定義するための DataSource を作ってみた。下記の ArraySource を利用することでモデル内に定義した配列 $values の値を find() 関数で取り出せる。実用的とはいえないかもしれないが、作り込んでいったら面白いものができそうな気がする。

models/datasources/array_source.php:

<?php
class ArraySource extends DataSource
{
    function calculate(&$model, $func, $params = array())
    {
        return array('count' => true);
    }

    function listSources()
    {
        return $this->config['sources'];
    }

    function describe(&$model)
    {
        return $model->keys;
    }

    function read(&$model, $query = array(), $recursive = null)
    {
        if (isset($query['conditions'])) {
            $conditions = $query['conditions'];
        } else {
            $conditions = null;
        }
        $results = array();
        $values = $model->values;
        foreach ($values as $value) {
            if ($conditions && !Set::contains($value, $conditions)) {
                continue;
            }
            $results[] = array($model->name => $value);
        }
        if (!empty($query['fields']['count'])) {
            $source = array('count' => count($results));
            return array(array($model->name => $source));
        } else {
            $offset = $query['limit'] * ($query['page'] - 1);
            return array_slice($results, $offset, $query['limit']);
        }
    }
}

使用例


models/sex.php:

<?php
class Sex extends AppModel
{
    var $name = 'Sex';
    var $useDbConfig = 'array';
    var $useTable = 'sex';

    var $keys = array('id', 'name');
    var $values = array(
        array('id' => 1, 'name' => 'Male'),
        array('id' => 2, 'name' => 'Female')
    );
}

config/database.php:

<?php
class DATABASE_CONFIG
{
    var $array = array(
        'datasource' => 'array',
        'sources' => array('sex')
    );
}

あとはモデルを使うだけ。

<?php
 $data = $this->Sex->find('first', array('conditions' => array('id' => 2)));

モデルを増やす度に database.php の'sources'に追加してやる必要があるのが難点かな。