访问我的路线/message/new
我将显示一个表单,用于向一个或多个客户发送新消息。表单模型(以及其他)包含Customer
个实体的集合:
class MyFormModel
{
/**
* @var ArrayCollection
*/
public $customers;
}
我想使用customers
GET参数实施自动客户选择,如下所示:
message/new?customers=2,55,543
现在只需拆分,
并进行查询即可获得客户:
public function newAction(Request $request)
{
$formModel = new MyFormModel();
// GET "customers" parameter
$customersIds = explode($request->get('customers'), ',');
// If something was found in "customers" parameter then get entities
if(!empty($customersIds)) :
$repo = $this->getDoctrine()->getRepository('AcmeHelloBundle:Customer');
$found = $repo->findAllByIdsArray($customersIds);
// Assign found Customer entities
$formModel->customers = $found;
endif;
// Go on showing the form
}
如何使用Symfony 2 converters执行相同的操作?像:
public function newAction(Request $request, $selectedCustomers)
{
}
答案 0 :(得分:13)
回答我自己:没有让你生活轻松的事情。我编写了一个快速而肮脏(可能是错误)的解决方案,我想分享,等待最好的解决方案。
编辑警告:这不适用于具有相同类别的两个参数转换器。
/mesages/new?customers=2543,3321,445
/**
* @Route("/new")
* @Method("GET|POST")
* @ParamConverter("customers",
* class="Doctrine\Common\Collections\ArrayCollection", options={
* "finder" = "getFindAllWithMobileByUserQueryBuilder",
* "entity" = "Acme\HelloBundle\Entity\Customer",
* "field" = "id",
* "delimiter" = ",",
* }
* )
*/
public function newAction(Request $request, ArrayCollection $customers = null)
{
}
选项delimiter
用于分割GET
参数,而id
用于添加WHERE id IN...
子句。这两个都是可选的。
选项class
仅用作“签名”来告诉转换器应该support
它。 entity
必须是Doctrine实体的FQCN,而finder
是要调用的存储库方法,应返回查询构建器(默认提供)。
class ArrayCollectionConverter implements ParamConverterInterface
{
/**
* @var \Symfony\Component\DependencyInjection\ContainerInterface
*/
protected $container;
public function __construct(ContainerInterface $container)
{
$this->container = $container;
}
function apply(Request $request, ConfigurationInterface $configuration)
{
$name = $configuration->getName();
$options = $this->getOptions($configuration);
// Se request attribute to an empty collection (as default)
$request->attributes->set($name, new ArrayCollection());
// If request parameter is missing or empty then return
if(is_null($val = $request->get($name)) || strlen(trim($val)) === 0)
return;
// If splitted values is an empty array then return
if(!($items = preg_split('/\s*'.$options['delimiter'].'\s*/', $val,
0, PREG_SPLIT_NO_EMPTY))) return;
// Get the repository and logged user
$repo = $this->getEntityManager()->getRepository($options['entity']);
$user = $this->getSecurityContext->getToken()->getUser();
if(!$finder = $options['finder']) :
// Create a new default query builder with WHERE user_id clause
$builder = $repo->createQueryBuilder('e');
$builder->andWhere($builder->expr()->eq("e.user", $user->getId()));
else :
// Call finder method on repository
$builder = $repo->$finder($user);
endif;
// Edit the builder and add WHERE IN $items clause
$alias = $builder->getRootAlias() . "." . $options['field'];
$wherein = $builder->expr()->in($alias, $items);
$result = $builder->andwhere($wherein)->getQuery()->getResult();
// Set request attribute and we're done
$request->attributes->set($name, new ArrayCollection($result));
}
public function supports(ConfigurationInterface $configuration)
{
$class = $configuration->getClass();
// Check if class is ArrayCollection from Doctrine
if('Doctrine\Common\Collections\ArrayCollection' !== $class)
return false;
$options = $this->getOptions($configuration);
$manager = $this->getEntityManager();
// Check if $options['entity'] is actually a Dcontrine one
try
{
$manager->getClassMetadata($options['entity']);
return true;
}
catch(\Doctrine\ORM\Mapping\MappingException $e)
{
return false;
}
}
protected function getOptions(ConfigurationInterface $configuration)
{
return array_replace(
array(
'entity' => null,
'finder' => null,
'field' => 'id',
'delimiter' => ','
),
$configuration->getOptions()
);
}
/**
* @return \Doctrine\ORM\EntityManager
*/
protected function getEntityManager()
{
return $this->container->get('doctrine.orm.default_entity_manager');
}
/**
* @return \Symfony\Component\Security\Core\SecurityContext
*/
protected function getSecurityContext()
{
return $this->container->get('security.context');
}
}
arraycollection_converter:
class: Acme\HelloBundle\Request\ArrayCollectionConverter
arguments: ['@service_container']
tags:
- { name: request.param_converter}
答案 1 :(得分:3)
已经很晚了,但根据latest关于@ParamConverter的文档,您可以按照以下方式实现:
* @ParamConverter("users", class="AcmeBlogBundle:User", options={
* "repository_method" = "findUsersByIds"
* })
您只需要确保存储库方法可以处理逗号(,)分隔值