## 搜索组件
搜索组件用于 Index 页面生成相对应的搜索表单, 所有搜索组件继承 `app\common\component\SearchComponent`
### 常用组件说明
#### Input 组件 基础组件
用于生成一个普通的 Input 表单
##### 参数:
无
##### 使用示例
```php
public $search = [
'category' => ['input'],
'name' => ['text', 'like'], // 找不到对应组件时将会默认使用 Input 组件, 并将组件名作为 Input 的类型
];
```
#### Selector 组件 选择器
该组件用于生成一个 select 选择器
##### 参数
`table`: 使用该参数的表的查询结果作为选择项
`field`: 需要用到的字段, 当 `format` 参数为空时, 只能填写一个字段, 并且该字段将作为选择项显示的内容
`value`: 作为值的字段
`format`: 展示的格式, 该字段存在时, `field` 参数可以是多个字段, "hello \*field\*" 中 "\*field\*" 将会被替换成字段 field 的值
`join`: 数据库查询时 join 的规则, 同 `think\Db::join` 方法参数格式相同
`where` 数据库查询时 where 的规则, 同 `think\Db::where` 方法参数格式相同
`list`: 当该参数存在时, 将使用该数据作为查询的结果, `list` 与 `table` 只能存在一个
##### 使用示例
```php
public $search = [
// 使用搜索组件中的 selector 组件, 使用 product_category 表中的数据
'cid' => ['selector', null, [
'table' => 'product_category',
'field' => 'name',
'value' => 'id'
]],
// 使用搜索组件中的 selector 组件, 使用固定数据
'status' => ['selector', null, [
'list' => [
[1, '上架'], // 等同与 [0 => 1, 1 => '上架'], 下同
[2, '下架']
],
'field' => 1,
'value' => 0
]],
];
```
#### Datetime 组件 时间范围选择
生成一个时间范围选择器
##### 参数
`type`: 可选, 默认 `datetime`, 时间类型, 当前支持: `datetime`, `date`, `time`
##### 使用示例
```php
public $search = [
'create_time' => ['datetime'],
'update_time' => ['datetime', null, ['type' => 'date']]
];
```
### 自定义搜索组件
**阅读该说明前请先阅读 [视图组件.md](视图组件.md)**
如果默认提供的组件无法满足需求, 目前有两种方法实现自定义的组件:
一种是直接使用一个有效的模板路径作为组件名称, 这样的话该模板将会作为字段的组件模板参与渲染
另外一种是创建自己的搜索组件, 并使用
以上两种方法, 一般来说都可以解决你的问题,
**第一种方法适用于组件的重复利用的可能性不大的情况, 并且灵活度较低, 无法处理返回值, 该方法较为简单**
**第二种方法则相反, 创建的组件可以重复利用, 甚至可以移植到其它项目继续使用, 灵活度较高, 但较为麻烦**
#### 使用模板路径作为组件名
我们先介绍第一种方法, 下面将创建一个可以随意修改属性 input 组件
为了方便使用我们在项目种使用, 我们可以创建一个目录专门用于保存这些 模板文件, 并且将该路径定义为一个常量便于使用
创建 `application\admin\view\component` 目录
![component](https://box.kancloud.cn/4ce585c1041fe5ab1d1707f74b0b8ed5_736x1215.png)
在 `application\admin\common.php` 中定义常量 `C_PATH` 为 创建的模板文件目录路径
![common.php](https://box.kancloud.cn/51f47d18608b1fda5af6579a73685f19_2622x541.png)
创建模板文件 `application\admin\view\component\attrInput.html`
模板的内容如下:
```php+HTML
<div class="col-md-3 col-sm-6">
<input type="text"
value="{$value}"
placeholder="{$name}"
name="{$field}"
class="form-control"
{$options.attr ?? null}
/>
</div>
```
**模板变量说明**
`$value`: 字段的值
`$name`: 字段的展示名
`$field`: 字段名称(已编码)
`$options`: 组件参数, 由于该值是可选的, 使用前请先判断是否存在
将该模板应用到字段上
```php
public $search = [
'name' => [C_PATH . 'attrInput.html', 'like', [
'attr' => 'disabled'
]],
...
];
// 我们这里给 input 传入一个 disabled 属性
```
打开对应的页面查看效果
![input](https://box.kancloud.cn/f4432fc57f269d280c75a2b0640bdcc5_2414x322.png)
可以看到 input 已经被禁用了, 这说明已经成功应用了该模板
虽然这种放非常简单, 但是这样没有办法很好的处理返回值, 比如说 搜索一个时间段, 这个时候, 我们要使用前端传回的值来生成生成查询语句, 那这种方法就不是特别合适了, 所以要用到第二种方法, 创建自定义搜索组件
#### 创建自定搜索组件
在此之前, 请先确定你阅读过 [视图组件.md](视图组件.md) 了解了组件的命名方式和基本的工作方式
下面我们将创建一个多选搜索的组件, 搜索满足任一条件的结果, 我们将其命名为 ICheckbox 组件
创建目录, 模板文件, 类文件
搜索组件的命名前缀为 Search, 所以我们需要创建:
目录 `application\common\component\SearchICheckbox`
模板文件 `application\common\component\SearchICheckbox\SearchICheckbox.html`
类文件 `application\common\component\SearchICheckbox\SearchICheckbox.html`
如图所示:
![目录](https://box.kancloud.cn/b504deda4ba4cb2829e2ed466bbd14e3_748x1067.png)
模板文件 `SearchICheckbox.html` 内容:
```php
<div class="col-md-3 col-sm-6">
{volist name="options.list" id="vo"}
<label>
<input name="{$field}[]"
value="{$vo}"
{if condition="in_array($vo, $value ?? [])"}checked{/if}
type="checkbox">
{$vo}
</label>
{/volist}
</div>
```
这里的模板变量与方法一中的相同:
`$value`: 字段的值
`$name`: 字段的展示名
`$field`: 字段名称(已编码)
`$options`: 组件参数, 由于该值是可选的, 使用前请先判断是否存在
所有的 搜索组件都需要继承 `app\common\component\SearchComponent`
`SearchICheckbox.php` 的内容:
```php
<?php
namespace app\common\component\SearchICheckbox;
use app\common\component\SearchComponent;
class SearchICheckbox extends SearchComponent
{
}
```
现在我们可以先将该组件应用到视图模型 `application\admin\viewModel\ProductCategory.php` 中去看看效果:
```php
public $search = [
'name' => ['i_checkbox', null, [
'list' => ['零食', '口腔护理', '冰箱', '家用电器']
]],
...
]
```
效果如图所示:
![product_category](https://box.kancloud.cn/3f59296c10ba4a92dfe3310fae686f44_2485x1209.png)
可以看到勾选后点击搜索这个时候将会报错:
![error](https://box.kancloud.cn/b452cc8b3f9269e17c07bd936a16c5dd_1853x327.png)
因为 `name` 的值是一个数组, where 不能直接处理这样的一个数组, 所以我们可以直接在 组件中直接处理查询实例
`SearchComponent` 继承了 `Component` 并且有一个自己的方法, `search` 定义如下:
```php
abstract class SearchComponent extends Component
{
/**
* 生成查询条件
* @param $field string 表单字段
* @param $params array 查询参数
* @param $query Query Query 实例
*/
public static function search ($field, &$params, &$query)
{
$query->where($field, 'eq', $params[$field]);
}
}
```
所以在 `SearchICheckbox.php` 中, 我们重写 `search` 方法:
```php
class SearchICheckbox extends SearchComponent
{
public static function search($field, &$params, &$query)
{
if ($params) {
$query->where($field, 'in', $params[$field]);
// 这里直接使用 in 方法查询
}
}
}
```
那么现在这个组件已经可以正常工作了