LoginSignup
7
7

More than 5 years have passed since last update.

Phalcon Model::find の結果を Ginq にする方法

Last updated at Posted at 2015-05-01

※前提として、yield を使うので PHP5.5 以上であることが必要です

Phalcon の Resultset (Model::findの返却値) は多少の機能はありますが、ほぼORM機能を持ったクエリ結果カーソルの域を出ないので Ginq を使っています。

Resultset → Ginq

変換するには Ginq::fromLazy と yield を使います。

$rs = BlogEntries::find();
$entries = Ginq::fromLazy(function() use (&$rs) {
    foreach ($rs as $item) {
        yield $item;
    }
});

// 一日の中で PV 数が最上位のブログ記事を取得
$entries = $entries
    ->groupBy(['e'=>'e.getDate()'])
    ->select(function(GroupingGinq $g) {
        return $g->max(['e'=>'e.getPV()']);
    });

// 出力(これを View でやる)
foreach ($entries as $date => $entry) {
    echo $date . ":" . $entry->getTitle();
}

本来 Resultset はイテレータなので、そのまま Ginq::from(BlogEntries::find()) と書いても動くはずなのですが、なぜか要素がところどころ抜け落ちたりしました。
原因は不明ですが yield を使うことで極限まで抽象化できるので Ginq::fromLazy で解決できます。

find の返却値自体を Ginq にしちゃう

継承する中間クラスとして ModelBase クラスを定義し、find メソッドをオーバーライドします。

use Ginq\Ginq;
use Phalcon\Mvc\Model;

class ModelBase extends Model {

    /**
     * @param array $parameters
     * @return static[]|Ginq
     */
    public static function find($parameters = null) {
        $rs = parent::find($parameters);
        return Ginq::fromLazy(function() use (&$rs) {
            foreach ($rs as $item) {
                yield $item;
            }
        });
    }

} 

すべての Model で ModelBase を継承するだけで、find の結果が Ginq に統一されます。
思い切ったやりかたではありますが、中途半端に Ginq を使い分けるよりもコーディングポリシーを統一できるので、私は実際のプロダクトを一気にリファクタリングしました。

注意が必要なところ

いまのところ、この方法を使う上で以下の点に気を付ける必要があります。

count($entries) ではなく $entries->count()

count($entries) では正しく数量が計算できませんでした。
Ginq の count メソッドを使って $entries->count() と記述する必要があります。

Volt テンプレートエンジンの for 文の特殊変数が機能しない

Volt のループ構文ではループコンテキストという特殊変数が使えますが、このうち

  • loop.first
  • loop.last
  • loop.length

などは使用できませんでした。もちろん $entries->toList() でプリミティブの配列にすれば使えます。

{% for entry in entries.toList() %}
    {{ loop.last }}
{% endfor %}

このへんは責任が持てませんので、各自で検証してください。


暇があったらページネータの GinqAdapter を書こうと思ってます。

7
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
7