Laravel Nova 排序 oneToMany 显示重复项
Laravel Nova sorting oneToMany shows dupplicates
当我对相关实体进行排序时,当正在排序的列中存在空值或相同值时,我得到重复值。
问题出现在关系的索引页面中,当我单击“下一步”时:在关系的下 5 个结果中,有前 5 个结果中已经存在的结果。分页好像坏了。
例如,如果我尝试对“总应用程序”列进行排序,并且在结果集中的相应字段 applies
中有 null
个值,那么我会得到重复的结果单击“下一步”时的后续页面。
其他示例:我尝试对“未发布时间”列进行排序,并且有许多值具有完全相同的 unpublished_at
日期。然后我在下一页上得到重复的结果。
在我看来,当正在排序的列中没有差异时,Nova 无法正确处理逻辑“sorting/pagination”。在那种情况下,它应该按另一列排序,比方说我认为的 ID,它始终是唯一的。
EDIT :我想补充一点 JobOnJobboard
是基于具有其他有意义域的枢轴 table ('instances_offers')信息。但是我将 Job
作为简单的 HasMany
关系(而不是 BelongsToMany
关系)链接到它,因为我不需要访问多对多关系的另一端。我只需要有关枢轴 table.
的信息
有什么想法吗?
在此图中,左侧突出显示的一些 ID 也将出现在接下来的 5 个结果中,这非常令人困惑:
Laravel 6.17.1
新星 2.12
App\Job
=> 关联的实体
App\JobOnJobboard
=> 关系
App\Nova\Job
:
class Job extends Resource
{
/**
* The model the resource corresponds to.
*
* @var string
*/
public static $model = 'App\Job';
/**
* The single value that should be used to represent the resource when being displayed.
*
* @var string
*/
public static $title = 'title';
/**
* The per-page options used the resource index.
*
* @var array
*/
public static $perPageOptions = [10, 20, 25];
public function fields(Request $request): array
{
return [
HasMany::make('JobOnJobboard')
->hideFromIndex(),
];
}
}
App\Nova\JobOnJobboard
:
class JobOnJobboard extends Resource
{
/**
* The model the resource corresponds to.
*
* @var string
*/
public static $model = 'App\JobOnJobboard';
/**
* The columns that should be searched.
*
* @var array
*/
public static $search = [
'id',
];
public static $title = 'id';
/**
* Get the fields displayed by the resource.
*
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Text::make('Hits', 'hit')->readonly(true)->sortable(),
Text::make('Total applications', 'applies')->readonly(true)->sortable(),
Text::make('Status')->readonly(true)->sortable(),
DateTime::make('Published At')
->readonly(true),
DateTime::make('Unpublished At')
->readonly(true),
];
}
}
App\Job
:
class Job extends Model
{
use SoftDeletes;
use Filterable;
use HasJsonRelationships;
protected $table = 'offers';
protected $dates = [
'created_at',
'updated_at',
'archived_at',
'published_at',
'unpublished_at',
];
protected $casts = [
'published_at' => 'date:Y-m-d H:i:s',
'unpublished_at' => 'date:Y-m-d',
];
protected $appends = [
'location_iso',
];
public function jobOnJobboard(): HasMany
{
return $this->hasMany(JobOnJobboard::class, 'offer_id', 'id');
}
}
App\JobOnJobboard
:
class JobOnJobboard extends Pivot
{
/**
* {@inheritdoc}
*/
protected $table = 'instances_offers';
/**
* {@inheritdoc}
*/
protected $dates = [
'created_at',
'updated_at',
'published_at',
'unpublished_at',
];
public function job(): BelongsTo
{
return $this->belongsTo(Job::class, 'offer_id');
}
}
所以我找到了解决方案。问题是 MySQL 位置在使用 ORDER BY 时是不确定的。 “并且由于您每次访问页面时都执行新的查询,因此行将被重新“打乱”。
该信息的来源:
由于排序列中的所有行都具有相同的值(无论是“null”还是其他值),MySQL 无法保持每页之间的一致性。因此重复的结果。
为了解决这个问题,按照上面的 Whosebug 响应,我在我的 Base Nova Resource 上做了:
app/Nova/Resource.php
abstract class Resource extends NovaResource
{
public static function indexQuery(NovaRequest $request, $query): Builder
{
$table = $query->getModel()->getTable();
if (Schema::hasColumn($table, 'id')) {
return $query->orderBy('id');
}
return $query;
}
}
我只是在检查我当前的型号 table 是否有“id”列,如果是的话,将其添加为新的订单商品。
这样,如果我有具有相同值的行,MySQL 仍会按 ID 列对它们进行排序。
有关其他信息,sql 查询在此补丁之前是:
select * from `instances_offers` where `instances_offers`.`offer_id` = ? and `instances_offers`.`offer_id` is not null order by `applies` asc limit 6 offset 5
打补丁后变成:
select * from `instances_offers` where `instances_offers`.`offer_id` = ? and `instances_offers`.`offer_id` is not null order by `applies` asc, `id` asc limit 6 offset 5
注意 id asc
添加了一个额外的排序层以防止下一页的结果是 'scrambled'。
当我对相关实体进行排序时,当正在排序的列中存在空值或相同值时,我得到重复值。
问题出现在关系的索引页面中,当我单击“下一步”时:在关系的下 5 个结果中,有前 5 个结果中已经存在的结果。分页好像坏了。
例如,如果我尝试对“总应用程序”列进行排序,并且在结果集中的相应字段 applies
中有 null
个值,那么我会得到重复的结果单击“下一步”时的后续页面。
其他示例:我尝试对“未发布时间”列进行排序,并且有许多值具有完全相同的 unpublished_at
日期。然后我在下一页上得到重复的结果。
在我看来,当正在排序的列中没有差异时,Nova 无法正确处理逻辑“sorting/pagination”。在那种情况下,它应该按另一列排序,比方说我认为的 ID,它始终是唯一的。
EDIT :我想补充一点 JobOnJobboard
是基于具有其他有意义域的枢轴 table ('instances_offers')信息。但是我将 Job
作为简单的 HasMany
关系(而不是 BelongsToMany
关系)链接到它,因为我不需要访问多对多关系的另一端。我只需要有关枢轴 table.
有什么想法吗?
在此图中,左侧突出显示的一些 ID 也将出现在接下来的 5 个结果中,这非常令人困惑:
Laravel 6.17.1
新星 2.12
App\Job
=> 关联的实体
App\JobOnJobboard
=> 关系
App\Nova\Job
:
class Job extends Resource
{
/**
* The model the resource corresponds to.
*
* @var string
*/
public static $model = 'App\Job';
/**
* The single value that should be used to represent the resource when being displayed.
*
* @var string
*/
public static $title = 'title';
/**
* The per-page options used the resource index.
*
* @var array
*/
public static $perPageOptions = [10, 20, 25];
public function fields(Request $request): array
{
return [
HasMany::make('JobOnJobboard')
->hideFromIndex(),
];
}
}
App\Nova\JobOnJobboard
:
class JobOnJobboard extends Resource
{
/**
* The model the resource corresponds to.
*
* @var string
*/
public static $model = 'App\JobOnJobboard';
/**
* The columns that should be searched.
*
* @var array
*/
public static $search = [
'id',
];
public static $title = 'id';
/**
* Get the fields displayed by the resource.
*
* @return array
*/
public function fields(Request $request)
{
return [
ID::make()->sortable(),
Text::make('Hits', 'hit')->readonly(true)->sortable(),
Text::make('Total applications', 'applies')->readonly(true)->sortable(),
Text::make('Status')->readonly(true)->sortable(),
DateTime::make('Published At')
->readonly(true),
DateTime::make('Unpublished At')
->readonly(true),
];
}
}
App\Job
:
class Job extends Model
{
use SoftDeletes;
use Filterable;
use HasJsonRelationships;
protected $table = 'offers';
protected $dates = [
'created_at',
'updated_at',
'archived_at',
'published_at',
'unpublished_at',
];
protected $casts = [
'published_at' => 'date:Y-m-d H:i:s',
'unpublished_at' => 'date:Y-m-d',
];
protected $appends = [
'location_iso',
];
public function jobOnJobboard(): HasMany
{
return $this->hasMany(JobOnJobboard::class, 'offer_id', 'id');
}
}
App\JobOnJobboard
:
class JobOnJobboard extends Pivot
{
/**
* {@inheritdoc}
*/
protected $table = 'instances_offers';
/**
* {@inheritdoc}
*/
protected $dates = [
'created_at',
'updated_at',
'published_at',
'unpublished_at',
];
public function job(): BelongsTo
{
return $this->belongsTo(Job::class, 'offer_id');
}
}
所以我找到了解决方案。问题是 MySQL 位置在使用 ORDER BY 时是不确定的。 “并且由于您每次访问页面时都执行新的查询,因此行将被重新“打乱”。
该信息的来源:
由于排序列中的所有行都具有相同的值(无论是“null”还是其他值),MySQL 无法保持每页之间的一致性。因此重复的结果。
为了解决这个问题,按照上面的 Whosebug 响应,我在我的 Base Nova Resource 上做了:
app/Nova/Resource.php
abstract class Resource extends NovaResource
{
public static function indexQuery(NovaRequest $request, $query): Builder
{
$table = $query->getModel()->getTable();
if (Schema::hasColumn($table, 'id')) {
return $query->orderBy('id');
}
return $query;
}
}
我只是在检查我当前的型号 table 是否有“id”列,如果是的话,将其添加为新的订单商品。
这样,如果我有具有相同值的行,MySQL 仍会按 ID 列对它们进行排序。
有关其他信息,sql 查询在此补丁之前是:
select * from `instances_offers` where `instances_offers`.`offer_id` = ? and `instances_offers`.`offer_id` is not null order by `applies` asc limit 6 offset 5
打补丁后变成:
select * from `instances_offers` where `instances_offers`.`offer_id` = ? and `instances_offers`.`offer_id` is not null order by `applies` asc, `id` asc limit 6 offset 5
注意 id asc
添加了一个额外的排序层以防止下一页的结果是 'scrambled'。