🔥

CodeIgniter4のCodeIgniter\Model (2)Entityクラスの利用

2021/12/13に公開

CodeIgniter Advent Calendar 2021

CodeIgniter4の CodeIgniter\Model でEntityクラスを使ってみましょう。

目次

Entityクラスとは?

Entityクラスは、1つのテーブルのレコードを表すクラスです。POPOではありません。

テーブルのカラムを表す(マジック)プロパティを持ち、様々なデータをキャストするハンドラーを内蔵しています。

Entityクラスには、そのオブジェクトのビジネスロジックを実装するためのメソッドを追加します。

Entityクラスは自分自身を永続化する方法については何も知りません。永続化はモデルクラスが行います。

Entityの作成

CodeIgniter\Entity\Entity を継承したEntityクラスを作成します。

app/Entitles/News.php

<?php

namespace App\Entities;

use CodeIgniter\Entity\Entity;

class News extends Entity
{
}

これだけで動作します。

Entityの利用

データの検索

モデルクラスの $returnType にEntityクラス名の指定します。

--- a/app/Models/NewsModel.php
+++ b/app/Models/NewsModel.php
@@ -2,6 +2,7 @@
 
 namespace App\Models;
 
+use App\Entities\News;
 use CodeIgniter\Model;
 
 class NewsModel extends Model
@@ -10,6 +11,8 @@ class NewsModel extends Model
 
     protected $allowedFields = ['title', 'slug', 'body'];
 
