tatter/花名册

CodeIgniter 4 中数据库关系的批量名称查找

v1.0.1 2022-03-06 23:40 UTC

This package is auto-updated.

Last update: 2024-09-18 05:57:53 UTC


README

CodeIgniter 4 中数据库关系的批量名称查找

Coverage Status

快速入门

  1. 使用 Composer 安装: > composer require tatter/roster
  2. 创建 Roster 类
  3. 加载高性能名称: <?= 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>