Fields inherited from ModelRelationField do not work with either the specified resource query or the scope of the related model
savosik opened this issue · comments
savosik commented
Description
PHP version: PHP 8.2.18
DB version: MySQL: 8.2
Laravel version: 10.48.16
Moonshine version: 2.18.1
Steps to reproduce:
- Create Model 'Company':
class Company extends Model
{
use SoftDeletes; // Model uses SoftDeletes!
protected $fillable = ['name', 'inn', 'moonshine_user_id'];
protected $searchableFields = ['*'];
public function orders(): `HasMany`
{
return $this->hasMany(Order::class);
}
public function user(): BelongsTo
{
return $this->belongsTo(User::class, 'moonshine_user_id'); // User was inherited from MoonshineUser model
}
protected static function booted()
{
static::addGlobalScope('filterByUser', function (Builder $builder) { // scope was temporary added from trait (wherehas etc..)
if (!App::runningInConsole() && Auth::check()) {
$builder->whereHas('user', function (Builder $query) {
$query->where('moonshine_users.id', Auth::id());
});
}
});
}
}
- Create Moonshine Resource 'CompanyResource':
class CompanyResource extends ModelResource
{
protected string $model = Company::class;
protected string $title = 'Компании';
protected string $column = 'name';
/* todo:: uncomment it for test resource without model's global scope
public function query() : \Illuminate\Contracts\Database\Eloquent\Builder
{
return parent::query()->where('moonshine_user_id', auth()->id());
}
*/
protected function beforeCreating(Model $item): Model
{
$item->moonshine_user_id ??= auth()->id();
return $item;
}
...
}
- Create Order Model:
class Order extends Model
{
use \Znck\Eloquent\Traits\BelongsToThrough;
use SoftDeletes;
use FilterByUser; // global scope by user for order
protected $fillable = [ '*',];
public function company(): BelongsTo
{
return $this->belongsTo(Company::class);
}
public function user(): BelongsToThrough
{
return $this->belongsToThrough(User::class, Company::class);
}
}
- Create Moonshine Resource : 'OrderResource':
class OrderResource extends ModelResource
{
protected string $model = Order::class;
protected string $title = 'Заказы поставщику';
public function fields(): array
{
return [
Block::make([
ID::make()->sortable(),
BelongsTo::make('Компания', 'company', resource: new CompanyResource())
]),
];
}
}
The filtering methods on the field itself are very cumbersome and often force code duplication or the creation of a custom class for the field:
BelongsTo::make('Компания', 'company', resource: new CompanyResource())
->valuesQuery(function (Builder $builder) {
return $builder->whereHas('user', function (Builder $builder) {
$builder->where('moonshine_users.id', Auth::id())->whereNull('deleted_at');
});
})->asyncSearch(asyncSearchQuery: function (Builder $builder) {
return $builder->whereHas('user', function (Builder $builder) {
$builder->where('moonshine_users.id', Auth::id())->whereNull('deleted_at');;
});
})