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.
Ich fühle, dass Ihre Frage zu kompliziert ist. Was genau versuchst du zu tun? –
Finde heraus, wo dein Problem ist und poste dann die entsprechenden Zeilen. Wir sind nicht hier, um dein Problem zu finden. –
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