Laravel Nova 中同一模型上的两个资源字段的 relatableQuery()
relatableQuery() for two resource fields on same model in Laravel Nova
我的工作'days'和不同类型的项目有关系。所以我的 'days' 记录引用了我的 'projects' table 两次,因为我有两种不同类型的项目,分别称为 'Series' 和 'Event'.
在我的 'days' 资源中,我创建了两个字段:
BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
BelongsTo::make('Event','event',Project::class)->sortable()->nullable(),
我想做的是按类型过滤项目,所以我创建了这个:
public static function relatableProjects(NovaRequest $request, $query){
return $query->where('type', 'Series');
}
我试过制作 relatableSeries 和 relatableEvents,但它们不起作用。我怎样才能使它正确地连接到字段而不必为 'series' 和 'events'.
创建两个单独的 tables
上面的 relatable查询结束过滤两个资源字段。
因为 relatableQuery() 引用了 relatableModel() (所以 relatableProjects() 引用了 Project 模型)我能够创建另一个模型仅用于帮助解决此问题。
我创建了一个引用相同 projects
table 的事件模型,然后能够创建 relatableEvents() 方法来使用 where() 过滤器查询。
注意:我确实还必须创建一个引用事件模型的事件资源,因为这是 Nova 的工作方式,但能够隐藏它不被访问,您可以找到有关 here
的更多信息
查看以下修改后的 BelongsTo 字段和新模型:
天资源
/**
* Build a "relatable" query for the given resource.
*
* This query determines which instances of the model may be attached to other resources.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function relatableProjects(NovaRequest $request, $query){
return $query->where('type', 'Series');
}
/**
* Build a "relatable" query for the given resource.
*
* This query determines which instances of the model may be attached to other resources.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function relatableEvents(NovaRequest $request, $query){
return $query->where('type', 'Event');
}
/**
* Get the fields displayed by the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()->hideFromIndex()->hideFromDetail()->hideWhenUpdating(),
BelongsTo::make('User','user',User::class)->sortable(),
BelongsTo::make('Budget','budget',Budget::class)->sortable()->nullable(),
BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
BelongsTo::make('Event','event',Event::class)->sortable()->nullable(),
DateTime::make('Last Updated','updated_at')->hideFromIndex()->readOnly(),
new Panel('Schedule',$this->schedule()),
new Panel('Time Entry',$this->timeEntries()),
];
}
事件模型
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'projects';
protected $casts = [
'starts_on' => 'date',
'ends_on' => 'date',
];
public function event(){
return $this->belongsTo('App\Event');
}
public function project(){
return $this->belongsTo('App\Project');
}
}
我知道这是一个老问题,但我在 laravel nova belongsto 领域遇到了同样的问题,在某些资源中我有一个与用户相关的 belongsto 但这些应该是 'supervisor' 角色在另一个资源中,我有一个与用户相关的 belongsto 字段,但这些应该具有 'guard' 的作用,因为 laravel nova belongsto 字段只接受所有用户,选择所有用户出现,似乎 nova belongsto 字段没有有办法,或者至少我没有找到它来确定查询的范围,所以我所做的是创建一个名为 BelongstoScoped 的 php class this class extends laravel nova field BelongsTo 所以我重写了负责创建查询的方法
<?php
namespace App\Nova\Customized;
use Laravel\Nova\Query\Builder;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Http\Requests\NovaRequest;
class BelongsToScoped extends BelongsTo
{
private $modelScopes = [];
//original function in laravel belongsto field
public function buildAssociatableQuery(NovaRequest $request, $withTrashed = false)
{
$model = forward_static_call(
[$resourceClass = $this->resourceClass, 'newModel']
);
$query = new Builder($resourceClass);
//here i chaned this:
/*
$query->search(
$request, $model->newQuery(), $request->search,
[], [], ''
);
*/
//To this:
/*
$query->search(
$request, $this->addScopesToQuery($model->newQuery()), $request->search,
[], [], ''
);
*/
//The method search receives a query builder as second parameter, i just passed the result of custom function
//addScopesToQuery as second parameter, thi method returns the same query but with the model scopes passed
$request->first === 'true'
? $query->whereKey($model->newQueryWithoutScopes(), $request->current)
: $query->search(
$request, $this->addScopesToQuery($model->newQuery()), $request->search,
[], [], ''
);
return $query->tap(function ($query) use ($request, $model) {
forward_static_call($this->associatableQueryCallable($request, $model), $request, $query, $this);
});
}
//this method reads the property $modelScopes and adds them to the query
private function addScopesToQuery($query){
foreach($this->modelScopes as $scope){
$query->$scope();
}
return $query;
}
// this method should be chained tho the field
//example: BelongsToScoped::make('Supervisores', 'supervisor', 'App\Nova\Users')->scopes(['supervisor', 'active'])
public function scopes(Array $modelScopes){
$this->modelScopes = $modelScopes;
return $this;
}
}
?>
在我的用户模型中,我有这样的主管和警卫角色的范围:
public function scopeActive($query)
{
return $query->where('state', 1);
}
public function scopeSupervisor($query)
{
return $query->role('supervisor');
}
public function scopeSuperadmin($query)
{
return $query->role('superadmin');
}
public function scopeGuarda($query)
{
return $query->role('guarda');
}
所以在 laravel nova 资源中我只包括了这个 class 的使用
*记住命名空间取决于您如何命名文件,在我的例子中,我创建了自定义文件夹并将文件包含在其中:
use App\Nova\Customized\BelongsToScoped;
在 nova 资源的字段中,我这样使用:
BelongsToScoped::make('Supervisor', 'supervisorUser', 'App\Nova\Users\User')
->scopes(['supervisor', 'active'])
->searchable()
这样我就可以调用 nova 资源中的 belongsto 字段,它根据模型范围过滤用户。
希望对大家有所帮助,如果我的英语不是很好,请见谅。
我的工作'days'和不同类型的项目有关系。所以我的 'days' 记录引用了我的 'projects' table 两次,因为我有两种不同类型的项目,分别称为 'Series' 和 'Event'.
在我的 'days' 资源中,我创建了两个字段:
BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
BelongsTo::make('Event','event',Project::class)->sortable()->nullable(),
我想做的是按类型过滤项目,所以我创建了这个:
public static function relatableProjects(NovaRequest $request, $query){
return $query->where('type', 'Series');
}
我试过制作 relatableSeries 和 relatableEvents,但它们不起作用。我怎样才能使它正确地连接到字段而不必为 'series' 和 'events'.
创建两个单独的 tables上面的 relatable查询结束过滤两个资源字段。
因为 relatableQuery() 引用了 relatableModel() (所以 relatableProjects() 引用了 Project 模型)我能够创建另一个模型仅用于帮助解决此问题。
我创建了一个引用相同 projects
table 的事件模型,然后能够创建 relatableEvents() 方法来使用 where() 过滤器查询。
注意:我确实还必须创建一个引用事件模型的事件资源,因为这是 Nova 的工作方式,但能够隐藏它不被访问,您可以找到有关 here
的更多信息查看以下修改后的 BelongsTo 字段和新模型:
天资源
/**
* Build a "relatable" query for the given resource.
*
* This query determines which instances of the model may be attached to other resources.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function relatableProjects(NovaRequest $request, $query){
return $query->where('type', 'Series');
}
/**
* Build a "relatable" query for the given resource.
*
* This query determines which instances of the model may be attached to other resources.
*
* @param \Laravel\Nova\Http\Requests\NovaRequest $request
* @param \Illuminate\Database\Eloquent\Builder $query
* @return \Illuminate\Database\Eloquent\Builder
*/
public static function relatableEvents(NovaRequest $request, $query){
return $query->where('type', 'Event');
}
/**
* Get the fields displayed by the resource.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()->hideFromIndex()->hideFromDetail()->hideWhenUpdating(),
BelongsTo::make('User','user',User::class)->sortable(),
BelongsTo::make('Budget','budget',Budget::class)->sortable()->nullable(),
BelongsTo::make('Series','series',Project::class)->sortable()->nullable(),
BelongsTo::make('Event','event',Event::class)->sortable()->nullable(),
DateTime::make('Last Updated','updated_at')->hideFromIndex()->readOnly(),
new Panel('Schedule',$this->schedule()),
new Panel('Time Entry',$this->timeEntries()),
];
}
事件模型
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Event extends Model
{
/**
* The table associated with the model.
*
* @var string
*/
protected $table = 'projects';
protected $casts = [
'starts_on' => 'date',
'ends_on' => 'date',
];
public function event(){
return $this->belongsTo('App\Event');
}
public function project(){
return $this->belongsTo('App\Project');
}
}
我知道这是一个老问题,但我在 laravel nova belongsto 领域遇到了同样的问题,在某些资源中我有一个与用户相关的 belongsto 但这些应该是 'supervisor' 角色在另一个资源中,我有一个与用户相关的 belongsto 字段,但这些应该具有 'guard' 的作用,因为 laravel nova belongsto 字段只接受所有用户,选择所有用户出现,似乎 nova belongsto 字段没有有办法,或者至少我没有找到它来确定查询的范围,所以我所做的是创建一个名为 BelongstoScoped 的 php class this class extends laravel nova field BelongsTo 所以我重写了负责创建查询的方法
<?php
namespace App\Nova\Customized;
use Laravel\Nova\Query\Builder;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Http\Requests\NovaRequest;
class BelongsToScoped extends BelongsTo
{
private $modelScopes = [];
//original function in laravel belongsto field
public function buildAssociatableQuery(NovaRequest $request, $withTrashed = false)
{
$model = forward_static_call(
[$resourceClass = $this->resourceClass, 'newModel']
);
$query = new Builder($resourceClass);
//here i chaned this:
/*
$query->search(
$request, $model->newQuery(), $request->search,
[], [], ''
);
*/
//To this:
/*
$query->search(
$request, $this->addScopesToQuery($model->newQuery()), $request->search,
[], [], ''
);
*/
//The method search receives a query builder as second parameter, i just passed the result of custom function
//addScopesToQuery as second parameter, thi method returns the same query but with the model scopes passed
$request->first === 'true'
? $query->whereKey($model->newQueryWithoutScopes(), $request->current)
: $query->search(
$request, $this->addScopesToQuery($model->newQuery()), $request->search,
[], [], ''
);
return $query->tap(function ($query) use ($request, $model) {
forward_static_call($this->associatableQueryCallable($request, $model), $request, $query, $this);
});
}
//this method reads the property $modelScopes and adds them to the query
private function addScopesToQuery($query){
foreach($this->modelScopes as $scope){
$query->$scope();
}
return $query;
}
// this method should be chained tho the field
//example: BelongsToScoped::make('Supervisores', 'supervisor', 'App\Nova\Users')->scopes(['supervisor', 'active'])
public function scopes(Array $modelScopes){
$this->modelScopes = $modelScopes;
return $this;
}
}
?>
在我的用户模型中,我有这样的主管和警卫角色的范围:
public function scopeActive($query)
{
return $query->where('state', 1);
}
public function scopeSupervisor($query)
{
return $query->role('supervisor');
}
public function scopeSuperadmin($query)
{
return $query->role('superadmin');
}
public function scopeGuarda($query)
{
return $query->role('guarda');
}
所以在 laravel nova 资源中我只包括了这个 class 的使用 *记住命名空间取决于您如何命名文件,在我的例子中,我创建了自定义文件夹并将文件包含在其中:
use App\Nova\Customized\BelongsToScoped;
在 nova 资源的字段中,我这样使用:
BelongsToScoped::make('Supervisor', 'supervisorUser', 'App\Nova\Users\User')
->scopes(['supervisor', 'active'])
->searchable()
这样我就可以调用 nova 资源中的 belongsto 字段,它根据模型范围过滤用户。
希望对大家有所帮助,如果我的英语不是很好,请见谅。