Risposta a me stesso: non esiste una cosa che ti renda la vita facile. Ho codificato una soluzione rapida e sporca (e probabilmente buggy) che mi piacerebbe condividere, in attesa di una migliore.
AVVISO DI EDIT: non funziona con due convertitori di parametri della stessa classe.
esempio URL
/mesages/new?customers=2543,3321,445
NOTE:
/**
* @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)
{
}
Opzione delimiter
è usato per separare GET
parametro mentre id
viene utilizzato per l'aggiunta di una clausola WHERE id IN...
. Ci sono entrambi facoltativi.
L'opzione class
viene utilizzata solo come "firma" per indicare che il convertitore deve essere support
. entity
deve essere un FQCN di un'entità Doctrine mentre finder
è un metodo di repository da richiamare e deve restituire un generatore di query (quello predefinito fornito).
Converter
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');
}
}
definizione Servizio
arraycollection_converter:
class: Acme\HelloBundle\Request\ArrayCollectionConverter
arguments: ['@service_container']
tags:
- { name: request.param_converter}
Probabilmente dovresti usare 'preg_quote()' per l'inserimento di '$ opzioni ['delimitatore']' –
@PeterBailey grazie per il tuo suggerimento! – gremo