NestedSets Model を使って FuelPHP 用コメントボックスパッケージを作った話post

こんにちは、こんばんは、昨日に引き続き FuelPHP Advent Calendar 2015 の 5 日目を担当する @sharkpp です。

今回は、一番最後に追加された NestedSets Model (日本語訳は NestedSets Model @ fuelphp.jp を参照) を使って DisqusFacebook Comments のようなものを貼り付けられる FuelPHP パッケージを作ってみた話をしようかと思います。

実際のパッケージは sharkpp/fuel-commentbox からダウンロードできます。

画面例

こんな画面になります。

NestedSets Model の使い方

使い方を、、、と言いつつ、実際は公式ドキュメントの NestedSets Model (日本語訳は NestedSets Model @ fuelphp.jp を参照) を参照すれば簡単に使えてしまうぐらいに整っていると思います。

基本的な機能は \Orm\Model_Nestedset からの派生としてモデルクラスを作れば特に考えることもなく用意されたものを使うことができます。

model/commentbox.php

namespace Commentbox;

class Model_Commentbox extends \Orm\Model_Nestedset
{
    protected static $_properties = array(

のような感じです。

oil generate のドキュメントを参照すると

$ php oil g model post title:varchar[50] body:text user_id:int --nestedset

と、実は、このような感じでスケルトンを作ることもできるため、ドキュメントを見ながら必要なフィールドを用意したりマイグレーションコードを用意したりする必要もなく、簡単に機能の実装に入ることができます。

multi tree に必要なフィールドを追加 · sharkpp/fuel-commentbox@a222248

 @@ -8,6 +8,7 @@ class Model_Commentbox extends \Orm\Model_Nestedset
        'id',
        'left_id',
        'right_id',
+       'tree_id',
        'comment_key',
        'user_id',
        'name',
 @@ -30,6 +31,9 @@ class Model_Commentbox extends \Orm\Model_Nestedset
    );

    protected static $_tree = array(
+       'left_field' => 'left_id',
+       'right_field' => 'right_id',
+       'tree_field' => 'tree_id',
        'title_field' => 'comment_key',
    );

と、このように、 tree_id を追加することで、

  • 唯一の親を持つツリーで管理する
  • 複数の親を持つツリーで管理する

か、を選べるようになっています。

コメントや掲示板、などは「複数の親を持つツリーで管理する」方が管理しやすいのではないかと自分は思います。

なので、追加するには先にルートを作っておいたほうが管理がしやすいので

classes/model/commentbox.php

    public static function get_parent($comment_key, $create = false)
    {
        $root = self::get_item($comment_key);
        if (null != $root ||
            ! $create)
        {
            return $root;
        }
        $root = new static();
        $root->comment_key = $comment_key;
        $root->user_id = -1;
        $root->name = '';
        $root->email = '';
        $root->website = '';
        $root->body = '';
        $root->save();
        return $root;
    }

のように、ルートノード取得時に、存在しなければルートノードを作成するメソッドを作り、扱いやすくしています。

子を追加するときは

                    }

                    $model->child($parent)->save();
                }

のような感じです。

ツリーの扱いとしては、例えば、

classes/commentbox.php

        $form = $this->fieldset();
        $root = Model_Commentbox::get_parent($this->comment_key);
        $tree = $root ? $root->dump_tree() : array();
        $user_page_empty

このように dump_tree() 関数を使うことで指定のアイテムを含めた下位のツリーを丸ごと取ることができます。

ドキュメントではこの他にも、ツリーを移動するためのメソッドが多数用意されています。

また、通常のモデルのように

classes/commentbox.php

                { // 投稿処理
                    // キーとなるハッシュを生成
                    for ($comment_key = \Str::random('alnum', 32);
                         Model_Commentbox::query()
                            ->where('comment_key', $comment_key)
                            ->count();
                         $comment_key = \Str::random('alnum', 32))
                        continue;

query() メソッドを使い個別に条件を追加して検索することもできます。

まとめ

  • oil コマンドでスケルトンを作ることができるので素早く実装に進むことができる。
  • 2種類の管理の仕方、「唯一の親を持つツリーで管理する」か「複数の親を持つツリーで管理する」があり、フィールドの有無でどちらか選ぶことができる。
  • 通常のモデルクラスと同じように条件を指定し検索することができる。
  • 多彩なツリーの移動メソッドがあらかじめ用意されている。

と、このような感じなのでサクサクと実装できるのではないかと思います。

ぜひ使って見てください。

以上、@sharkpp がお送りいたしました。

この文章は クリエイティブ・コモンズ 表示 4.0 国際 ライセンス、コードスニペットは MIT ライセンス の下に提供されています。

おまけ

コメントに張り付くアイコンの表示としては Gravatar が有名ですが、探してみるとマイナー気味ですがおもしろそーなサービスが他にもあったのでこのパッケージでは選んで使えるようにしてあります。

Gravatar

avatar example gravatar

こんな感じの表示になります。

その2は、RoboHash というサービスで、アイコンがいろんなタイプのロボットで表示され、背景も何種類か選ぶことができます。

avatar example robohash

こんな感じの表示になります。

その3は、Adorable Avatars! というサービスで、とぼけた?ような顔のアイコンを作ってくれます。 ただ、このサービスはアイコンの種類が少ないのか意外とアイコンが被ってしまうことが多い気がします。

avatar example adorable

こんな感じの表示になります。

Avatar というクラスを作りまとめて管理しているので他にも同じようなサービスが見つかったら簡単に追加できるようにしてあるので誰か使って欲しいなぁ、なんて。

参考


この投稿は FuelPHP Advent Calendar 20155日目の記事です。


   /   変更履歴  /   Permalink  /  このエントリーをはてなブックマークに追加 
 カテゴリ: ブログ  /   タグ: Advent Calendar, php, FuelPHP