Query filter

model-grid provides a number of methods to implement query filtering of table data:

  1. // prohibit the use of sth.
  2. $grid->disableFilter();
  3. // show
  4. $grid->showFilter();
  5. // Disable filter button
  6. $grid->disableFilterButton();
  7. // Display filter button
  8. $grid->showFilterButton();
  9. $grid->filter(function($filter){
  10. // Expand Filter
  11. $filter->expand();
  12. // Add a field filter here
  13. $filter->equal('id', '产品序列号');
  14. $filter->like('name', 'name');
  15. ...
  16. });

Filter layout

The default layout is rightSide.

rightSide

  1. use Dcat\Admin\Grid;
  2. $grid->filter(function (Grid\Filter $filter) {
  3. // Change to rightSide Layout
  4. $filter->rightSide();
  5. ...
  6. });

result

Query filter - 图1

panel

  1. use Dcat\Admin\Grid;
  2. $grid->filter(function (Grid\Filter $filter) {
  3. // Change to panel layout
  4. $filter->panel();
  5. // Note that you need to readjust the width of the form fields when switching to panel layout.
  6. $filter->equal('id')->width(3);
  7. });

result

Query filter - 图2

Custom layout (view)

If the above layout does not meet your needs, you can customize the filter template using the view method

  1. $grid->filter(function ($filter) {
  2. $filter->view('xxx');
  3. ...
  4. });

Query type

The following filter types are currently supported:

equal

sql: ... WHEREcolumn= "$input"

  1. $filter->equal('column', $label);

notEqual

sql: ... WHEREcolumn!= "$input"

  1. $filter->notEqual('column', $label);

like

sql: ... WHEREcolumnLIKE "%$input%"

  1. $filter->like('column', $label);

ilike

sql: ... WHEREcolumnILIKE "%$input%"

  1. $filter->ilike('column', $label);

startWith

sql: ... WHEREcolumnLIKE "$input%"

  1. $filter->startWith('column', $label);
  2. // If you need to use “ilike”
  3. $filter->startWith('column', $label)->ilike();

endWith

sql: ... WHEREcolumnLIKE "%$input"

  1. $filter->endWith('column', $label);
  2. // If you need to use “ilike”
  3. $filter->endWith('column', $label)->ilike();

gt

sql: ... WHEREcolumn> "$input"

  1. $filter->gt('column', $label);

lt

sql: ... WHEREcolumn< "$input"

  1. $filter->lt('column', $label);

ngt

sql: ... WHEREcolumn<= "$input"

  1. $filter->ngt('column', $label);

nlt

sql: ... WHEREcolumn>= "$input"

  1. $filter->nlt('column', $label);

between

sql: ... WHEREcolumnBETWEEN "$start" AND "$end"

  1. $filter->between('column', $label);
  2. // Set datetime type
  3. $filter->between('column', $label)->datetime();
  4. // Set the time type
  5. $filter->between('column', $label)->time();

in

sql: ... WHEREcolumnin (...$inputs)

  1. $filter->in('column', $label)->multipleSelect(['key' => 'value']);

notIn

sql: ... WHEREcolumnnot in (...$inputs)

  1. $filter->notIn('column', $label)->multipleSelect(['key' => 'value']);

date

sql: ... WHERE DATE(column) = "$input"

  1. $filter->date('column', $label);

day

sql: ... WHERE DAY(column) = "$input"

  1. $filter->day('column', $label);

month

sql: ... WHERE MONTH(column) = "$input"

  1. $filter->month('column', $label);

year

sql: ... WHERE YEAR(column) = "$input"

  1. $filter->year('column', $label);

findInSet

sql: ... WHERE FIND_IN_SET("$input", $column)

  1. $filter->findInSet('column', $label);

Complex query where

You can use WHERE to build more complex query filters.

