2014-01-31 16 views
5

Was ich brauche

Ich muss ein Modul bauen, das die Eingabe von sehr einfachen Pay-Stubs ermöglicht. Die Klassen, die dies darstellen, sind PayStub und Detail, die POPO und persistent sind. Darüber hinaus muss die Detail s gegen die Fee s, die wiederum eine Klasse ist, die zu einer Tariff Klasse gehört ausgeglichen werden. So hat die Detail Informationen über die Fee, die bezahlt wird.Symfony2 - Pass Daten zwischen Ereignissen

Um die Dinge etwas komplizierter zu machen, die Fee der Benutzer hängt davon ab, direkt, was EducationLevel die Enrolment hat zahlen müssen, was zu einem Student gehört, was zu einem Person gehört auch.

Was ich habe

Die PayStub hat:

  • Pay Stub Anzahl
  • Zahlungstermin
  • Zahlungs-Methode
  • Beobachtungen

Und die Detail h wie:

  • Fee
  • prüfen, falls vorhanden
  • Betrag bezahlt
  • Scholarship Prozentsatz

Die Fee hat:

  • Anzahl der Gebühr
  • Pri ce

, die zu einer Tariff Klasse gehört:

  • Gesamtbetrag
  • Jahr
  • Ausbildungsniveau

Das Problem

Das ganze Problem kommt, wenn ich bauen die Form.

PayStubType:

class PayStubType extends AbstractType 
{ 
    //I need to pass the years and the DAOs because I need to use them later 
    public function __construct(School $c, DAOPerson $dao, $years = array(), DAOFee $dc) 
    { 
     $this->c = $c; 
     $this->dao = $dao; 
     $this->years = $years; 
     $this->dc = $dc; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $sch = $this->c; 
     $std = $this->dao->getEnroledStudents($sch)[0]; 
     $builder->add('student', 'entity', array(
        'label' => 'Student', 
        'class' => 'System\SchoolsBundle\Person\Person', 
        'mapped' => false, 
        'query_builder' => $this->dao->getEnroledStudents($sch, true) 
       ))->add('payDate', 'datetime', array(
        'label' => 'Payment Date', 
        'widget' => 'single_text', 
        'input' => 'datetime', 
        'format' => 'dd/MM/yyyy' 
       ))->add('payMethod', 'choice', array(
        'label' => 'Payment Method', 
        'choices' => EPaymentMethod::$arrPayMethods 
       ))->add('stubNumber', 'text', array(
        'label' => 'Pay Stub No.', 
        'required' => false 
       ))->add('observation', 'textarea', array(
        'label' => 'Observations', 
        'max_length' => 1024, 
        'required' => false 
       )); 
     $years = $this->years; 
     $dc = $this->dc; 
     $builder->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) use ($sch, $std, $years, $dc) { 
      $form = $event->getForm(); 
      $data = $event->getData(); 
      $stdRole = $std->getInfoContainer()->getRole('STUDENT'); 
      $form->add('details', 'collection', array(
       'type' => new DetailType($sch, $std, $years, $dc), 
       'label' => false, 
       'allow_add' => true, 
       'by_reference' => false 
      )); 
     }); 

    public function getName() 
    { 
     return 'paystubtype'; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'System\SchoolsBundle\Payments\PayStub' 
     )); 
    } 

    private $c; 
    private $dao; 
    private $years; 
    private $dc; 
} 

DetailType:

class DetailType extends AbstractType 
{ 
    public function __construct(School $c, Student $al, $years = array(), DAOFee $dc) 
    { 
     $this->c = $c; 
     $this->al = $al; 
     $this->years = array_reverse($years, true); 
     $this->dc = $dc; 
    } 

    public function buildForm(FormBuilderInterface $builder, array $options) 
    { 
     $sch = $this->c; 

     $list = array(); //List of scholarship percentages 
     for ($i=0; $i<=100; $i++) { 
      $list[(string)($i/100)] = $i."%"; 
     } 

     $pref = min($cole->getSchoolYear(), array_values($this->years)[0]); 

     $builder->add('ct', 'choice', array(
        'label' => false, 
        'mapped' => false, 
        'choices' => Fee::$arrFees //A list of possible fees. The only possible values are the enrolment price and one fee per school month. Read after the code for a longer explanation about how this works. 
       ))->add('year', 'choice', array(
        'mapped' => false, 
        'label' => false, 
        'choices' => $this->years, //Years that have tariffs registered 
        'preferred_choices' => array($pref) //The minimum between the current school year and the last year where tariffs were registered 
       ))->add('cheque', 'entity', array(
        'label' => false, 
        'class' => 'System\SchoolsBundle\Payments\Cheque', 
        'property' => 'numberAndBank', 
        'required' => false, 
        'empty_value' => 'Select Cheque', 
        'query_builder' => function(EntityRepository $er) use ($sch) { 
         return $er->createQueryBuilder('u') 
           ->where('u.school = ?1') 
           ->orderBy('u.number') 
           ->setParameter(1, $sch); 
        } 
       ))->add('amount', 'text', array(
        'label' => false, 
       ))->add('scholarshipPerc', 'choice', array(
        'label' => false, 
        'choices' => $list 
       )); 
     // From here on, it gets blurry. Read below for more. 
    } 

