文系Webエンジニアの技術メモとたまに旅のメモ

未経験文系エンジニアとして働いてます。アウトプットとして簡単に技術メモを残していきます。たまに旅関係のも趣味で残していこうと思ってます。

【CakePHP3/loadmodel】Controllerで別名Tableの関数を呼ぶ方法

今回は、CakePHP3系でControllerから別Tableに記述した関数を呼ぶ方法を記していきます。
パターン1:loadmodel
パターン2:TableRegistry
パターン3:TableLocator

1.今回やりたい事

UsersContoller.phpからDepartmentsTable.phpに記述した関数を呼びたい。

2.Tableに関数の記述

DepartmentsTable.phpに任意の関数を追加します。
今回は、Departmentsからレコードを1件取得する関数を追加します。

DepartmentsTable.php
<?php
    public function getOneDepartment($department_id)
    {
        $department = $this->find()
            ->where(['id' => $department_id])      
            ->first();
        return $department;
    }
?>

3.Controllerにloadmodelの記述

UsersController.phpでDepartmentsTable.phpで追加した「getOneDepartment」関数を呼び出します。
任意のfunction内で下記記述をします。
今回はこの様な書き方になります。

UsersController.php
<?php
    $id = 1;
    $this->loadmodel('Departments');
    $department = $this->Users->getOneDepartment($id);

    $this->{Table名}->{Tableに記述した関数名}
?>

4.取得内容の確認

実際に関数が呼ばれ想定の値が取得できているか確認をしましょう。

UsersController.phpで$departmentをdebugして見ましょう。
下記記述を行いURLにアクセスします。

loadmodel無しの場合

UsersController.php
<?php
    $id = 1;
    $department = $this->Users->getOneDepartment($id);
    debug($users);
    die();
?>

下記エラーが表示されます。
「Call to a member function getOneDepartment() on bool」

関数が正常に呼び出せなかった場合に表示されるエラーです。

次にloadmodelを使用した後に関数を呼んで見ましょう。

UsersController.php
<?php
    $id = 1;
    // Departmentsを使用可能にします。
    $this->loadmodel('Departments');
    $department = $this->Users->getOneDepartment($id);
    debug($users);
    die();
?>

この様に、取得できて入れば成功です。

f:id:igarashi44:20200705225245p:plain

5.CakePHP3.6以降は、非推奨になったTableRegistryでも取得は可能

CakePHP3.6からTableRegistryは非推奨となりました。
3.6 移行ガイド - 3.8

下記記述で取得はできますが、TableRegistryを使わなければならない理由がない限りは、使用は控えた方が良さそうですね。

UsersController.php
<?php
    use Cake\ORM\TableRegistry;
 // function内で記述
    $this->Departments = TableRegistry::get('Departments');
    $department = $this->Departments->getOneDepartment(1);
?>

6.TableLocatorを使用して取得も可能

3.6系の移行ガイドを見ると、TableLocatorを使用して取得もできるようになりました。

UsersController.php
<?php
    $this->Departments = $this->getTableLocator()->get('Departments');
    $department = $this->Departments->getOneDepartment(1);
?>

7.取得方法は複数ありましが、loadmodelを使用するのが良いのでは?

3パターン紹介しましたが、個人的にはloadmodelを使用するのが良いかと思います。
1:loadmodel
2:TableRegistry
3:TableLocator

複数のfunctionでloadmodelを使用する際は、initializeを継承して書いてしまうのが楽かもしれません。

UsersController.php
<?php
    public function initialize()
    {
        parent::initialize();
        $this->loadmodel('Departments');
    }
    public function index()
    {
        $department = $this->Departments->getOneDepartment($id);
    }
?>

loadmodelを使うのが楽かなと思っていますが、他の方が良いという意見がありましたらコメント等にお願いします。
明確な理由があってloadmodelを使用している訳ではないので。