LaravelでYouTubeのようなコメント機能を作成する方法を解説します。
YouTubeのようなコメント機能とは、親コメントに返信したり子コメントに返信することができ、その流れに沿ってコメントが表示されるものです。
入れ子集合モデルとは?
今回のコメント機能は、「入れ子集合モデル」という概念を採用しています。むずかしい話は省略して簡単に図で表すと、次のようになります。
親が1つ目のコメント、子が親に対する返信、孫が子に対する返信です。
それぞれの子孫が中に入っていく仕組みで、子孫が増えるたびに両端の数値が大きくなっていきます。
そして、その数値の変動は他の親コメントや子コメントにも影響します。
例えば、右のオレンジ色の親コメントにもう1つ子コメントが入るとこのようになります。
この左右の数値をDBで管理する仕組みを作ります。
kalnoy/nestedsetの使い方
コメントが増えるたびに全てのコメントの左右の数値が変化するので大変です。
しかし、Laravelなら便利なパッケージがあるから大丈夫!というわけで、kalnoy/nestedsetの使い方を見ていきましょう。
1:kalnoy/nestedsetインストール
まずはターミナルでインストールします。
composer require kalnoy/nestedset
2:DBマイグレーション
nestedsetを使う場合は、マイグレーションファイルに下記を追加します。
public function up()
{
Schema::create('comments', function (Blueprint $table) {
$table->nestedSet();
});
}
public function down()
{
Schema::table('comments', function (Blueprint $table) {
$table->dropNestedSet();
});
}
これで、入れ子構造の左右の数値を管理するカラムと、親コメントのidを管理するカラムが追加されます。
ちなみにこの書き方はLaravel 5.5以上の場合です。
マイグレーションファイルには、他にも用途に合わせて必要なものを記入しましょう。
3:Commentモデルに追記
Commentモデルに下記を追記します。nestedsetを使うために必要です。
namespace App;
use Illuminate\Database\Eloquent\Model;
use Kalnoy\Nestedset\NodeTrait; //追記
class Comment extends Model
{
use NodeTrait; //追記
}
4:tinkerでtreeをfixする
これは、コメントが追加されるたびに数値がアップデートされる_lftカラムと_rgtカラムを管理するために必要な作業です。
これをせずにパッケージ特有のメソッドを使うと、Node must existsというエラーが出てしまいますのでご注意。
ターミナルを開き、tinkerを起動します。
$ php artisan tinker
次に、該当のモデルをfixTree()します。
>>> Comment::fixTree();
もしかしたら次のようなエラーがでるかもしれません。
PHP Fatal error: Class ‘Comment’ not found in Psy Shell code on line 1
その場合は、次のようにAppから打ってください。
>>> App\Comment::fixTree();
これで準備は万端です!
親コメントと子コメントの登録
kalnoy/nestedsetにはさまざまなメソッドが用意されています。
まずは親コメントの登録はLaravelのクエリビルダそのままです。
$comment = new Comment($attributes);
$comment->save();
子コメントの登録には、たくさんのメソッドが用意されています。
$child->appendToNode($parent)->save();
//または
$parent->appendNode($child);
//または
$child->parent()->associate($parent)->save();
// またはシンプルにLaravelのメソッドで
$child->parent_id = $parent->id;
$child->save();
これらは主にコメントが新規追加されたときにDBへ保存する方法として使えます。
他にも、既存のコメントを一番上の親に移動したり、任意のコメントの隣に移動する方法などがあります。詳しくはコチラ。
以上で〜す!