Laravel4でリレーション先のupdated_atでリレーション元をソートしたかった件
Postモデル hasMany Commentモデル
みたいなリレーションの時に、コメントがついていれば
最新コメント順でPostを並べ替えたいと思っていました。
要は、管理画面とかでコメント着いた順に並んでて
それにアクセスしたいな、って感じが要望です。
問題
単純な問題として、orderByは呼び出してるModelにしか効かない。
で、Webで検索しててよく出て来たのがリレーション先のものをソートするというやつ。
php - Laravel Eloquent sort by relation table column - Stack Overflow
そうじゃないんだよな、感が強い。
解決
ぱっと思いついた話で言うとタイトルの通りなんですが、
極端な話、今回の要望に関してはコメントがポストに付与した時に
ポストのupdated_atが更新されればOKです。
$comment = new Comment; $comment = Input::get('comment'); $comment->save(); $post = Post::find($id); $post->updated_at = $comment->updated_at; $post->save();
みたいなことをしようとしてましたw
まぁ、実際にコレをやるなら、PostモデルにaddCommentみたいな
メソッド作ってその中でやりそうですがw
で、こんなのやりたくないなーと思ったら神みたいな機能がLaravelについてました。
Laravelの機能 -> 親のタイムスタンプの更新
例えばCommentがPostに所属しているような場合、子供のモデルが変更された場合、所属している(belongsTo)親のタイムスタンプも変更されると便利です。Commentモデルが更新されたら、Postが持っているupdated_atタイムスタンプも自動的に更新したい場合などです。Eloquentでは簡単に実現できます。子供のモデルでtouchesプロパティーに、関連名を付け加えてください。
class Comment extends Eloquent { protected $touches = array('post'); public function post() { return $this->belongsTo('Post'); } }
これだけでOK!
これで、Commentが更新されるとそれを所有している
Postのupdated_atまで同時に更新されるようになりました。
マジ最高っす。
ちょっとリアルにBaseModelか何かに
親のupdated_atを更新するsaveメソッドを作るところだったw
あぶねー。
で、ここまで出来たら
public function index() { $posts = Post::orderBy('updated_at', 'desc')->get(); return View::make('admin.posts.index', compact('posts')); }
とやれば、コメント順に並びました。
めでたしめでたし。
おやすみなさい。