CakePHP3.8 と Laravel7.x の「書き方」の違い ~ORM周りその2~
今回はアクセサー周り
前: クエリの要約
そもそもクエリオブジェクトの返り値が別
1件取得
- CakePHP
Table クラスとは別に、Entity クラスがあり、それが返ってくる
// \App\Model\Entity\Users が返ってくる(Table クラスとは別)
$veteranHyphen = $usersTable->find('hyphen')->find('veteran')->first();
- Laravel
Model が Cake で言う Table, Entity の役割を持っている。
なので Model 自身のインスタンスが返ってくる。
// \App\Users が返ってくる
$veteranHyphen = Users::hyphen()->veteran()->first();
複数件取得
- CakePHP
Collection インスタンスが返ってくる。
Collection の要素には Entity インスタンスが入っている。
// \Cake\Collection\Collection
$veteranHyphenUsers = $usersTable->find('hyphen')->find('veteran')->all();
foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Model\Entity\Users
- Laravel
Collection インスタンスが返ってくる。
Collection の要素には Model インスタンスが入っている。
// \Illuminate\Database\Eloquent\Collection
$veteranHyphenUsers = Users::hyphen()->veteran()->get();
foreach ($veteranHyphenUsers as $veteranHyphenUser) // 中身は \App\Users
アクセサー
fetch したレコードの値を、参照するときにフォーマットすることができます。
DB からとってくるとき、ちょっとした整形が面倒くさいなぁ(CASE文大量など)といったときに便利です。
個人的には表示系をここに書いても良いんじゃないかなって思います。
(郵便番号 => 住所 とか 0,1 => 男女 とか)
- CakePHP
CakePHP では「仮想プロパティ」と呼ばれています。
Entity クラスの中で、「_get」+ {仮想プロパティ名}で定義できます。
namespace App\Model\Entity;
use Cake\ORM\Entity;
class User extends Entity
{
protected function _getFullName()
{
return $this->_properties['first_name'] . ' ' .
$this->_properties['last_name'];
}
}
// 参照する時
echo $user->full_name; // 横丁 小町
仮想プロパティはデータを保存するときには干渉しません。
- Laravel
Laravel では「アクセサ」と呼ばれています。
get + {プロパティ名} + Attribute で定義できます。
namespace App;
use Illuminate\Database\Eloquent\Model;
class User extends Model
{
/**
* ユーザーのフルネームを取得
*
* @return string
*/
public function getFullNameAttribute()
{
return $this->first_name . ' ' .
$this->last_name';
}
}
// 参照する時
echo $user->full_name; // 横丁 小町
保存時にも影響を与えたい時
入力した値を、自動的に保存時にフォーマットしてほしい時
- CakePHP3
ややこしいですが、CakePHP ではこれを アクセサ と呼びます。
値を参照するときにはもちろん、DBにデータを保存するときにも適用されます。
値を保存する時、値を参照する時、両方向に影響があるので、冪等性が担保されていなければなりません
namespace App\Model\Entity;
use Cake\ORM\Entity;
class Article extends Entity
{
protected function _getTitle($title)
{
return ucwords($title);
}
}
- Laravel
Laravel では、カスタムキャスト でこれを実現します。
CakePHPと違って、値を取得する時、保存する時で処理を分けられるので、冪等性をそんなに気にしなくても良いです。
キャストを定義して、
namespace App\Casts;
use Illuminate\Contracts\Database\Eloquent\CastsAttributes;
class Ucwords implements CastsAttributes
{
/**
* 指定された値をキャストする
*
* @param \Illuminate\Database\Eloquent\Model $model
* @param string $key
* @param mixed $value
* @param array $attributes
* @return array
*/
public function set($model, $key, $value, $attributes)
{
return ucwords($value);
}
}
Model で設定
namespace App;
use App\Casts\Ucwords;
use Illuminate\Database\Eloquent\Model;
class Article extends Model
{
/**
* キャストする属性
*
* @var array
*/
protected $casts = [
'title' => Ucwords::class,
];
}
# おわりに
フレームワークごとに単語を統一してほしい。