daycry / relations
CodeIgniter 4 的实体关系
Requires
- php: ^8.1
- daycry/schemas: ^1.0
Requires (Dev)
- codeigniter/coding-standard: *
- codeigniter/phpstan-codeigniter: ^1.3
- codeigniter4/devkit: *
- codeigniter4/framework: ^4
- ergebnis/composer-normalize: *
- fakerphp/faker: ^1.9
- friendsofphp/php-cs-fixer: ^3
- icanhazstring/composer-unused: *
- mikey179/vfsstream: ^1.6
- nexusphp/tachycardia: *
- phpstan/phpstan-strict-rules: ^1.5
This package is auto-updated.
Last update: 2024-09-28 14:17:33 UTC
README
Codeigniter 4 的 Relations
快速开始
- 使用 Composer 安装:
> composer require daycry/relations
- 将特性添加到您的模型中:
use \Daycry\Relations\Traits\ModelTrait
- 加载关系:
$users = $userModel->with('groups')->findAll();
- 将特性添加到您的实体中:
use \Daycry\Relations\Traits\EntityTrait
- 加载关系:
foreach ($user->groups as $group)
(详见底部示例)
安装
通过 Composer 轻松安装,利用 CodeIgniter 4 的自动加载功能,并保持最新状态
> composer require daycry/relations
或者,通过下载源文件并将目录添加到 app/Config/Autoload.php 中手动安装。
配置(可选)
可以通过扩展其配置文件来更改库的默认行为。将 examples/Relations.php 复制到 app/Config/ 并遵循注释中的说明。如果 app/Config 中没有找到配置文件,库将使用其自己的。
模式
库的所有功能都依赖于生成的数据库模式。该模式来自 Daycry\Schemas,可以根据您的需求进行调整(参见 Schemas 配置文件)。如果您想使用自动生成的模式,您的数据库将遵循外键和 pivot/join 表的传统命名模式;有关详细信息,请参阅 Daycry\Schemas。
使用
关系加载由添加到相应元素的特性处理。
急切/模型
ModelTrait 通过扩展默认的模型 find*
方法并将关系注入到返回的结果中来为您的模型添加关系加载。由于这发生在模型级别,因此可以在批量中预先加载相关项目(“急切加载”)。
将特性添加到您的模型中
use \Daycry\Relations\Traits\ModelTrait
可以通过添加 $with
属性到您的模型来请求相关项目
protected $with = 'groups'; // or protected $with = ['groups', 'permissions'];
... 或者通过使用模型的 with()
方法即时请求
$users = $userModel->with('groups')->findAll(); foreach ($users as $userEntity) { echo "User {$user->name} has " . count($user->groups) . " groups."; ...
如你所见,相关项目被直接添加到框架模型返回的相应对象(或数组)中。
懒惰/实体
EntityTrait 通过为每个项目添加魔法 __get()
和 __call()
方法来扩展单个项目的加载关系。由于这发生在每个项目上,因此可以即时检索或更新相关项目(“懒惰加载”)。
将特性和其必要的属性添加到您的实体中
use \Daycry\Relations\Traits\EntityTrait protected $table = 'users'; protected $primaryKey = 'id';
相关项目作为虚拟属性可用
$user = $userModel->find(1); foreach ($user->groups as $group) { echo $group->name; }
... 并且也可以直接从实体更新
$user->addGroup(3); if ($user->hasGroups([1, 3])) { echo 'allowed!'; } $user->setGroups([]);
可用的魔法方法动词是:has
、set
、add
和 remove
,并且仅适用于“多对多”关系。
返回的项目
Schemas 将尝试将您的数据库表关联回其模型,如果成功,Relations 将使用每个表的模型来查找相关项目。这保持了模型返回类型、事件和其他方面的连贯性。除了返回类型之外,Relations 还将调整单例关系的相关项目。
// User hasMany Widgets $user = $userModel->with('widgets')->find($userId); echo "User {$user->name} has " . count($user->widgets) . " widgets."; // ... but a Widget belongsTo one User $widget = $widgetModel->with('users')->find($widgetId); echo $widget->name . " belongs to " . $widget->user->name;
嵌套
ModelTrait 支持嵌套关系调用,但这些都可能非常消耗资源,因此可以通过更改配置中的 $allowNesting
来禁用。启用嵌套后,任何相关项目也将加载其相关项目(但不会无限加载)
/* Define your models */ class UserModel { use \Daycry\Relations\Traits\ModelTrait; protected $table = 'users'; protected $with = 'widgets'; ... /* Then in your controller */ $groups = $groupModel->whereIn('id', $groupIds)->with('users')->findAll(); foreach ($groups as $group) { echo "<h1>{$group->name}</h1>"; foreach ($group->users as $user) { echo "{$user->name} is a {$user->role} with " . count($user->widgets) . " widgets."; } }
软删除
如果您的目标关系对应于使用软删除的CodeIgniter模型,那么您可以在array $withDeletedRelations
属性中包含表名以包括软删除项。这对于紧密关系特别有用,比如当一个项目belongsTo
另一个已经被软删除的项目时。$withDeletedRelations
在实体和模型上都能工作。
性能
警告:请注意,关系依赖于从Schema库生成的模式。虽然这个过程相对较快,但如果页面请求启动加载,将会造成明显的延迟。该模式将尝试缓存以防止这种延迟,但如果您的缓存配置不正确,您可能会经历明显的性能下降。建议的做法是使用cron作业定期生成您的模式,这样它永远不会过期,并且没有用户会触发未缓存的加载,例如:
php spark schemas
有关详细信息,请参阅Daycry\Schemas。
预加载或延迟加载
您负责您应用程序的性能!这些工具在这里是为了帮助您,但它们仍然允许愚蠢的事情。
预加载(通过ModelTrait
)可以通过将通常需要多个数据库调用的内容合并为一个,从而大大提高性能。然而,相关的项目将占用额外的内存,如果无差别使用,可能会造成其他瓶颈或脚本失败。
延迟加载(通过EntityTrait
)使得在需要时与相关项目一起工作变得非常容易,并且神奇的功能使您的代码清晰简洁。然而,每个实体都会发出自己的数据库调用,如果过度使用,确实会开始减慢性能。
一个好的经验法则是使用ModelTrait
来预加载将反复处理(例如,在循环中)或表示非常小或静态数据集(例如,10个可用偏好字符串集)的关系。使用EntityTrait
来处理单个项目,例如查看单个用户页面,或者当您不太可能使用大多数项目的相关关系时。