sql: ... WHEREtitleLIKE "%$input" ORcontentLIKE "%$input"

  1. $filter->where('search', function ($query) {
  2. $query->where('title', 'like', "%{$this->input}%")
  3. ->orWhere('content', 'like', "%{$this->input}%");
  4. });

sql: ... WHERErate>= 6 ANDcreated_at= {$input}:

  1. $filter->where('Text', function ($query) {
  2. $query->whereRaw("`rate` >= 6 AND `created_at` = {$this->input}");
  3. });

Relational query for the field corresponding to the relationship profile.

  1. $filter->where('mobile', function ($query) {
  2. $query->whereHas('profile', function ($query) {
  3. $query->where('address', 'like', "%{$this->input}%")->orWhere('email', 'like', "%{$this->input}%");
  4. });
  5. }, 'Address or mobile number');

Complex range queries whereBetween

Customizable range queries via whereBetween

  1. $filter->whereBetween('created_at', function ($q) {
  2. $start = $this->input['start'] ?? null;
  3. $end = $this->input['end'] ?? null;
  4. $q->whereHas('goods', function ($q) use ($start) {
  5. if ($start !== null) {
  6. $q->where('price', '>=', $start);
  7. }
  8. if ($end !== null) {
  9. $q->where('price', '<=', $end);
  10. }
  11. });
  12. });

This method also supports time and date range queries

  1. $filter->whereBetween('created_at', function ($q) {
  2. ...
  3. })->datetime();

Filter group

Sometimes you need to set multiple filters for the same field, which can be done in the following ways

  1. $filter->group('rate', function ($group) {
  2. $group->gt('大于');
  3. $group->lt('小于');
  4. $group->nlt('不小于');
  5. $group->ngt('不大于');
  6. $group->equal('等于');
  7. });

There are several methods that can be invoked

  1. // equal
  2. $group->equal();
  3. // not equal to
  4. $group->notEqual();
  5. // greater than
  6. $group->gt();
  7. // less than
  8. $group->lt();
  9. // greater than or equal to
  10. $group->nlt();
  11. // less than equal to
  12. $group->ngt();
  13. // match
  14. $group->match();
  15. // complex condition
  16. $group->where();
  17. // like query
  18. $group->like();
  19. // like query
  20. $group->contains();
  21. // ilike search
  22. $group->ilike();
  23. // Begin with what you have entered
  24. $group->startWith();
  25. // End with what you have entered
  26. $group->endWith();

Range query scope

It is possible to define the queries you use most often as a range of queries that will appear in the drop-down menu of the Filter button, here are a few examples:

  1. $filter->scope('male', '男性')->where('gender', 'm');
  2. // multi-conditional query
  3. $filter->scope('new', 'Recently changed')
  4. ->whereDate('created_at', date('Y-m-d'))
  5. ->orWhere('updated_at', date('Y-m-d'));
  6. // Affiliation Search
  7. $filter->scope('address')->whereHas('profile', function ($query) {
  8. $query->whereNotNull('address');
  9. });
  10. $filter->scope('trashed', 'Soft-deleted data')->onlyTrashed();

The first argument of the scope method is the key of the query, which will appear in the url, the second argument is the label of the drop-down menu item.

The scope method can be chained to any eloquent query condition, result reference Demo

Type of form

text

The default form type is text input, you can set placeholder:

  1. $filter->equal('column')->placeholder('Please enter...');

It is also possible to restrict the user input format in some of the following ways:

  1. $filter->equal('column')->url();
  2. $filter->equal('column')->email();
  3. $filter->equal('column')->integer();
  4. $filter->equal('column')->ip();
  5. $filter->equal('column')->mac();
  6. $filter->equal('column')->mobile();
  7. // $options see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
  8. $filter->equal('column')->decimal($options = []);
  9. // $options see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
  10. $filter->equal('column')->currency($options = []);
  11. // $options see https://github.com/RobinHerbots/Inputmask/blob/4.x/README_numeric.md
  12. $filter->equal('column')->percentage($options = []);
  13. // $options see https://github.com/RobinHerbots/Inputmask, $icon为input前面的图标
  14. $filter->equal('column')->inputmask($options = [], $icon = 'pencil');