    public function getName() 
    { 
     return 'detailtype'; 
    } 

    public function setDefaultOptions(OptionsResolverInterface $resolver) 
    { 
     $resolver->setDefaults(array(
      'data_class' => 'System\SchoolsBundle\Payments\Detail' 
     )); 
    } 

    private $c; 
    private $al; 
    private $years; 
    private $dc; 
} 

In Bezug auf die Gebühr Auswahlfeld, habe ich nicht einen Entitätstyp verwenden, da es eine AJAX-Abfrage beinhalten würde, wo ich jedes Mal die Schüler aktualisieren oder das Jahr, ich müsste den Prototyp für den Sammeltyp neu laden, die neuen Gebühren für das Jahr laden und extrem komplexe Ereignisse hinzufügen, von denen ich nicht sicher bin, dass das richtig funktionieren würde. Also entschied ich mich, eine generische Liste zu verwenden und die Verarbeitung später durchzuführen.

Hier werden die Dinge jedoch komplex. Ich spielte mit den Ereignissen herum und entschied, dass ein PRE_SUBMIT Event in der Lage sein würde, das Jahr und die Gebühr zu erfassen, also frage ich einfach danach und füge es dem Objekt hinzu. Allerdings ist das Ereignis nicht mit dem zugeordneten Datentyp umgehen, so muss ich auf ein anderes Ereignis diese neuen Informationen übergeben und ich beschlossen, dies war die Art und Weise, es zu tun:

$builder->addEventListener(FormEvents::PRE_SUBMIT, function(FormEvent $event) use ($sch, $al) { 
     $form = $event->getForm(); 
     $data = $event->getData(); 
     if (array_key_exists('ct', $data) == true && array_key_exists('year', $data) == true) { 
      $et = $al->getEnrolmentBySchool($sch, $data['year'])->getEducationLevel(); 
      $year = $data['year']; 
      $feeNumber = $data['ct']; 
      $form->add('fee', 'entity', array(
       'label' => false, 
       'class' => 'System\SchoolsBundle\Payments\Fee', 
       'property' => 'feeName', 
       'query_builder' => function(EntityRepository $er) use ($et, $year, $feeNumber) { 
        return $er->createQueryBuilder('u') 
          ->innerJoin('u.tariff', 'a') 
          ->innerJoin('a.edType', 'et') 
          ->where('et = ?1') 
          ->andWhere('a.year = ?2') 
          ->andWhere('u.feeNumber = ?3') 
          ->orderBy('u.feeNumber') 
          ->setParameter(1, $et) 
          ->setParameter(2, $year) 
          ->setParameter(3, $feeNumber); 
       } 
      )); 
     } 
    }); 

Ich dachte, ich könnte nur das erhalten Daten später, map von Hand, und verwerfen Sie es (dh entfernen Sie es aus dem Formular). Das Ereignis POST_SUBMIT empfängt das Objekt jedoch nicht ordnungsgemäß, weder in der Form (Nullwert) noch im Objekt (gleiches Problem).

Bin ich dieses Problem richtig? Gibt es einen saubereren Weg, oder kann ich dieses Recht einfach so lösen? Danke im Voraus.

+8

Ich fühle, dass Ihre Frage zu kompliziert ist. Was genau versuchst du zu tun? –

+4

Finde heraus, wo dein Problem ist und poste dann die entsprechenden Zeilen. Wir sind nicht hier, um dein Problem zu finden. –

+0

So, wie ich es verstehe, ist das Problem, eines der Formularfelder (Gebühr) auf der Grundlage der Werte anderer Formularfelder (ed. Typ und Tarif) zu berechnen.Es bedeutet im Grunde, dass dieses berechnete Feld nicht direkt von einem Benutzer kontrolliert wird und daher kein Formularfeld oder ein Teil Ihres PayStubType/DetailType sein sollte. – nikita2206

Antwort

0

Ich würde vorschlagen, ein paar Überlegungen:
Die erste ist über den Code, ich denke, die Logik in Ihrem Formular beginnt ein wenig komplex zu sein, besser zu vermeiden, zu viele Zeilen von Codes in derselben Klasse, so Ich möchte über einen Refactor nach dem SRP (Single Responsibility Principle) nachdenken.

Die zweite Sache ist, dass ich nicht wirklich wissen kann, ob Ihre Vorgehensweise korrekt ist.
Ich könnte es annehmen, und vielleicht könnte die Verwendung von PRE_SUBMIT die Dinge erleichtern, aber ich würde gerne mehr auf Ihre Architektur achten.

Was ich meine ist, wir müssen mehr über die Gebühr Problem verstehen.
Wenn Sie denken, dass Sie den Wert bekommen Zeit in Anspruch nehmen und die einreichen verlangsamen könnte auch Prozess der Form (das hat möglichst schnell sein), Es könnte sich lohnen, über einige Alternativen zu denken:

  • Teilen Sie das Formular in 2 Unterformular (Beispiel 2 Seiten, Schritt 1 und Schritt 2);
  • restrukturieren Sie die Modelldaten und erstellen Sie zum Beispiel eine andere Tabelle oder besser eine Ansicht oder eine API, die den Wert schnell abrufen könnte;
  • Berechnen Sie den Wert später mit einem Cron-Job.

Ich hoffe, diese Sichtweise könnte hilfreich sein.