tjtjtjのメモ

自分のためのメモです

laravelのpivotいいなと思ったの巻

yii ActiveRecord の弱点

yii ActiveRecord は、many-manyの中間テーブルに属性を付けにくい弱点があります。たとえばこんな問題とか。
Accessing data in a join table with the related models
いまだにキレイな解決方法がない。と思う。ほんとにないの?

laravel は pivot で解決

一方、laravelならこう書く。

テーブル

CREATE  TABLE viewer (
  id INT NOT NULL PRIMARY KEY,
  name VARCHAR(45));
 
CREATE  TABLE movie (
  id INT NOT NULL PRIMARY KEY,
  title VARCHAR(45));
 
CREATE  TABLE viewer_watched_movie (
  id INT NOT NULL,                        -- <--- ここ見逃さない
  viewer_id INT NOT NULL,
  movie_id INT NOT NULL,
  liked TINYINT(1),
  PRIMARY KEY (id),
  CONSTRAINT fk_viewer_watched
    FOREIGN KEY (movie_id) REFERENCES movie (id),
  CONSTRAINT fk_movie_watched_by
    FOREIGN KEY (viewer_id) REFERENCES viewer (id));

viewerモデル

<?php
class Viewer extends Eloquent 
{
    public static $table = 'viewer';
    public function movies()
    {
        return $this->has_many_and_belongs_to('Movie', 'viewer_movies')
                    ->with('liked');          // <--- この with が大事
    }
} 

movieモデル

<?php
class Movie extends Eloquent
{
    public static $table = 'movie';
}

コントローラー

<?php
    $viewer = Viewer::find(1);
    foreach ($viewer->movies()->get() as $movie)
        echo $viewer->name 
            . ($movie->pivot->liked ? ' liked ' : ' didn’t like ')  // <--- pivot で with したカラムを参照できる
            . $movie->title ."<br>" ;

うん、素直に書けた。しかも冒頭挙げたページのproblemコードと酷似したコードで書けてる。

注意

pivot テーブルに created_at, updated_at がないと、こんなエラーがでる。

SQLSTATE[42S22]: Column not found: 1054 Unknown column 'viewer_movies.created_at' in 'field list'

そんなときは、 application/start.php にこれを書いておく。

Laravel\Database\Eloquent\Pivot::$timestamps = false;

pivot テーブルに created_at, updated_at を要求するのはお節介なような気が。