Table selector (selectTable)

  1. use App\Admin\Renderable\UserTable;
  2. use Dcat\Admin\Models\Administrator;
  3. $filter->equal('user_id')
  4. ->selectTable(UserTable::make(['id' => ...])) // Set the rendering class instance and pass custom parameters
  5. ->title('Pop-up window TITLE')
  6. ->dialogWidth('50%') // Popup width, default 800px
  7. ->model(Administrator::class, 'id', 'name'); // Set the display of editing data
  8. // The code above is equivalent to
  9. $filter->equal('user_id')
  10. ->selectTable(UserTable::make(['id' => ...])) // Set the rendering class instance and pass custom parameters
  11. ->options(function ($v) { // Set the display of editing data
  12. if (! $v) {
  13. return [];
  14. }
  15. return Administrator::find($v)->pluck('name', 'id');
  16. });

Define the rendering class as follows, which needs to inherit Dcat\Admin\Grid\LazyRenderable.

{tip} The data table is loaded asynchronously here, please refer to load asynchronously for more details.

  1. <?php
  2. namespace App\Admin\Renderable;
  3. use Dcat\Admin\Grid;
  4. use Dcat\Admin\Grid\LazyRenderable;
  5. use Dcat\Admin\Models\Administrator;
  6. class UserTable extends LazyRenderable
  7. {
  8. public function grid(): Grid
  9. {
  10. // Getting externally passed parameters
  11. $id = $this->id;
  12. return Grid::make(new Administrator(), function (Grid $grid) {
  13. $grid->column('id');
  14. $grid->column('username');
  15. $grid->column('name');
  16. $grid->column('created_at');
  17. $grid->column('updated_at');
  18. // Specify the field name of the value to be displayed when the line selector is selected.
  19. // Specify the field name of the value to be displayed when the line selector is selected.
  20. // Specify the field name of the value to be displayed when the line selector is selected.
  21. // If the form data has a "name", "title", or "username" field, you do not have to set this.
  22. $grid->rowSelector()->titleColumn('username');
  23. $grid->quickSearch(['id', 'username', 'name']);
  24. $grid->paginate(10);
  25. $grid->disableActions();
  26. $grid->filter(function (Grid\Filter $filter) {
  27. $filter->like('username')->width(4);
  28. $filter->like('name')->width(4);
  29. });
  30. });
  31. }
  32. }

multipleSelectTable

Multi-selected Uses are consistent with the selectTable method above

  1. $filter->in('user_id')
  2. ->multipleSelectTable(UserTable::make(['id' => $form->getKey()])) // Set the rendering class instance and pass custom parameters
  3. ->max(10) // Select up to 10 options. If you don't pass this, there's no limit.
  4. ->model(Administrator::class, 'id', 'name'); // Set the display of editing data

select

  1. $filter->equal('column')->select(['key' => 'value'...]);
  2. // Or get data from an api, the format of the api refers to the select component of the model-form
  3. $filter->equal('column')->select('api/users');

multipleSelect

Generally used with in and notIn query types that require an array of queries, but can also be used with where type queries:

  1. $filter->in('column')->multipleSelect(['key' => 'value'...]);
  2. // Or get data from an api, the format of which is referenced in the model-form's multipleSelect component
  3. $filter->in('column')->multipleSelect('api/users');

datetime

Search by date time component. Reference for parameters and values of $options bootstrap-datetimepicker

  1. $filter->equal('column')->datetime($options);
  2. // `date()` equal to `datetime(['format' => 'YYYY-MM-DD'])`
  3. $filter->equal('column')->date();
  4. // `time()` equal to `datetime(['format' => 'HH:mm:ss'])`
  5. $filter->equal('column')->time();
  6. // `day()` equal to `datetime(['format' => 'DD'])`
  7. $filter->equal('column')->day();
  8. // `month()` equal to `datetime(['format' => 'MM'])`
  9. $filter->equal('column')->month();
  10. // `year()` equal to `datetime(['format' => 'YYYY'])`
  11. $filter->equal('column')->year();

