在对 Laravel 查询结果集进行排序时指定一些要优先考虑的“粘性”值

问题描述 投票:0回答:3

我目前有一个显示所有国家/地区的国家/地区

dropdown
菜单。通常我的用户会在“美国”、“英国”或“加拿大”之间进行选择。我不希望我的用户一直向下滚动到列表来选择他们的国家/地区,那么有没有办法可以将这 3 个国家/地区置于列表顶部?

正如你从图片中看到的,这就是我想要的东西。当然,现在我已经对这 3 个国家/地区进行了硬编码。我觉得对其进行硬编码并不是一个好的做法,特别是因为我已经在列表中包含了这 3 个国家/地区,因此无需对其进行硬编码。

如您所见,这是我显示国家/地区的代码。您还可以看到我对 3 个国家/地区进行了硬编码。下面是我添加的代码,以便您可以看到。

<select name="country" id="country" class="custom-select" data-live-search="true" data-default="{{ old('country') }}">
    <option value="">Select Country</option>
    <option value="US">United States</option>
    <option value="GB">United Kingdom</option>
    <option value="CA">Canada</option>
    @foreach ($countries as $key=>$val)
        @if($key == old('country'))
            <option value="{{ $key }}" selected="selected">{{ $val }}</option>
        @else
            <option value="{{ $key }}">{{ $val }}</option>
        @endif
    @endforeach
</select>
laravel sorting eloquent laravel-blade custom-sort
3个回答
0
投票

在您的国家/地区表中添加一列,您可以在其中区分正常国家/地区和热门国家/地区。

选项 1:收藏夹

favorite
列附加到表中,如
TINYINT
(迁移中的
boolean
)。然后,只需将这 3 个国家/地区的设置为
1
(
true
),然后您就可以在查询中附加
orderBy
$query->orderByDesc('favorite')

这将使 3 个最喜欢的国家返回顶部

选项 2:订购

我更喜欢这种方法,因为它绝对更具可配置性。将

order
列附加到表中,作为无符号
INT
(迁移中的
unsignedInteger
)。然后,将订单值设置为 0 或 1(我个人更喜欢 1,因为它更容易阅读,但在更改/更新订单时必须记住这一点)到您有多少个国家/地区(如果您开始,则为 -1 0),以您希望的方式显示。然后,在您的查询中:
$query->orderBy('order')
。您甚至可以将其添加为全局范围,这样就永远不会忘记订购。这样,您就可以随时说您希望英国高于美国,反之亦然,或者如果您意识到一个国家比另一个国家更受欢迎,则可以更改它。


0
投票

您不需要添加额外的列或表。您可以使用

arrays
选项作为解决方案。根据以下条件分别制作两个数组。然后使用
->toArray()
将查询输出转换为数组。最后使用
array_merge()
合并两个数组并传递给视图。我想您会列出带有
id
country_name
字段的国家/地区列表,如下所示:

控制器

$my_countries = \App\Country::select(['id','country_name'])->where('country_name', 'United States')->orWhere('country_name', 'United Kingdom')->orWhere('country_name', 'Canada')->get()->toArray();
$countries = \App\Country::select(['id','country_name'])->whereNotIn('country_name', ['United States', 'United Kingdom', 'Canada'])->get()->toArray();
$all_countries  = array_merge($my_countries , $countries);   
return view('your_view', ['all_countries' => $all_countries]);  

查看

<select name="country">
    @foreach($all_countries as $country )
        <option value="{{ $country['id'] }}">{{ $country['country_name'] }}</option>
    @endforeach
</select>    

0
投票
  • 您不需要使用专门用于排序的另一列来扩展数据库表。
  • 您不需要查询数据库两次然后合并两个结果集。
  • 您不需要改变视图层来实现排序首选项。

使用

orderByRaw()
实现
FIELD()
排序。按降序指定您的粘性值(在本例中为第三、第二、第一偏好),然后对
FIELD()
的评估 DESC 进行排序。作为辅助排序,
orderBy()
name
ASC 用于标准字母排序。

代码:(PHPize演示

var_export(
    DB::table('countries')
    ->orderByRaw("FIELD(name, 'Canada', 'United Kingdom', 'United States') DESC")
    ->orderBy('name', 'ASC')
    ->get()
    ->toArray()
);

或者,如果需要对集合进行排序,请使用

sortBy()
。自定义回调参数必须写入数组内部(即使仅使用一种排序规则),否则排序将无法按预期工作。

代码:(PHPize演示

$priorities = array_flip(['United States', 'United Kingdom', 'Canada']);

var_export(
    DB::table('countries')
    ->get()
    ->sortBy([
        fn($a, $b) => [$priorities[$a->name] ?? PHP_INT_MAX, $a->name] <=> [$priorities[$b->name] ?? PHP_INT_MAX, $b->name]
    ])
    ->toArray()
);

输出(来自任一片段):

array (
  0 => 
  (object) array(
     'id' => 4,
     'name' => 'United States',
  ),
  1 => 
  (object) array(
     'id' => 5,
     'name' => 'United Kingdom',
  ),
  2 => 
  (object) array(
     'id' => 3,
     'name' => 'Canada',
  ),
  3 => 
  (object) array(
     'id' => 1,
     'name' => 'Albania',
  ),
  4 => 
  (object) array(
     'id' => 7,
     'name' => 'Algeria',
  ),
  5 => 
  (object) array(
     'id' => 2,
     'name' => 'Bahamas',
  ),
  6 => 
  (object) array(
     'id' => 6,
     'name' => 'Ireland',
  ),
)
© www.soinside.com 2019 - 2024. All rights reserved.