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テーブルuserfirst_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では値が返ってきます。しかし、toArraytoJsonでは入ってきません。

これは、パフォーマンスのために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入ってきますね。

By khino