If your time-date field is stored in the database as a timestamp type, you can convert the form value to a timestamp by using the toTimestamp method

  1. $filter->equal('column')->datetime($options)->toTimestamp();

Common methods

Filter width

  1. // Set width to a value between "1-12", default value is "3".
  2. $filter->equal('column')->width(3);
  3. // you can also write out the absolute width
  4. $filter->equal('column')->width('250px');

Set default values (default)

  1. $filter->equal('column')->default('text');
  2. $filter->equal('column')->select([0 => 'PHP', 1 => 'Java'])->default(1);

Expanding the filter (expand)

  1. $filter->expand();
  2. $filter->equal('column');
  3. ...

Do not display the border of the filter input box

  1. $filter->withoutInputBorder();
  2. $filter->equal('column');
  3. ...

Set filter container style

  1. $filter->style('padding:0');
  2. $filter->equal('column');
  3. ...

Set filter container padding

  1. $filter->padding('10px', '10px', '10px', '10px');
  2. $filter->equal('column');
  3. ...

ignore filter (ignore)

The ignore method allows you to ignore the current filter when submitting the form.

  1. $filter->equal('column')->ignore();

Relational field lookup

Suppose your model is as follows

  1. class User extends Model
  2. {
  3. public function profile()
  4. {
  5. return $this->hasOne(...);
  6. }
  7. public function myPosts()
  8. {
  9. return $this->hasMany(...);
  10. }
  11. }

The first_name field of the profiles table and the title field of the posts table can be queried by the following methods

  1. $grid->filter(function ($filter) {
  2. $filter->like('profile.first_name');
  3. $filter->like('myPosts.title');
  4. });

If dcat/laravel-wherehasin is installed, the whereHasIn method will be used in preference to queries

Custom Filters

The following is an implementation of between to explain how to customize the filter.

