失败/laravel-custom-builder

自定义Eloquent构建器,以按定义的方式操作其结果

1.0.2 2024-03-20 21:15 UTC

This package is auto-updated.

Last update: 2024-09-20 22:18:02 UTC


README

Laravel自定义构建器允许您像平常一样执行Eloquent查询,但可以改变其响应的形状或类型。

API

Builder类可以用多种类型作为第一个参数进行初始化

  • 从Eloquent构建器

    • 自定义构建器将直接使用Eloquent构建器当前的状态(这可能包括一些已经对其执行的操作)。
  • 从Eloquent模型

    • 底层Eloquent构建器将为此模型实例创建一个新的(例如,您可以获取关系并从那里继续链式调用)。
  • 从Eloquent模型的类(全限定名)

    • 底层Eloquent构建器将为此模型类创建一个新的。

第二个参数,可选的,是一个通用的$callback,它将应用于Eloquent链的任何最终方法(识别的最终方法有first()get()count()pluck())。通常情况下,您不会为所有最终方法使用单个回调,但在某些情况下,这可能是有意义的(见下面第一个简单的示例)。

通常,您不会使用第二个参数,而是为不同的最终方法定义不同的回调。这通过调用Builder@setCallback()Builder@setCallbacks()来实现,如下面的示例所示

use Faliure\LaravelCustomBuilder\Builder;

# Generic callback for all final methods
$builder = new Builder(User::class, fn ($x) => $x->toArray());

# Custom callback, only for `get()`
# NOTE: the other final methods don't transform the result
$builder = new Builder(User::class);
$builder->setCallback($someCallback, Builder::GET);

# Custom callback for `get()` and `first()`
# NOTE: the other final methods don't transform the result
$builder = new Builder(User::class);
$builder->setCallbacks($someCallback, [ Builder::GET, Builder::FIRST ]);

用法

基本示例(仅用于说明,实际上并不实用)

use App\Models\User;
use Faliure\LaravelCustomBuilder\Builder;

$builder = new Builder(User::class, fn ($result) => $result->toArray());

$userData = $builder->first();
$usersData = $builder->where('status', 'active')->get();

在这两种情况下,结果是模型或Eloquent模型集合,而是两者的数组表示。

让我们看看一个更实际的例子。在这里,我们有一个来自其他地方的转换选项,我们只是使用自定义构建器将其插入这里

use App\Models\User;
use Faliure\LaravelCustomBuilder\Builder;

$transform = TransformsFactory::getSomeUserTransformFn(); // Returns some hypotetical transformation closure

$builder = new Builder(User::class, $transform);
$usersTransformed = $builder->get();

在这种情况下,如果没有自定义构建器,我们会这样做

use App\Models\User;
use Faliure\LaravelCustomBuilder\Builder;

$transform = TransformsFactory::getSomeUserTransformFn(); // Returns some hypotetical transformation closure

$usersTransformed = $transform(User::all());

真正有趣的地方是,您可以构建自己的自定义函数,利用构建器无缝地将常规Eloquent结果转换为其他东西(例如,请参阅faliure/laravel-resourceable)。

trait HasResources // Eloquent Model trait
{
    public static function resourcesQuery(?string $resourceClass = null): Builder
    {
        $resourceClass ??= static::resourceClass();

        return (new Builder(static::class))
            ->setCallback(
                fn ($models) => $resourceClass::collection($models),
                Builder::GET
            )->setCallback(
                fn ($model) => $model->resource(),
                Builder::FIRST
            );
    }
}

# Elsewhere in the code
$resources = User::resourcesQuery()->where('some', 'constraint')->get();

通过这个例子,我们可以封装创建构建器和提供回调的复杂性,并仅使用它创建一些有用的函数。

定制

默认情况下,Resourceable假设您的主体Model JsonResource遵循标准

  • 用户的主要资源是App\Http\Resources\UserModel

如果这不是您的情况,您可以在Resourceable模型中定义一个属性resourceClass,如下所示

class User implements Resourceable
{
    // ...

    protected string $resourceClass = TheResourceClass::class;
}

此外,您可以通过将可选的$resourceClass参数传递给接口中定义的任何方法,为模型获取不同类型的资源。具体来说

$resource = $user->resource(SomeOtherResourceType::class);

$resources = User::resources(SomeOtherResourceType::class);

$filteredResources = User::resourcesQuery(SomeOtherResourceType::class)
    ->where('some', 'constraint')
    // ->...
    ->get();

就是这样简单!

如何使用resourcesBuilder

resourcesBuilder是一个自定义Eloquent构建器,允许您像通常一样编写Eloquent链,但它修改最终结果,以返回关联的资源而不是模型或它们的集合。

有关更多信息和其他用法,请参阅faliure/laravel-custom-builder