# Zend_Dojo_Data: dojo.data エンベロープ

Dojo には、データを扱うウィジェットのデータを抽象化するための dojo.data コンポーネントが存在します。 このコンポーネントの持つ機能は、 データストアのアタッチ、identifier フィールド (そしてオプションで label フィールド) に関連するメタデータの提供、 問い合わせやソート用の API、 データストアからのレコードの取得などがあります。

dojo.data は、よく XmlHttpRequest と組み合わせて用いられます。 動的なデータをサーバから取得するためにです。 この基本的な仕組みは、QueryReadStore を拡張して URL とクエリ情報を指定するようにします。 サーバ側からは、データを次のような JSON 形式で返します。

    {
        identifier: '<name>',
        <label: '<label>',>
        items: [
            { name: '...', label: '...', someKey: '...' },
            ...
        ]
    }

`Zend_Dojo_Data` は、 このような構造をプログラムで作成したりそれを操作したり、 配列や JSON にシリアライズしたりといった機能のシンプルなインターフェイスを提供します。

## Zend_Dojo_Data の使用法

もっともシンプルな使用法は、dojo.data に各アイテムの identifier フィールドの名前とアイテムの内容 (データ) を渡すことです。 コンストラクタか、あるいは設定用メソッドで渡します。

### コンストラクタでの Zend_Dojo_Data の初期化

    $data = new Zend_Dojo_Data('id', $items);

### 設定用メソッドでの Zend_Dojo_Data の初期化

    $data = new Zend_Dojo_Data();
    $data->setIdentifier('id')
         ->addItems($items);

アイテムをひとつずつ追加したり複数一括で追加したりするには、それぞれ `addItem()` および `addItems()` を使用します。

### Zend_Dojo_Data へのデータの追加

    $data = new Zend_Dojo_Data($identifier, $items);
    $data->addItem($someItem);

    $data->addItems($someMoreItems);

### 常に identifier を使うこと!

すべての dojo.data データストアは、identifier カラムがメタデータに存在することを必須としています。 `Zend_Dojo_Data` でもそれは同じです。 identifier のないアイテムを追加しようとすると、 例外が発生します。

個々のアイテムは、次のいずれかとなります。

- 連想配列

- `toArray()` メソッドを実装したオブジェクト

- その他のオブジェクト (get_object_vars() でシリアライズされます)

これらのアイテムのコレクションをアタッチするには `addItems()` あるいは `setItems()` (既存のアイテムはすべて消去されます) を使用します。 これを使用するときには、引数をひとつ指定します。

- 配列

- `Traversable` インターフェイスを実装したオブジェクト (このインターフェイスは `Iterator` と `ArrayAccess` を含んでいます)。

アイテムの label として働くフィールドを指定したい場合は `setLabel()` をコールします。

### Zend_Dojo_Data での label フィールドの指定

    $data->setLabel('name');

最後に、`Zend_Dojo_Data` のアイテムを dojo.data JSON 配列から読み込むには `fromJson()` メソッドを使用します。

### JSON からの Zend_Dojo_Data の作成

    $data->fromJson($json);

## コンテナへのメタデータの追加

Dojo コンポーネントの中には、 dojo.data の中に追加のメタデータを必要とするものもあります。 たとえば `dojox.grid.Grid` は、データを動的に `dojox.data.QueryReadStore` から取得することができます。 ページ移動を正しく行うには、返されるデータの中に `numRows` というキーのデータ (中身はクエリが返す行の数) が必要となります。 これによりグリッドが、サーバ側へのリクエストをいつ送ったらいいのか、 そしていつリクエストが不要になるのか (つまり最終ページに達するのがいつなのか) を知ることができるようになります。 このテクニックを使用すると、大規模なデータセットをグリッドに表示させる際に データ全体をいちどに取得する必要はなくなります。

`Zend_Dojo_Data` では、 このようなプロパティをオブジェクトのメタデータとして設定することができます。 以下の使用例をご覧ください。

    // "numRows" を 100 に設定します
    $data->setMetadata('numRows', 100);

    // 複数の項目をいちどに設定します
    $data->setMetadata(array(
        'numRows' => 100,
        'sort'    => 'name',
    ));

    // メタデータの値を調べます
    $numRows = $data->getMetadata('numRows');

    // すべてのメタデータを取得します
    $metadata = $data->getMetadata();

    // メタデータを削除します
    $data->clearMetadata('numRows');

    // すべてのメタデータを削除します
    $data->clearMetadata();

