2012-06-05 11 views
6

मेरे मार्ग /message/new तक पहुंचने के लिए मैं एक या अधिक ग्राहकों को नया संदेश भेजने के लिए एक फॉर्म दिखाने जा रहा हूं। पर्चा मॉडल (दूसरों के बीच) है Customer संस्थाओं का एक संग्रह:Symfony2 और ParamConverter (0)

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) 
{ 
} 

उत्तर

10

मेरे स्वयं का उत्तर दें: आपको जीवन आसान बनाने की कोई बात नहीं है। मैंने एक त्वरित और गंदे (और संभवतः छोटी गाड़ी) समाधान को कोड किया है जिसे मैं साझा करना चाहता हूं, सबसे अच्छा इंतजार कर रहा हूं।

चेतावनी संपादित करें: यह एक ही कक्षा के साथ दो पैरामीटर कन्वर्टर्स के साथ काम नहीं करेगा।

यूआरएल उदाहरण

/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) 
{ 
} 

विकल्प delimiterGET पैरामीटर विभाजित करने के लिए है, जबकि id एक WHERE id IN... खंड जोड़ने के लिए प्रयोग किया जाता है प्रयोग किया जाता है। दोनों वैकल्पिक हैं।

विकल्प class केवल यह संकेत देने के लिए "हस्ताक्षर" के रूप में उपयोग किया जाता है कि कनवर्टर support होना चाहिए। entity को एक सिद्धांत इकाई का एक एफक्यूसीएन होना चाहिए जबकि 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

आपको शायद अपने सुझाव के लिए '$ विकल्प ['delimiter'] ' –

+0

@ पीटरबाली धन्यवाद के सम्मिलन के आसपास' preg_quote() 'का उपयोग करना चाहिए! – gremo

3

यह देर हो चुकी है, लेकिन @ParamConverter के बारे में latest दस्तावेज़ के अनुसार, आप प्राप्त कर सकते हैं जिस तरह से पालन करें:

* @ParamConverter("users", class="AcmeBlogBundle:User", options={ 
* "repository_method" = "findUsersByIds" 
* }) 

तुम सिर्फ जरूरत है सुनिश्चित करें कि भंडार विधि अल्पविराम (,) अलग मूल्य को संभाल सकता है एस