First create a new filter class to inherit Dcat\Admin\Filter\AbstractFilter:

  1. <?php
  2. namespace Dcat\Admin\Grid\Filter;
  3. use Dcat\Admin\Admin;
  4. use Dcat\Admin\Grid\Filter\Presenter\DateTime;
  5. use Illuminate\Support\Arr;
  6. class Between extends AbstractFilter
  7. {
  8. // Customize your filter display templates
  9. protected $view = 'admin::filter.between';
  10. // This method is used to generate a unique id for the filter field
  11. // This unique id can be manipulated with js code
  12. public function formatId($column)
  13. {
  14. $id = str_replace('.', '_', $column);
  15. $name = $this->parent->getGrid()->getName();
  16. return ['start' => "{$name}{$id}_start", 'end' => "{$name}{$id}_end"];
  17. }
  18. // Form form name attribute formatting
  19. protected function formatName($column)
  20. {
  21. $columns = explode('.', $column);
  22. if (count($columns) == 1) {
  23. $name = $columns[0];
  24. } else {
  25. $name = array_shift($columns);
  26. foreach ($columns as $column) {
  27. $name .= "[$column]";
  28. }
  29. }
  30. return ['start' => "{$name}[start]", 'end' => "{$name}[end]"];
  31. }
  32. // Create conditions
  33. // The build condition here supports the `Laravel query builder`.
  34. public function condition($inputs)
  35. {
  36. if (!Arr::has($inputs, $this->column)) {
  37. return;
  38. }
  39. $this->value = Arr::get($inputs, $this->column);
  40. $value = array_filter($this->value, function ($val) {
  41. return $val !== '';
  42. });
  43. if (empty($value)) {
  44. return;
  45. }
  46. if (!isset($value['start']) && isset($value['end'])) {
  47. // The array returned here is equivalent to
  48. // $query->where($this->column, '<=', $value['end']);
  49. return $this->buildCondition($this->column, '<=', $value['end']);
  50. }
  51. if (!isset($value['end']) && isset($value['start'])) {
  52. // The array returned here is equivalent to
  53. // $query->where($this->column, '>=', $value['end']);
  54. return $this->buildCondition($this->column, '>=', $value['start']);
  55. }
  56. $this->query = 'whereBetween';
  57. // The array returned here is equivalent to
  58. // $query->whereBetween($this->column, $value['end']);
  59. return $this->buildCondition($this->column, $this->value);
  60. }
  61. // Customizing the filter form display
  62. public function datetime($options = [])
  63. {
  64. $this->view = 'admin::filter.betweenDatetime';
  65. DateTime::collectAssets();
  66. $this->setupDatetime($options);
  67. return $this;
  68. }
  69. protected function setupDatetime($options = [])
  70. {
  71. $options['format'] = Arr::get($options, 'format', 'YYYY-MM-DD HH:mm:ss');
  72. $options['locale'] = Arr::get($options, 'locale', config('app.locale'));
  73. $startOptions = json_encode($options);
  74. $endOptions = json_encode($options + ['useCurrent' => false]);
  75. // Do what you want with the form using the formatted id above.
  76. $script = <<<JS
  77. $('#{$this->id['start']}').datetimepicker($startOptions);
  78. $('#{$this->id['end']}').datetimepicker($endOptions);
  79. $("#{$this->id['start']}").on("dp.change", function (e) {
  80. $('#{$this->id['end']}').data("DateTimePicker").minDate(e.date);
  81. });
  82. $("#{$this->id['end']}").on("dp.change", function (e) {
  83. $('#{$this->id['start']}').data("DateTimePicker").maxDate(e.date);
  84. });
  85. JS;
  86. Admin::script($script);
  87. }
  88. }

admin::filter.between looks like:

  1. <div class="filter-input col-sm-{{ $width }} " style="{!! $style !!}">
  2. <div class="form-group" >
  3. <div class="input-group input-group-sm">
  4. <span class="input-group-addon"><b>{!! $label !!}</b></span>
  5. <input type="text" class="form-control" placeholder="{{$label}}" name="{{$name['start']}}" value="{{ request($name['start'], \Illuminate\Support\Arr::get($value, 'start')) }}">
  6. <span class="input-group-addon" style="border-left: 0; border-right: 0;">To</span>
  7. <input type="text" class="form-control" placeholder="{{$label}}" name="{{$name['end']}}" value="{{ request($name['end'], \Illuminate\Support\Arr::get($value, 'end')) }}">
  8. </div>
  9. </div>
  10. </div>

admin::filter.betweenDatetimelooks like:

  1. <div class="filter-input col-sm-{{ $width }}" style="{!! $style !!}">
  2. <div class="form-group">
  3. <div class="input-group input-group-sm">
  4. <span class="input-group-addon"><b>{{$label}}</b> &nbsp;<i class="fa fa-calendar"></i></span>
  5. <input type="text" class="form-control" id="{{$id['start']}}" placeholder="{{$label}}" name="{{$name['start']}}" value="{{ request($name['start'], \Illuminate\Support\Arr::get($value, 'start')) }}">
  6. <span class="input-group-addon" style="border-left: 0; border-right: 0;">To</span>
  7. <input type="text" class="form-control" id="{{$id['end']}}" placeholder="{{$label}}" name="{{$name['end']}}" value="{{ request($name['end'], \Illuminate\Support\Arr::get($value, 'end')) }}">
  8. </div>
  9. </div>
  10. </div>

Now just call the extend method to use it, open app/Admin/bootstrap.php and add the following code:

  1. Filter::extend('customBetween', Filter\Between::class);

use:

  1. $filter->customBetween('created_at')->datetime();