tatter / 花名册
CodeIgniter 4 中数据库关系的批量名称查找
资助包维护!
tattersoftware
paypal.me/tatter
Requires
- php: ^7.4 || ^8.0
Requires (Dev)
- codeigniter4/framework: ^4.1
- tatter/tools: ^2.0
This package is auto-updated.
Last update: 2024-09-18 05:57:53 UTC
README
CodeIgniter 4 中数据库关系的批量名称查找
快速入门
- 使用 Composer 安装:
> composer require tatter/roster
- 创建 Roster 类
- 加载高性能名称:
<?= service('roster')->user(1) ?>
描述
Roster
以优雅的方式解决了常见且具有针对性的问题:无需数据库查询即可快速访问实体关系显示名称。例如... 你的电子商务应用允许用户列出自己的产品以及他们的用户名。为了显示完整的商品页面,传统上你可能需要数据库 JOIN
来获取每个产品的用户名,或者依赖于第三方解决方案,如对象关系映射 (ORM) 来加载相关数据。 Roster
通过预加载对象名称批次并将其缓存以提高快速访问来简化并优化这一点。
安装
通过 Composer 安装以利用 CodeIgniter 4 的自动加载功能,并始终保持最新状态
> composer require tatter/roster
或者,通过下载源文件并将目录添加到 app/Config/Autoload.php
中手动安装。
使用方法
Roster
服务处理定位和与你的 Roster 类交互,因此你只需要创建一些 Rosters。所有 Rosters 都必须满足一些标准才能被发现
- Rosters 必须扩展 Base Roster(《Tatter\Roster\BaseRoster》)
- Rosters 必须位于命名空间(例如
App\Rosters
)中的 Rosters 文件夹内 - Rosters 必须以它们的查找名称后跟 "Roster"(例如 "CarRoster")来命名
BaseRoster
BaseRoster
定义了你的类必须实现的三个方法
protected function key(): string;
protected function fetchAll(): array;
protected function fetch($id): ?string;
有关更多详细信息,请参阅 BaseRoster
文件。
ModelRoster
大多数情况下,Rosters 将从数据库中获取信息。为了使这更加方便并减少重复代码,此库附带了一个中间支持类,即 ModelRoster
。如果你的 Roster 与现有的模型一致,则只需扩展 ModelRoster
类并提供以下所需字段
protected $modelName;
protected $field;
显示
配置好 Rosters 后,使用服务以 Roster 名称作为方法和项目 ID 作为唯一参数
$userName = service('roster')->user($userId);
示例
你正在开发一个博客。在每篇帖子的底部有一个评论部分,其中登录用户可以发表回复。作为一名聪明的开发者,你决定使用 Tatter\Roster
来处理显示并节省每次页面上的昂贵数据库连接。
首先,让我们处理显示每个评论旁边的用户名。你已经有了 UserModel
,因此我们可以使用 ModelRoster
使其更加容易。创建 app/Rosters/UserRoster.php
namespace App\Rosters; use App\Models\UserModel; use Tatter\Roster\ModelRoster; class UserRoster extends ModelRoster { protected $modelName = UserModel::class; protected $field = 'username'; }
这就完成了!ModelRoster
处理根据这些属性检索值。现在在我们的评论 HTML 块中,我们可以使用 Roster 服务来显示每个用户名
<?php foreach ($comments as $comment): ?> <div class="comment"> <blockquote><?= $comment->content ?></blockquote> <div class="comment-footer"> Commented by <?= service('roster')->user($comment->user_id) ?> </div> </div> <?php endforeach; ?>
接下来让我们处理我们的博客标签:在帖子标题下,我们希望显示此帖子的每个标签。不幸的是,标签的格式是 "[一般] 特定" 因此没有单个字段可以工作。我们仍然可以使用 ModelRoster
,但我们将提供自己的确定方法而不是指定字段。创建 app/Rosters/TagRoster.php
namespace App\Rosters; use App\Models\TagModel; use Tatter\Roster\ModelRoster; class TagRoster extends ModelRoster { protected $modelName = TagModel::class; protected function getFieldValue(array $row): string { // Convert the database row from TagModel into its displayable form $general = $row['general']; $specific = $row['specific']; return "[$general] $specific"; } }
现在我们的博客帖子标题看起来更整洁了
<h1><?= $post->title ?></h1> <div class="tags"> <?php foreach ($post->tags as $tagId): ?> <span class="tag"><?= service('roster')->tag($tagId) ?></span> <?php endforeach; ?> </div>
最后,我们的博客将显示一个侧边栏菜单,其中包含指向合作伙伴的相关链接。这些数据将来自第三方API,每次页面加载时调用它将非常昂贵,因此我们为其创建了一个清单。因为数据源不是一个模型,我们需要扩展Base Roster。创建 app/Rosters/LinkRoster.php
namespace App\Rosters; use App\Libraries\LinkApi; use Tatter\Roster\BaseRoster; class LinkRoster extends BaseRoster { /** * Returns the handler-specific identifier used for caching */ protected function key(): string { return 'roster-links'; } /** * Loads all IDs and their names from the data source. */ protected function fetchAll(): array { $results = []; $links = new LinkApi(); foreach ($links->list() as $link) { $results[$link->uid] = $link->href; } return $results; } /** * Loads a single ID and name from the data source. */ protected function fetch($id): ?string { $links = new LinkApi(); if ($link = $links->get($id)) { return $link->href; } return null; } }
有一点更多的代码,但是使用BaseRoster
可以提供更多关于数据来源和格式化的控制。你可能已经猜到了这部分,但让我们完成我们的链接,并添加它们的HTML菜单
<nav class="links-menu"> <h3>Visit our partner blogs!</h3> <ul> <?php foreach ($post->partnerLinks as $uid): ?> <span class="tag"><?= service('roster')->link($uid) ?></span> <?php endforeach; ?> </ul> </nav>