2016-01-23 9 views
11

मेरे मॉडल में मेरे पास एक पकाने की विधि और संघटक इकाई है। पकाने की विधि इकाई में, संबंध इस तरह परिभाषित किया गया है:सिम्फनी फॉर्म का ऑर्डर कलेक्शनटाइप फ़ील्ड

/** 
* @ORM\OneToMany(targetEntity="Ingredient", mappedBy="recipe", cascade={"remove", "persist"}, orphanRemoval=true) 
* @ORM\OrderBy({"priority" = "ASC"}) 
*/ 
private $ingredients; 

घटक इकाई में:

/** 
* @ORM\ManyToOne(targetEntity="Recipe", inversedBy="ingredients") 
* @ORM\JoinColumn(name="recipe_id", referencedColumnName="id") 
*/ 
private $recipe; 

मैं नुस्खा के लिए CRUD नियंत्रक पर काम कर रहा हूँ और मैं उपयोगकर्ता सामग्री गतिशील रूप से जोड़ने के लिए सक्षम होना चाहते हैं । मैं यह भी चाहता हूं कि उपयोगकर्ता नुस्खा में अपनी प्राथमिकता (ऑर्डर) सेट करने के लिए सामग्री खींचें और छोड़ दें। मैं इसके लिए कलेक्शनटाइप फॉर्म फ़ील्ड का उपयोग कर रहा हूं।

और ट्यूटोरियल के रूप में यह पेज:

http://symfony.com/doc/current/cookbook/form/form_collections.html

जोड़ना और नुस्खा के प्रदर्शन पूरी तरह से अब तक काम कर रहे हैं, लेकिन वहाँ संपादन/अद्यतन कार्रवाई, जो मैं नीचे का वर्णन करने की कोशिश करेंगे के साथ एक समस्या है:

नियंत्रक में, मैं इकाई लोड और इस तरह के फार्म बनाने के लिए:

public function updateAction($id, Request $request) 
    { 
     $em = $this->getDoctrine()->getManager(); 
     $recipe = $em->getRepository('AppBundle:Recipe')->find($id); 


     $form = $this->createEditForm($recipe); 
     $form->handleRequest($request); 

     ... 

    } 

प्रायोरी के बाद से ty डीबी में सहेजा गया है, और मेरे पास @ORM\OrderBy({"priority" = "ASC"}) है, प्रारंभिक लोडिंग और सामग्री का प्रदर्शन ठीक काम करता है। हालांकि यदि उपयोगकर्ता आसपास सामग्री को ड्रैग और ड्रॉप करता है, तो प्राथमिकता मान बदल जाते हैं। यदि फॉर्म सत्यापन त्रुटियां हैं और फ़ॉर्म को बार-बार प्रदर्शित करने की आवश्यकता है, तो फॉर्म के अंदर सामग्री पुराने क्रम में प्रदर्शित हो जाती है, भले ही प्राथमिकता मान अपडेट हो जाएं।

उदाहरण के लिए, मैं डीबी में प्रारंभिक घटक निम्नलिखित => प्राथमिकता मान हैं:

  • एक => 1
  • बी => 2
  • सी => 3

फॉर्म पंक्तियों को क्रम में प्रदर्शित किया जाता है: ए, बी, सी;

उपयोगकर्ता आदेश में परिवर्तन के बाद, मैं है:

  • बी => 1
  • एक => 2
  • सी => 3

लेकिन प्रपत्र पंक्तियों अभी भी प्रदर्शित किए जाते हैं ए, बी, सी के रूप में;

मैं समझता हूँ कि प्रपत्र आदेश ए, बी, सी के साथ शुरू कर दिया गया है, और अद्यतन करने priority ArrayCollection के तत्व आदेश नहीं बदलता है। लेकिन मेरे पास (लगभग) कोई विचार नहीं है कि इसे कैसे बदला जाए।

क्या मैं अब तक की कोशिश की है:

$form->getData(); 
// sort in memory 
$form->setData(); 

यह काम नहीं करता, जाहिरा तौर पर के रूप में यह रूप है जो पहले से ही इनपुट है पर setData() का उपयोग करने के लिए अनुमति नहीं है।

मैंने पंक्तियों को ऑर्डर करने के लिए डेटा ट्रांसफॉर्मर सेट करने का भी प्रयास किया है, लेकिन फ़ॉर्म नए ऑर्डर को अनदेखा करता है।

मैं भी उपयोग करने के लिए पूर्व/पोस्ट FormType कक्षा में संचालकों प्रस्तुत पंक्तियों ऑर्डर करने के लिए कोशिश की है, फिर भी फार्म अभी भी नए आदेश पर ध्यान नहीं देता।

पकाने की विधि इकाई में, परिभाषित sortIngredients() विधि है जो स्मृति में ArrayCollection सॉर्ट करता,

public function sortIngredients() 
    { 
     $sort = \Doctrine\Common\Collections\Criteria::create(); 
     $sort->orderBy(Array(
      'priority' => \Doctrine\Common\Collections\Criteria::ASC 
    )); 

     $this->ingredients = $this->ingredients->matching($sort); 

     return $this; 
    } 

फिर, नियंत्रक में:

$form = $this->createEditForm($recipe); 
    $form->handleRequest($request); 

    $recipe->sortIngredients(); 

    // repeatedly create and process form with already sorted ingredients 
    $form = $this->createEditForm($recipe); 
    $form->handleRequest($request); 

    // ... do the rest of the controller stuff, flush(), etc 

आखिरी बात यह है कि (एक तरह से) काम करता है यह है

यह काम करता है, लेकिन फार्म बनाया है और संसाधित किया जाता है दो बार, और ईमानदारी से यह एक हैक की तरह दिखता है ...

मैं समस्या को हल करने के लिए एक बेहतर तरीका ढूंढ रहा हूं।

उत्तर

9

आप अपने प्रपत्र प्रकार की finishView विधि का उपयोग करने की जरूरत है।

यहाँ कोड का उदाहरण है:

public function finishView(FormView $view, FormInterface $form, array $options) 
{ 
    usort($view['photos']->children, function (FormView $a, FormView $b) { 
     /** @var Photo $objectA */ 
     $objectA = $a->vars['data']; 
     /** @var Photo $objectB */ 
     $objectB = $b->vars['data']; 

     $posA = $objectA->getSortOrder(); 
     $posB = $objectB->getSortOrder(); 

     if ($posA == $posB) { 
      return 0; 
     } 

     return ($posA < $posB) ? -1 : 1; 
    }); 
} 
+3

काम करता है !!! इस पर आधा दिन बिताया ... धन्यवाद। इस विधि के बारे में सिम्फनी वेबसाइट पर बहुत बुरा दस्तावेज नहीं है। – Karolis

संबंधित मुद्दे