Laravelのマニュアルは、ほどよい説明で気に入っています。長い説明でポイントがつかめなく困ることはそうありません。理解には何回か読むことも必要ですが。
しかし、ときには掲載されるサンプルコードがよく使用されるような例ではなく、逆に混乱してしまうことあります。
例えば、Eloquent Mutatorsの以下のサンプルコード。
namespace App; use Illuminate\Database\Eloquent\Model; class User extends Model { public function getFirstNameAttribute($value) { return ucfirst($value); } }
getFirstNameAttribute
を上のように定義すると、
$user = App\User::find(1); $firstName = $user->first_name;
のように使えると。
ucfirst
の関数は、文字列の最初の文字を大文字にする関数なので、もとのDBテーブルuser
のfirst_name
の項目の値、つまり$user->first_name
が変換されるのだな、とは推測できます。
しかし、元の項目名もfirst_name
であるし、変換した値にアクセスするのもfirst_name
で、同じ変数名でややこしく思いませんか?
テンプレートで使用するなら、こちらの方が混乱せずに管理性が高いです。
{{ ucfirst($user->first_name) }}
アクセッサーの便利さの説明には、違うサンプルコードを使用した方が良いと思います。
例えば、
public function getNameAttribute() { return $this->first_name.' '.$this->last_name; }
この例では、name
という項目はDBテーブルに存在しないという仮定です。
$user = App\User::find(1); echo $user->name;
$user->first_name
が「Kenji」で、$user->last_name
が「Hino」なら、「Kenji Hino」が表示されます。つまり、モデルに新規の属性を作成するのは簡単ということが、このサンプルからわかります。
注意してもらいたいのは、関数名にパラメータがないことです。最初の例では、$value
がありました。そのパラメータは、関数名で指定される(この場合、FisrtName => first_name)変数の値をとってくるという意味ですね。
さて、この新規の属性name
、他のDBから入ってくる属性と違って生成するオブジェクトに自動的にふくまれるというわけではありません。
$ php artisan tinker Psy Shell v0.6.1 (PHP 5.6.13 — cli) by Justin Hileman >>> use App\User; => false >>> $user = User::find(1); => App\User {#847 id: 1, created_at: "2015-04-21 11:56:46", updated_at: "2016-01-29 14:17:54", first_name: "Kenji", last_name: "Hino", } >>> $user->name; => "Kenji Hino" >>> $user->toArray() => [ "id" => 1, "created_at" => "2015-04-21 11:56:46", "updated_at" => "2016-01-29 14:17:54", "first_name" => "Kenji", "last_name" => "Hino", ] >>>
最初のオブジェクトの属性としては、name
は入ってきませんね。しかし、$user->name
では値が返ってきます。しかし、toArray
やtoJson
では入ってきません。
これは、パフォーマンスのためにLaravelの意図的な仕様です。毎回毎回必要なものでもありませんね。
しかし、必要なときにはどうしたらよいのでしょう?
class User extends Model { protected $appends = ['name']; ...
と$appends
に新規属性を指定すると、
>>> $user->toArray() => [ "id" => 1, "created_at" => "2015-04-21 11:56:46", "updated_at" => "2016-01-29 14:17:54", "first_name" => "Kenji", "last_name" => "Hino", "name" => "Kenji Hino", ] >>>
name
入ってきますね。