构建搜索表单的最佳方式是什么?我将在我的基础分支模板中渲染,以便它始终可见?
我根据需要创建了一个表单类型类,可以在控制器中使用它然后在模板上呈现表单但是对其他控制器和模板做同样的事情是没有意义的所以我写了一个service:
<?php
namespace MyBundle'Services;
use Symfony'Component'Form'FormFactory;
use MyBundle'Form'FulltextSearchType;
class FulltextSearch {
private $formFactory;
public function __construct(FormFactory $formFactory) {
$this->formFactory = $formFactory;
}
public function mySearch() {
$form = $this->formFactory->createBuilder('MyBundle'Form'FulltextSearchType');
return $form->getForm()->createView();
//return $form->createView();
}
}
还在服务中定义了服务。Yml和配置。然后在模板中渲染:
<form action="{{ path('my_search') }}" method="post">
{{ form_widget(fulltextSearch.mySearch) }}
</form>
它工作,我得到表单,我得到表单提交后的请求,但我怀疑这是最好的方式来实现我的问题标题说
这可以通过将服务作为全局变量注入到所有模板中来实现:
首先,用它的依赖定义你的服务:
services:
app.fulltextsearch:
class: MyBundle'Services'FulltextSearch
arguments: ['@form.factory']
第二,将此服务定义为全局Twig变量:
# app/config/config.yml
twig:
# ...
globals:
fulltextSearch: '@app.fulltextsearch'
就是这样!
无论何时在模板中访问全局变量,都将从服务容器中请求该服务,并且您可以访问该对象。
另一方面,我建议您在FulltextSearch::mySearch
方法中创建整个表单,以实现主要的可重用性:
class FulltextSearch
{
private $router;
//...
public function mySearch() {
$form = $this->formFactory->createBuilder()
->setAction($this->router->generate('my_search'))
->add('search', FulltextSearch::class)
->getForm();
return $form->createView();
}
}
注意:确保在app.fulltextsearch
定义中注入@router
服务以及'@form.factory'
。
接下来,您的基本搜索模板看起来像这样,(不需要<form>
标签,action
和method
属性,最后一个默认是POST
):
{{ form(fulltextSearch.mySearch) }}
我不知道这是不是最好的方法,但是:
创建一个控制器动作
public function getSearchFormAction(Request $request) {
...
return $this->render( 'YourBundle:searchform.html.twig', array( 'form' => $form->createView() ));
}
模板中的
{{ render(controller('YourBundle:YourController:getSearchForm')) }}
你也可以使用ajax函数来搜索,就像这样,你可以调用一个控制器,它只在动态div中返回答案或html中的其他东西,你可以预先制作一个自动完成的搜索,并将第二个在提交时启动的搜索添加到"表单"中。
info:为了更灵活(个人喜好),你可以用手写的表单代替FormType.php,因为这不是一个错误的表单,它只是一个输入。
FOR AJAX SEARCH: Controller.php
<?php
namespace AppBundle'Controller;
use Sensio'Bundle'FrameworkExtraBundle'Configuration'Route;
use Symfony'Bundle'FrameworkBundle'Controller'Controller;
use Symfony'Component'HttpFoundation'Request;
use Symfony'Component'HttpFoundation'Response;
use Symfony'Component'Serializer'Serializer;
use Symfony'Component'Serializer'Encoder'XmlEncoder;
use Symfony'Component'Serializer'Encoder'JsonEncoder;
use Symfony'Component'Serializer'Normalizer'GetSetMethodNormalizer;
use YourBundle'Entity'Yourentity;
class SearchController extends Controller
{
public function ajaxAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$string = $this->getRequest()->request->get('recherche');
$limit = 3;
$listsearch = $em->getRepository('YourBundle:Yourentity')->myFind($string, $limit);
$encoders = array(new XmlEncoder(), new JsonEncoder());
$normalizers = array(new GetSetMethodNormalizer());
$serializer = new Serializer($normalizers, $encoders);
$jsonContent = $serializer->serialize($listsearch, 'json');
$response = new Response($jsonContent);
return $response;
}
}
实体的存储库用于定义您自己的find方法:
<?php
namespace YourBundle'Repository;
/**
* YourentityRepository
*
* This class was generated by the Doctrine ORM. Add your own custom
* repository methods below.
*/
class YourentityRepository extends 'Doctrine'ORM'EntityRepository
{
public function myFind($string, $limit)
{
return $this->getEntityManager()->createQuery('SELECT a FROM YourBundle:Yourentity a
WHERE a.onedata(name, id...) LIKE :string OR a.anotherdata LIKE :string')
->setParameter('string','%'.$string.'%')
->setMaxResults($limit)
->getResult();
}
}
view.html。Twig + script
<form method="POST" action="" class="navbar-form navbar-left inline-form">
<input id="search" type="text" name="recherche" class="input-sm form-control">
<input type="submit" value="Search" class="btn-primary btn">
<div id="sresult" class="search-result">
</div>
</form>
<script>
$('#search').keyup(function() {
recherche = $(this).val();
$.ajax({
type: "POST",
url: "{{ path('search') }}",
dataType: "json",
data: {recherche : recherche},
success : function(response) {
document.getElementById("sresult").innerHTML = "";
if(response.length === 1){
var elmt = document.getElementById("sresult");
elmt.style.display = "block";
var result = response[0];
document.getElementById("sresult").innerHTML = "<div class=resultat><p> Title : "+result.title+"<br/>oneData : "+result.data+"<br/>Gender : "+result.gender+"</p><br/></div>";
}
else {
for(var i =0;i <= response.length-1;i++) {
var elmt = document.getElementById("sresult");
elmt.style.display = "block";
var result = response[i];
document.getElementById("sresult").innerHTML += "<div class=resultat><p> Title : "+result.title+"<br/>Data : "+result.data+"<br/>Gender : "+result.gender+"</p><br/></div>";
}
}
}
});
});
</script>
(这是您使用的实体应用结果的示例)
:
Controller.php :
public function searchAction(Request $request)
{
$em = $this->getDoctrine()->getManager();
$user = $this->container->get('security.context')->getToken()->getUser();
$tabsearch = [];
$search = $request->request->get('recherche');
if ($search == null) {
$searchresult = $em->getRepository('AppBundle:User')->findAll();
}
else {
$searchresult = $em->getRepository('AppBundle:User')->findByUsername($search);
}
foreach ($searchresult as $datasearch)
{
$thisGender = $em->getRepository('AppBundle:datauser')->findOneByIduser($datasearch->getId());
$tabsearch[] = array(
'gender' => $thisGender->getGenre(),
'username' => $datasearch->getUsername(),
'lastlogin' => $datasearch->getLastlogin(),
'id' => $datasearch->getId(),
);
}
return $this->render('default/search.html.twig', array(
'tabsearchs' => $tabsearch,
));
}
对于视图,它与AJAX相同,因此您可以将这两种方法应用于搜索栏的相同输入,我已经从我的一个项目中获取了这一点,因此只需修改应用于您自己的项目(实体和数据)。search.html.twig for result由您定义,使用tabsearch和twig for循环({% for search in tabsearch %} ... ...)
路由如下:
经典写法:
classical_search:
path: /result/search
defaults: { _controller: YourBundle:Default:search }
Ajax方式:
ajax_search:
path: /search
defaults: { _controller: YourBundle:Default:ajax}