Symfony 4.3 sonata admin的select2实现搜索框
遇到的坑
新的工作环境,需要用到国外的php开发框架 Symfony 4
我们需要知道Sonata Admin是自带 Select2的,而且由于代码经过封装,本身是有一套东西的。
如果你的数据量不大,直接调用sonata的实体映射其实就满足需求了,这里我遇到的是,数据库有10几万数据,不可能一次性都查出来,肯定是需要直接去搜索数据库的。
而sonata自带的那个搜索框官网根本没有这方面的信息,加上Form的一些规则限制,搞的刚刚接触这个框架的我一脸懵逼。
可能是Symfony框架在国内的生态比较差,相关的教程或博客太少了。
我们不仅仅需要和数据库做简单的绑定,我们还需要和非数据库的数据源做绑定,以及复杂关系型数据库的绑定。
怎么解决
首先我们需要自己应该怎么去实现整个流程
我们需要用到一个表单类型 ChoiceType 用于修改数据时对搜索框的数据进行一个加载。
然后我们需要对这个表单类型设定的字段添加一些配置,multiple=>true 让这个表单类型支持多个值。
‘attr’ => [‘data-sonata-select2’ => ‘false’] 不让Sonata自动去给我们这个字段渲染Select2,如果让他去渲染,我们就什么事情都做不了。
// 调用数据加载方法
$doctrine= $this->registry;
$em = $doctrine->getManager();
$list=$em->getRepository(MyTable::class)
->findPoiList(explode('/',$_SERVER['REQUEST_URI'])[5]);
// 通过截取当前页面的URL,查看是否是修改操作,如果是添加操作,将返回一个NULL
// 如果是修改操作,将返回已添加的数据
$formMapper
->add('features',ChoiceType::class,[
'choices' => $list, //如果有数据,将用于在Select2中显示
'required' => false,
'multiple' => true, //支持多选
'attr' => [
'data-sonata-select2' => 'false' //禁止自动渲染Select2
]
])
这个地方的$list是我做的一个数据加载,用于修改。
实现接口,ajax请求
return [
'msg' => 'ok',
'total_row' => $count ?? 0,
'page' => $page,
'limit' => $limit,
'results' => $arr,
'pagination'=>['more'=>$page*10<$count]
];
这时我们需要一个数据源,用于搜索数据,这个数据源将以接口形式返回数据,我们完全按照Select2官网的要求进行一个配置,数据的来源不限制,这个地方我用的是 多对多关系 数据库查询的数据,可以根据你自己的需要配置,比如从其他程序的 API接口 或者 静态数据 根据你自己的需要配置数据源,最终返回的结果要像上边的结构。
<input id="search" type="hidden" name="search"/>
<label class="control-label required">Search</label>
<div id="mySelect2"></div>
<script>
var obj = $("#mySelect2").select2({
ajax: {
url: url,
delay: 250,
data: function (params) {
var query = {
name: params,
limit: 10
}
// Query parameters will be ?search=[term]&page=[page]
return query;
}, processResults: function (data) {
//这里是用于存储提交的搜索框多选信息的
//我选择让他提交 以“,”分割的字符串
$("#search").val($("#mySelect2").val());
return {
results: data.results,
pagination: data.pagination
};
}
},
width: '100%',
multiple: true,
maximumInputLength: 30,
closeOnSelect: false
});
</script>
如果你看过Select2的文档,或者用过Select2,就知道该怎么用JS自己渲染。
而上述html 和js 代码如何插入到symfony的 twig文件中呢?
1.直接继承模板,在对应位置插入(太粗暴,不推荐)
2.通过setHelps方法,优雅的插入html和JS,并可以通过指定参数,访问不同的API接口数据源(推荐) 此处的htmlstr是我自定义的php方法,返回的是一个html字符串。
->setHelps([
'features'=>$this->htmlstr("/api/url")
])
其实到了这里实现思路就基本完成了,至于里边的细节,比如隐藏自动生成的select,渲染好的select数据怎么写进去,怎么渲染选中的内容,怎么在控制器取到search的值,此处就跳过了。
如果需要完整的代码或者技术指导,可以回复留言。