Posted at

CakePHP3まとめ(Entityクラス編)

More than 5 years have passed since last update.

CakePHP3から新しく追加されるEntityクラスの簡単なまとめ


環境構築についてはCakePHP dev-3 + Windows7 + IIS + MySQLの環境構築を参照


  • 概要

  • ファイル名・クラス名

  • Getter と Setter

  • Eager loading と Lazy loading

  • その他


概要


  • 2.xまでのModelクラスは、3.xではTableクラスとEntityクラスに分離される

  • Tableクラスは主に下記のような機能を有する(2.xまでのModelクラスと機能的にはほぼ同じ)


    • データのCRUD

    • アソシエーション

    • バリデーション



  • Entityクラスはクエリ結果の各レコードにアクセスするためのクラス

namespace App\Model\Table;

use Cake\ORM\Table;
class ArticlesTable extends Table {

public function initialize(array $config) {
$this->belongsTo('Users');
$this->hasMany('Comments');
}

public function index() {
$query = $articles->find();
// クエリ結果のデータ型は配列ではなくオブジェクト
// フェッチで結果を取得
foreach ($query as $row) {
echo $row->title;
// or
echo $row->get('title');

// アソシエーションテーブルから取得
// UserEntityクラスは$row->userに相当
echo $row->user->name

foreach ($row->comments as $comment)
// CommentEntityクラスは$commentに相当
echo $comment->comment;
}
}
}


ファイル名・クラス名


  • ファイル名・クラス名ともに対応するTableクラスの単数形

  • 別のクラス名のEntityクラスを指定したい場合は、Tableクラスのinitializeメソッドで指定


Getter と Setter

namespace App\Model\Entity;

use Cake\ORM\Entity;

class Article extends Entity {
// フィールド名の先頭に'get'をつける
public function getTitle($title) {
return ucwords($title);
}

// フィールド名の先頭に'set'をつける
public function setTitle($title) {
// set(key, value)で$_properties配列にデータをセット
$this->set('slug', Inflector::slug($title));
return $title;
}

// 複数フィールドの値を加工して取得したい場合、メソッド名のget,setの後ろは自由
public function getFullName() {
// クエリで取得した値、もしくはset()でセットした値を$_propertiesから取得
return $this->_properties['first_name'] . ' ' .
$this->_properties['last_name'];
}
}


Eager loading と Lazy loading


  • Eager loading = 一括取得

  • Lazy loading = 都度取得

  • 両者のメリット・デメリットについては割愛

// Eager loading はアソシエーションによるデータの一括取得

// Lazy loading はEntityのGetterでアソシエーションテーブルのデータを取得

namespace App\Model\Entity;

use Cake\ORM\Entity;
use Cake\ORM\TableRegistry;

class Article extends Entity {

public function getComments() {
// Commentsテーブルクラスをインスタンス化
$comments = TableRegistry::get('Comments');
// Articleのidと紐づくCommentsデータを取得
return $comments->find('all')
->where(['article_id' => $this->id])
->all();
}

}

$article = $this->Articles->findById($id);
// $article->commentsで上記のgetCommentsを実行
foreach ($article->comments as $comment) {
echo $comment->body;
}


その他


  • 関数の再利用

  • バリデーションエラー

  • 仮想フィールドの設定

  • 隠しフィールの設定


関数の再利用


  • Traitを使用

// SoftDelete/Model/Entity/SoftDeleteTrait.php

namespace SoftDelete\Model\Entity;

trait SoftDeleteTrait {

public function softDelete() {
$this->set('deleted', true);
}
}

namespace App\Model\Entity;

use Cake\ORM\Entity;
use SoftDelete\Model\Entity\SoftDeleteTrait;

class Article extends Entity {
use SoftDeleteTrait;
}


バリデーションエラー

// すべて取得

$errors = $user->errors();

// フィールドを指定して取得
$errors = $user->errors('password');

// メッセージをセット
$user->errors('password', ['Password is required.']);


仮想フィールドの設定

Entityクラスの$_virtualプロパティにセット

namespace App\Model\Entity;

use Cake\ORM\Entity;
class User extends Entity {
protected $_virtual = ['full_name'];
}

...
// テーブルオブジェクトからセットする場合、virtualProperties()を使用
$user->virtualProperties(['full_name', 'is_admin']);


隠しフィールドの設定

Entityクラスの$_hiddenプロパティにセット

namespace App\Model\Entity;

use Cake\ORM\Entity;
class User extends Entity {
protected $_hidden = ['password'];
}

...
// テーブルオブジェクトからセットする場合、hiddenProperties()を使用
$user->hiddenProperties(['password', 'recovery_question']);