Laravel 中的集合可以将其视为一个增强版的数组,它在 Laravel 生态系统中非常有用。
代码示例
集合在 Laravel 生态系统中非常强大,但在某些场景下,执行特定操作的逻辑可能变得复杂和冗长,这时就需要考虑抽象这些操作。
一起来看一个 MoonGuard 代码库中的实际案例,这里需要检查每个站点的状态。
以下是 CheckUptimeCommand
类的示例:
<?php
namespace Taecontrol\MoonGuard\Console\Commands;
use Illuminate\Console\Command;
use Taecontrol\MoonGuard\Models\Site;
use Taecontrol\MoonGuard\Contracts\MoonGuardSite;
class CheckUptimeCommand extends Command
{
protected $signature = 'check:uptime';
protected $description = 'Check uptime for all registered sites';
public function handle()
{
//...
$this->info('[Uptime] Starting check...');
// @var Collection
$sites = SiteRepository::query()
->whereUptimeCheckEnabled()
->whereIsNotOnMaintenance()
->with('uptimeCheck')
->get();
$responses = Http::pool(...);
/** @var UptimeCheckService $uptimeCheckService */
$uptimeCheckService = app(UptimeCheckService::class);
$sites->each(
/** @throws InvalidPeriodException */
fn (MoonGuardSite $site) => $uptimeCheckService->check($site, $responses[$site->url->toString()])
);
$this->info('[Uptime] Uptime checked');
}
}
创建自定义集合
我们可以创建一个 SiteCollection
类来封装这些逻辑:
<?php
namespace Taecontrol\MoonGuard\Collections;
use Illuminate\Support\Facades\Http;
use Illuminate\Database\Eloquent\Collection;
use Taecontrol\MoonGuard\Contracts\MoonGuardSite;
use Taecontrol\MoonGuard\Services\UptimeCheckService;
use Taecontrol\MoonGuard\Exceptions\InvalidPeriodException;
use Taecontrol\MoonGuard\Services\SslCertificateCheckService;
class SiteCollection extends Collection
{
public function checkUptime(): void
{
/** @var array<string, Response> $responses */
$responses = Http::pool(/**...*/);
/** @var UptimeCheckService $uptimeCheckService */
$uptimeCheckService = app(UptimeCheckService::class);
$this->each(
/** @throws InvalidPeriodException */
fn (MoonGuardSite $site) => $uptimeCheckService->check($site, $responses[$site->url->toString()])
);
}
}
注意
任何自定义集合都必须继承 Illuminate\Database\Eloquent\Collection
或 Illuminate\Support\Collection
。
在模型中使用自定义集合
要让 Site
模型使用这个集合,需要重写模型的 newCollection()
方法。
<?php
namespace Taecontrol\MoonGuard\Models;
use Taecontrol\MoonGuard\Collections\SiteCollection;
#[CollectedBy(SiteCollection::class)]
class Site extends Model
{
// ...
}
<?php
namespace Taecontrol\MoonGuard\Models;
use Taecontrol\MoonGuard\Collections\SiteCollection;
class Site extends Model
{
// ...
public function newCollection(array $models = []): SiteCollection
{
return new SiteCollection($models);
}
}
更新命令类
最后更新 UptimeCheckCommand
命令以使用 SiteCollection
:
<?php
namespace Taecontrol\MoonGuard\Console\Commands;
use Illuminate\Console\Command;
use Taecontrol\MoonGuard\Repositories\SiteRepository;
class CheckUptimeCommand extends Command
{
protected $signature = 'check:uptime';
protected $description = 'Check uptime for all registered sites';
public function handle()
{
// ...
$this->info('[Uptime] Starting check...');
SiteRepository::query()
->whereUptimeCheckEnabled()
->whereIsNotOnMaintenance()
->with('uptimeCheck')
->get()
->checkUptime();
$this->info('[Uptime] Uptime checked');
}
}
自定义集合允许以实用的方式自定义集合的行为,更重要的是它通过抽象和封装逻辑帮助我们提高代码的可读性和一致性。