## 高度な使用法

シリアライズ可能なデータコンテナとしての働きだけではなく、 `Zend_Dojo_Data` にはデータを様々な方法で操作したり 読み込んだりする機能もあります。

`Zend_Dojo_Data` は、インターフェイス `ArrayAccess`、`Iterator` および `Countable` を実装しています。 そのため、データコレクションをまるで配列であるかのように使用することができます。

すべてのアイテムは、その identifier フィールドを用いて参照します。 identifier は一意でなければならないので、 この値を使用すればレコードを特定できるのです。 参照する方法には、`getItem()` メソッドを使用するものと配列表記を使用するものの 2 通りがあります。

    // getItem() を使用します
    $item = $data->getItem('foo');

    // あるいは配列表記を使用します
    $item = $data['foo'];

identifier がわかれば、それを使用してアイテムを取得したり、 あるいは更新したり削除したり作成したり調べたりすることができます。

    // アイテムの更新あるいは作成
    $data['foo'] = array('title' => 'Foo', 'email' => 'foo@foo.com');

    // アイテムの削除
    unset($data['foo']);

    // アイテムの確認
    if (isset($data[foo])) {
    }

すべてのアイテムをループ処理することもできます。 内部的には、すべてのアイテムは配列として格納されています。

    foreach ($data as $item) {
        echo $item['title'] . ': ' . $item['description'] . "\n";
    }

count で、アイテムの総数を調べることも可能です。

    echo count($data), " items found!";

また、このクラスは `__toString()` を実装しているので、 JSON への変換は単に echo するか文字列にキャストするだけで可能です。

    echo $data; // JSON 文字列として echo

    $json = (string) $data; // 文字列へのキャスト == JSON へのキャスト

### 使用可能なメソッド

上で説明したインターフェイスを実装するのに必要なメソッドに加えて、 次のメソッドが使用可能です。

- `setItems($items)`: 複数のアイテムを一度に設定し、 それまでそのオブジェクトに設定されていたアイテムをすべて上書きします。 `$items` は、配列あるいは `Traversable` オブジェクトでなければなりません。

- `setItem($item, $id = null)`: 個別のアイテムを設定し、オプションで明示的に identifier を渡します。 それまでにコレクション内にあったアイテムは上書きされます。 アイテムとして指定できるのは、連想配列、あるいは `toArray()` を実装したオブジェクト、 あるいは public プロパティを持つそれ以外のオブジェクトです。

- `addItem($item, $id = null)`: 個別のアイテムを追加し、オプションで明示的に identifier を渡します。 コレクション内にそのアイテムが既に存在する場合は例外が発生します。 アイテムとして指定できるのは、連想配列、あるいは `toArray()` を実装したオブジェクト、 あるいは public プロパティを持つそれ以外のオブジェクトです。

- `addItems($items)`: 複数のアイテムを一度に追加し、 それを任意のアイテムに追記します。新しく追加するアイテムの中に、 コレクション内の既存のアイテムの identifier と一致するものがある場合は例外が発生します。 `$items` は、配列あるいは `Traversable` オブジェクトでなければなりません。

- `getItems()`: すべてのアイテムを、配列の配列形式で取得します。

- `hasItem($id)`: 指定した identifier のアイテムがコレクション内に存在するかどうかを調べます。

- `getItem($id)`: 指定した identifier のアイテムをコレクションから取得します。 返されるアイテムは連想配列となります。 マッチするアイテムがない場合は、null 値を返します。

- `removeItem($id)`: 指定した identifier のアイテムをコレクションから削除します。

- `clearItems()`: コレクション内のすべてのアイテムを消去します。

- `setIdentifier($identifier)`: コレクション内の各アイテムの一意な識別子 (identifier) をあらわすフィールドの名前を設定します。

- `getIdentifier()`: identifier フィールドの名前を取得します。

- `setLabel($label)`: アイテムの表示用ラベルとして使用するフィールドの名前を設定します。

- `getLabel()`: ラベル用フィールドの名前を取得します。

- `toArray()`: オブジェクトを配列にキャストします。 配列には、最低限 'identifier' と 'items' というキーが含まれ、オブジェクトにラベルフィールドが設定されている場合は 'label' というキーも含まれます。

- `toJson()`: オブジェクトを JSON 表現にキャストします。