+    protected $returnType = News::class;
+
     public function getNews($slug = false)
     {
         if ($slug === false) {

これで、検索結果が配列から、Entityクラスのインスタンスに変わります。

$newsItem = $newsModel->find(1);
object(App\Entities\News)#78 (8) {
  ["datamap":protected]=>
  array(0) {
  }
  ["dates":protected]=>
  array(3) {
    [0]=>
    string(10) "created_at"
    [1]=>
    string(10) "updated_at"
    [2]=>
    string(10) "deleted_at"
  }
  ["casts":protected]=>
  array(0) {
  }
  ["castHandlers":protected]=>
  array(0) {
  }
  ["defaultCastHandlers":"CodeIgniter\Entity\Entity":private]=>
  array(14) {
    ["array"]=>
    string(33) "CodeIgniter\Entity\Cast\ArrayCast"
    ["bool"]=>
    string(35) "CodeIgniter\Entity\Cast\BooleanCast"
    ["boolean"]=>
    string(35) "CodeIgniter\Entity\Cast\BooleanCast"
    ["csv"]=>
    string(31) "CodeIgniter\Entity\Cast\CSVCast"
    ["datetime"]=>
    string(36) "CodeIgniter\Entity\Cast\DatetimeCast"
    ["double"]=>
    string(33) "CodeIgniter\Entity\Cast\FloatCast"
    ["float"]=>
    string(33) "CodeIgniter\Entity\Cast\FloatCast"
    ["int"]=>
    string(35) "CodeIgniter\Entity\Cast\IntegerCast"
    ["integer"]=>
    string(35) "CodeIgniter\Entity\Cast\IntegerCast"
    ["json"]=>
    string(32) "CodeIgniter\Entity\Cast\JsonCast"
    ["object"]=>
    string(34) "CodeIgniter\Entity\Cast\ObjectCast"
    ["string"]=>
    string(34) "CodeIgniter\Entity\Cast\StringCast"
    ["timestamp"]=>
    string(37) "CodeIgniter\Entity\Cast\TimestampCast"
    ["uri"]=>
    string(31) "CodeIgniter\Entity\Cast\URICast"
  }
  ["attributes":protected]=>
  array(4) {
    ["id"]=>
    string(1) "1"
    ["title"]=>
    string(13) "Elvis sighted"
    ["slug"]=>
    string(13) "elvis-sighted"
    ["body"]=>
    string(95) "Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app."
  }
  ["original":protected]=>
  array(4) {
    ["id"]=>
    string(1) "1"
    ["title"]=>
    string(13) "Elvis sighted"
    ["slug"]=>
    string(13) "elvis-sighted"
    ["body"]=>
    string(95) "Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app."
  }
  ["_cast":"CodeIgniter\Entity\Entity":private]=>
  bool(true)
}

$newsItem->titletitle カラムの値を取得できます。

複数レコードの場合は、オブジェクトの配列が返ります。

$newsItems = $newsModel->find([1, 2]);
array(2) {
  [0]=>
  object(App\Entities\News)#79 (8) {
    ["datamap":protected]=>
    array(0) {
    }
    ["dates":protected]=>
    array(3) {
      [0]=>
      string(10) "created_at"
      [1]=>
      string(10) "updated_at"
      [2]=>
      string(10) "deleted_at"
    }
    ["casts":protected]=>
    array(0) {
    }
    ["castHandlers":protected]=>
    array(0) {
    }
    ["defaultCastHandlers":"CodeIgniter\Entity\Entity":private]=>
    array(14) {
      ["array"]=>
      string(33) "CodeIgniter\Entity\Cast\ArrayCast"
      ["bool"]=>
      string(35) "CodeIgniter\Entity\Cast\BooleanCast"
      ["boolean"]=>
      string(35) "CodeIgniter\Entity\Cast\BooleanCast"
      ["csv"]=>
      string(31) "CodeIgniter\Entity\Cast\CSVCast"
      ["datetime"]=>
      string(36) "CodeIgniter\Entity\Cast\DatetimeCast"
      ["double"]=>
      string(33) "CodeIgniter\Entity\Cast\FloatCast"
      ["float"]=>
      string(33) "CodeIgniter\Entity\Cast\FloatCast"
      ["int"]=>
      string(35) "CodeIgniter\Entity\Cast\IntegerCast"
      ["integer"]=>
      string(35) "CodeIgniter\Entity\Cast\IntegerCast"
      ["json"]=>
      string(32) "CodeIgniter\Entity\Cast\JsonCast"
      ["object"]=>
      string(34) "CodeIgniter\Entity\Cast\ObjectCast"
      ["string"]=>
      string(34) "CodeIgniter\Entity\Cast\StringCast"
      ["timestamp"]=>
      string(37) "CodeIgniter\Entity\Cast\TimestampCast"
      ["uri"]=>
      string(31) "CodeIgniter\Entity\Cast\URICast"
    }
    ["attributes":protected]=>
    array(4) {
      ["id"]=>
      string(1) "1"
      ["title"]=>
      string(13) "Elvis sighted"
      ["slug"]=>
      string(13) "elvis-sighted"
      ["body"]=>
      string(95) "Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app."
    }
    ["original":protected]=>
    array(4) {
      ["id"]=>
      string(1) "1"
      ["title"]=>
      string(13) "Elvis sighted"
      ["slug"]=>
      string(13) "elvis-sighted"
      ["body"]=>
      string(95) "Elvis was sighted at the Podunk internet cafe. It looked like he was writing a CodeIgniter app."
    }
    ["_cast":"CodeIgniter\Entity\Entity":private]=>
    bool(true)
  }
  [1]=>
  object(App\Entities\News)#80 (8) {
    ["datamap":protected]=>
    array(0) {
    }
    ["dates":protected]=>
    array(3) {
      [0]=>
      string(10) "created_at"
      [1]=>
      string(10) "updated_at"
      [2]=>
      string(10) "deleted_at"
    }
    ["casts":protected]=>
    array(0) {
    }
    ["castHandlers":protected]=>
    array(0) {
    }
    ["defaultCastHandlers":"CodeIgniter\Entity\Entity":private]=>
    array(14) {
      ["array"]=>
      string(33) "CodeIgniter\Entity\Cast\ArrayCast"
      ["bool"]=>
      string(35) "CodeIgniter\Entity\Cast\BooleanCast"
      ["boolean"]=>
      string(35) "CodeIgniter\Entity\Cast\BooleanCast"
      ["csv"]=>
      string(31) "CodeIgniter\Entity\Cast\CSVCast"
      ["datetime"]=>
      string(36) "CodeIgniter\Entity\Cast\DatetimeCast"
      ["double"]=>
      string(33) "CodeIgniter\Entity\Cast\FloatCast"
      ["float"]=>
      string(33) "CodeIgniter\Entity\Cast\FloatCast"
      ["int"]=>
      string(35) "CodeIgniter\Entity\Cast\IntegerCast"
      ["integer"]=>
      string(35) "CodeIgniter\Entity\Cast\IntegerCast"
      ["json"]=>
      string(32) "CodeIgniter\Entity\Cast\JsonCast"
      ["object"]=>
      string(34) "CodeIgniter\Entity\Cast\ObjectCast"
      ["string"]=>
      string(34) "CodeIgniter\Entity\Cast\StringCast"
      ["timestamp"]=>
      string(37) "CodeIgniter\Entity\Cast\TimestampCast"
      ["uri"]=>
      string(31) "CodeIgniter\Entity\Cast\URICast"
    }
    ["attributes":protected]=>
    array(4) {
      ["id"]=>
      string(1) "2"
      ["title"]=>
      string(16) "Say it isn't so!"
      ["slug"]=>
      string(14) "say-it-isnt-so"
      ["body"]=>
      string(64) "Scientists conclude that some programmers have a sense of humor."
    }
    ["original":protected]=>
    array(4) {
      ["id"]=>
      string(1) "2"
      ["title"]=>
      string(16) "Say it isn't so!"
      ["slug"]=>
      string(14) "say-it-isnt-so"
      ["body"]=>
      string(64) "Scientists conclude that some programmers have a sense of humor."
    }
    ["_cast":"CodeIgniter\Entity\Entity":private]=>
    bool(true)
  }
}

データの保存

新規にレコードを保存したい場合は、以下のようなコードになります。

$model = model(NewsModel::class);

$news = new \App\Entities\News([
    'title' => $this->request->getPost('title'),
    'slug'  => url_title($this->request->getPost('title'), '-', true),
    'body'  => $this->request->getPost('body'),
]);
$model->save($news);

CodeIgniter4のCodeIgniter\Model (3)モデル内でのバリデーション
へ続く。

参考

Discussion