PHP
CakePHP

CakePHP3まとめ(Entityクラス編)

More than 3 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']);