daycry/relations

CodeIgniter 4 的实体关系

v3.0.0 2024-08-28 14:08 UTC

This package is auto-updated.

Last update: 2024-09-28 14:17:33 UTC


README

Codeigniter 4 的 Relations

Build status Coverage Status Downloads GitHub release (latest by date) GitHub stars GitHub license

快速开始

  1. 使用 Composer 安装: > composer require daycry/relations
  2. 将特性添加到您的模型中: use \Daycry\Relations\Traits\ModelTrait
  3. 加载关系: $users = $userModel->with('groups')->findAll();
  4. 将特性添加到您的实体中: use \Daycry\Relations\Traits\EntityTrait
  5. 加载关系: 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([]);

可用的魔法方法动词是:hassetaddremove,并且仅适用于“多对多”关系。

返回的项目

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来处理单个项目,例如查看单个用户页面,或者当您不太可能使用大多数项目的相关关系时。