symfony - Symfony2 and ParamConverter(s) -
accessing route /message/new i'm going show form sending new message 1 or more customers. form model has (among others) collection of customer entities:
class myformmodel { /** * @var arraycollection */ public $customers; } i'd implement automatic customers selection using customers parameters, this:
message/new?customers=2,55,543 this working splitting on , , query getting customers:
public function newaction(request $request) { $formmodel = new myformmodel(); // "customers" parameter $customersids = explode($request->get('customers'), ','); // if found in "customers" parameter 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 form } how can same using symfony 2 converters? like:
public function newaction(request $request, $selectedcustomers) { }
answer self: there not such thing make life easy. i've coded quick , dirty (and possibly buggy) solution i'd share, waiting best one.
edit warning: not going work 2 parameter converters same class.
url example
/mesages/new?customers=2543,3321,445 annotations:
/** * @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) { } option delimiter used split get parameter while id used adding where id in... clause. there both optional.
option class used "signature" tell converter should support it. entity has fqcn of doctrine entity while finder repository method invoked , should return query builder (default 1 provided).
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 empty collection (as default) $request->attributes->set($name, new arraycollection()); // if request parameter missing or empty return if(is_null($val = $request->get($name)) || strlen(trim($val)) === 0) return; // if splitted values empty array return if(!($items = preg_split('/\s*'.$options['delimiter'].'\s*/', $val, 0, preg_split_no_empty))) return; // repository , logged user $repo = $this->getentitymanager()->getrepository($options['entity']); $user = $this->getsecuritycontext->gettoken()->getuser(); if(!$finder = $options['finder']) : // create new default query builder 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 builder , add in $items clause $alias = $builder->getrootalias() . "." . $options['field']; $wherein = $builder->expr()->in($alias, $items); $result = $builder->andwhere($wherein)->getquery()->getresult(); // set request attribute , we're done $request->attributes->set($name, new arraycollection($result)); } public function supports(configurationinterface $configuration) { $class = $configuration->getclass(); // check if class arraycollection doctrine if('doctrine\common\collections\arraycollection' !== $class) return false; $options = $this->getoptions($configuration); $manager = $this->getentitymanager(); // check if $options['entity'] dcontrine 1 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'); } } service definition
arraycollection_converter: class: acme\hellobundle\request\arraycollectionconverter arguments: ['@service_container'] tags: - { name: request.param_converter}
Comments
Post a Comment