jeremyharris / cakephp-lazyload
CakePHP ORM 关联式懒加载器
Requires
- php: >=8.1
- cakephp/orm: ^5.0
Requires (Dev)
- cakephp/cakephp: ^5.0
- phpunit/phpunit: ^10
README
CakePHP ORM 懒加载插件
这是一个为 CakePHP ORM 实体设计的关联式懒加载器。它允许您通过访问属性来懒加载关联数据,而不必使用 contain()
(贪婪加载器)。
安装
要求
- CakePHP ORM(或完整框架)5.x
- sloth
$ composer require jeremyharris/cakephp-lazyload
对于 CakePHP ORM 的旧版本,请查看此库的旧版本。
使用方法
如果您有一个基本实体,添加特质以在整个实体上启用懒加载。或者,将其附加到单个实体上,仅在该实体上启用懒加载
src/Model/Entity/User.php
<?php namespace App\Model\Entity; use Cake\ORM\Entity; use JeremyHarris\LazyLoad\ORM\LazyLoadEntityTrait; class User extends Entity { use LazyLoadEntityTrait; }
现在可以从实体中懒加载 Users 表的关联了!
示例
假设我们的基本实体具有 LazyLoadEntityTrait
特质
Brewery hasMany Beers
Programmer belongsToMany Beers
使用懒加载器,我们只需要实体
<?php // get an entity, don't worry about contain $programmer = $this->Programmers->get(1);
当访问关联属性时(就像数据已经贪婪加载一样),关联数据将自动加载。
<?php // beers is lazy loaded foreach ($programmer->beers as $beer) { // brewery is lazy loaded onto $beer echo $programmer->name . ' drinks beer ' . $beer->name . ' from ' . $beer->brewery->name; }
使用 contain 与懒加载器结合使用
懒加载器不会覆盖由贪婪加载器(contain()
)生成的结果。您仍然可以编写复杂的 contain 条件并利用懒加载器。
<?php $programmer = $this->Programmers->get(1, [ 'contain' => [ 'Beers' ] ]); // beers is loaded via the eager loader $programmer->beers; // brewery is lazy loaded onto $beer[0] $programmer->beers[0]->brewery;
实体方法支持
具有懒加载器特质的实体支持使用 Cake ORM 提供的不同属性访问方法进行懒加载
- 获取器:
$programmer->get('beers')
,$programmer->beers
- 存在:
$programmer->has('beers')
- 取消设置:
$programmer->unsetProperty('beers')
通过 Entity::unsetProperty()
取消设置属性时,将防止在将来对该实体进行懒加载,因为它以类似于典型实体的方式尊重状态。如果您希望重新填充关联,可以使用 ORM 提供的 Table::loadInto
<?php $programmer = $this->Programmers->get(1); // beers is lazy loaded $programmer->beers; // remove beers from the entity $programmer->unsetProperty('beers'); // this now returns false $programmer->has('beers'); // if we want access to beers again, we can manually load it $programmer = $this->Programmers->loadInto($programmer, ['Beers']);
测试
有时在测试中,我们创建的实体可能没有表。当访问一个不存在的属性时,LazyLoad 特质将尝试加载表以获取关联数据,如果表不存在,则会引发错误。为防止这种情况,您可以在实体中重写 _repository()
<?php namespace App\Model\Entity; use Cake\ORM\Entity; use Exception; use JeremyHarris\LazyLoad\ORM\LazyLoadEntityTrait; class User extends Entity { use LazyLoadEntityTrait { _repository as _loadRepository; } protected function _repository() { try { $repository = $this->_loadRepository(); } catch (Exception $e) { return false; } return $repository; } }
默认情况下,LazyLoad 特质会抛出 TableRegistry::get()
弹出的任何错误。
插件
如果测试没有表的插件实体,请确保重写 _repository()
方法以返回 插件 的表。
注意事项
- Contain: 这不是
contain()
的替代品,后者可以编写复杂的查询以指定要包含的数据。懒加载器遵守您在表上定义关联时设置的关联条件,但除此之外,它会获取所有关联数据。 - 速度: 以这种方式进行懒加载并不一定提高速度。事实上,在某些情况下,它可能会降低速度,例如在循环中遍历懒加载关联的实体(为每个项目创建单个 SQL 查询而不是使用连接或 ORM)。此插件旨在作为启动项目的辅助工具。
- 数据初始化:懒加载器需要您的结果集进行初始化,以便提供懒加载功能。
特别感谢@lorenzo在插件最初发布前对其进行审查!