tatter/关系

CodeIgniter 4的实体关系

v2.1.1 2022-07-14 20:12 UTC

This package is auto-updated.

Last update: 2024-09-09 13:32:37 UTC


README

CodeIgniter 4的实体关系

Coverage Status

快速开始

  1. 使用Composer安装: > composer require tatter/relations
  2. 将特性添加到您的模型中: use \Tatter\Relations\Traits\ModelTrait
  3. 加载关系: $users = $userModel->with('groups')->findAll();
  4. 将特性添加到您的实体中: use \Tatter\Relations\Traits\EntityTrait
  5. 加载关系: foreach ($user->groups as $group)

(参见下方的示例)

安装

通过Composer轻松安装,利用CodeIgniter 4的自动加载功能,并始终保持最新状态

    > composer require tatter/relations

或者,通过下载源文件并将目录添加到 app/Config/Autoload.php 手动安装。

配置(可选)

可以通过扩展其配置文件来更改库的默认行为。将 examples/Relations.php 复制到 app/Config/,并按照注释中的说明进行操作。如果在 app/Config 中找不到配置文件,库将使用其自己的配置。

模式

库的所有功能都依赖于生成的数据库模式。模式来自 Tatter\Schemas,可以根据您的需求进行调整(请参阅 模式 配置文件)。如果您想使用自动生成的模式,您的数据库将遵循外键和 pivot/join 表的传统命名模式;有关详细信息,请参阅 Tatter\Schemas

使用方法

关系加载由添加到各自元素的特性处理。

急切/模型

ModelTrait 通过扩展默认的 find* 方法并注入关系到返回的结果中,将关系加载添加到您的模型中。因为这是在模型级别发生的,所以可以在批量中提前加载相关项(“急切加载”)。

将特性添加到您的模型中

	use \Tatter\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 \Tatter\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,并且仅适用于“多对多”关系。

返回的项目

模式将尝试将您的数据库表与其模型关联起来,如果成功,关系将使用每个表的模型来查找相关项目。这保持了模型返回类型、事件和其他方面的一致性。除了返回类型外,关系还会调整单例关系的相关项目。

// 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;

嵌套

模型特质支持嵌套关系调用,但这些可能很耗费资源,因此可以通过在配置中更改$allowNesting来禁用。启用嵌套后,任何相关项目也将加载它们的相关项目(但不是无限循环)。

/* Define your models */
class UserModel
{
	use \Tatter\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在实体和模型上都有效。

性能

警告:请注意,关系依赖于由模式库生成的模式。虽然这个过程相对较快,但如果页面请求启动加载,则会导致明显的延迟。模式将尝试缓存以防止这种延迟,但如果您的缓存配置不正确,您可能会遇到明显的性能下降。建议的方法是让cron作业定期生成您的模式,这样它就永远不会过期,并且不会触发未缓存的加载,例如:

php spark schemas

有关更多详细信息,请参阅Tatter\Schemas

预加载或延迟加载

您负责您应用程序的性能!这些工具在这里是为了帮助,但它们仍然允许做愚蠢的事情。

预加载(通过模型特质)可以通过将本应进行多次数据库调用的操作合并为一次来创建巨大的性能提升。然而,相关项目将占用额外的内存,并且如果使用不当,可能会导致其他瓶颈或脚本失败。

延迟加载(通过实体特质)使得仅在需要相关项目时与之工作变得非常简单,并且魔法函数使您的代码清晰简洁。然而,每个实体都会发出自己的数据库调用,如果过度使用,可能会导致性能真正变慢。

一个很好的经验法则是使用模型特质来预加载将反复处理(例如,在循环中)或表示非常小或静态数据集(例如,10个可用偏好字符串的集合)的关系。使用实体特质来处理单个项目,例如查看单个用户页面,或者当您不太可能使用大多数项目的相关关系时。