失败 / laravel-custom-builder
自定义Eloquent构建器,以按定义的方式操作其结果
Requires
- laravel/framework: ^9.50 || ^10.0 || ^11.0
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