簡単に間違いコードを書くと
<?php use Illuminate\Database\Eloquent\Model as Eloquent; class Example extends Eloquent { protected $table = 'examples'; public function getPath() { return parse_url($this->url); } }
ここで url
というのは examples
テーブルの1カラムとする。
要は url
を単にURLではなくて、後ろのパスだけを取り出すメソッドが書きたいと思ったときにどうしたらいいの?というのを調べてた。
正直、上みたいに書いただけで簡単に動いてほしかったんだが、実際には以下のような例外が飛んだ。
[BadMethodCallException] Call to undefined method Illuminate\Database\Query\Builder::getPath()
まさか Query\Builder
からメソッドが呼び出されるとは思ってなくて驚いたんだが、Eloquentはすべてのattributeをあるテーブルのカラムと紐付けて取り出そうとしてしまうからのようで、上のサンプルコードのようなことをやりたかったら実際のテーブルには存在しない仮想的なカラムみたいなのを用意して実装してやる必要があると分かった。
なので上のコードを修正すると
<?php use Illuminate\Database\Eloquent\Model as Eloquent; class Example extends Eloquent { protected $table = 'examples'; protected $appends = ['path']; public function getPathAttribute() { return parse_url($this->url); } }
これで例えば $example
が Example
クラスのインスタンスで $example->url = 'http://example.com/hoge/fuga'
とすると、 $example->path
で '/hoge/fuga'
が取れるようになる。
一応公式ドキュメントにもこうやったらできることは書かれてるんだが、見つけるのが難しいところにある。
After creating the accessor, add the attribute name to the appends property on the model.
しかもサンプルコードはあるけど、これしか書いてない。あるカラムのaccessorを作ると、そのカラムを取り出すときに必ずaccessorに指定した処理が実行されて取り出される。これが上の例でいう getPathAttribute
なんだが、 path
というカラムがテーブルには存在しない場合 protected $appends = ['path'];
と書いて、仮想的なカラムを用意してねとある。これ、できればMutatorsの方に説明を書いてほしい…。
ググってたらこの質問に行き着いて、2013年に立てられたものなので使えるのか不安だったが、今の公式ドキュメントと照らし合わせるとなるほどって感じだった。
ちなみにこの仕組を使って私が書いたコードは ここ においてる。