LoginSignup
1
0

More than 1 year has passed since last update.

[CakePHP] 型情報付きでエンティティを取得する

Posted at

前回の型情報付きでテーブルオブジェクトを取得するの続き

課題

通常CakePHPではエンティティオブジェクトをQuery/ResultSetからfirst()等で取得する。
ResultSetからforeachで取るような場合は@var書くしかないして、fisrt()のときくらいはEntityInterfaceではなく具体的な型情報がほしい。

解決策

ジェネリクスを使用した回避策がこれ。
例としてByIdにしてあるけど条件は好みで適当に調整。

use Cake\Utility\Inflector;

/**
 * @template T
 * @param class-string<T> $fullEntityName 完全修飾エンティティ名
 * @param int $id
 * @return T of \Cake\ORM\Entity
 */
public static function getEntityById(string $fullEntityName, int $id, array $contain = [])
{
    if (!preg_match('#(\w+)$#', $fullEntityName, $matches)) {
        throw new \DomainException();
    }
    $tableName = Inflector::pluralize($matches[1]);

    return TableRegistry::getTableLocator()->get($tableName)->findById($id)->contain($contain)->first();
}

使用例

$article = getEntityById('\App\Model\Entity\Article', 3);

または

$article = getEntityById(\App\Model\Entity\Article::class, 3);

または

use \App\Model\Entity\Article;
$article = getEntityById(Article::class, 3);

いずれも\App\Model\Entity\Article型としてIDEに認識される

留意事項

テーブルモデルと同様、ジェネリクスを使う都合上、単にgetEntityById('Articles', ~~)と書くことはできず、完全修飾名で指定する必要がある。
使用例の真ん中の書き方であればIDE補完付きで書くことができるのでそれほど手間ではない。

また配列形式であれば以下のように書けるはずだが、現時点ではPhpStormは対応しておらず、今後対応予定とのこと。(公式ブログのWI-60894 Support parameter wrapping)

use Cake\Utility\Inflector;

/**
 * @template T
 * @param class-string<T> $fullEntityName 完全修飾エンティティ名
 * @param string $named
 * @return array<int, T>
 */
public static function getEntitiesByName(string $fullEntityName, string $name, array $contain = [])
{
    if (!preg_match('#(\w+)$#', $fullEntityName, $matches)) {
        throw new \DomainException();
    }
    $tableName = Inflector::pluralize($matches[1]);

    return TableRegistry::getTableLocator()->get($tableName)->findByName($name)->contain($contain)->toArray();
}
1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0