Что мне нужно
Я должен создать модуль, который позволяет вводить очень простые платные заглушки. Классы, представляющие это, являются PayStub
и Detail
, которые являются POPO и постоянными. Кроме того, Detail
s должно быть сбалансировано относительно Fee
s, что в свою очередь относится к классу, принадлежащему классу Tariff
. Таким образом, у Detail
есть информация о Fee
, которые оплачиваются.Symfony2 - Передача данных между событиями
Чтобы сделать вещи немного более сложными, Fee
пользователь должен платить напрямую зависит от того, что EducationLevel
Enrolment
имеет, который принадлежит к Student
, который также принадлежит к Person
.
То, что я
PayStub
имеет:
- расчетном листке Номер
- Оплата Дата
- Способ оплаты
- Наблюдения
И в Detail
час как:
- Плата
- Проверить, если
- уплаченная сумма
- процент Стипендия
Fee
имеет:
- Номер платы
- Pri се
Который принадлежит к Tariff
классу:
- Общая сумма
- Год
- Уровень образования
Этот вопрос
Вся проблема возникает, когда я строю форма.
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;
}
Что касается поля выбора плата, я не использовал тип объекта, поскольку он будет включать запрос AJAX, где каждый раз, когда я обновляю студента или год, мне придется перезагрузить прототип для типа коллекции, загрузить новые гонорары за год и добавить чрезвычайно сложные события, которые я не уверен, что они будут работать должным образом. Поэтому я решил использовать общий список и выполнить обработку позже.
Здесь все сложнее. Я играл с событиями и решил, что событие PRE_SUBMIT
сможет поймать год и плату, поэтому я просто запрошу его и добавлю в объект. Однако, это событие не имеет дело с отображенным типом данных, так что я должен передать эту новую информацию к другому событию, и я решил, что это был способ сделать это:
$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);
}
));
}
});
Я думал, что я мог бы просто получать данные позже, сопоставьте его вручную и отбросьте (то есть удалите его из формы). Однако событие POST_SUBMIT
не получает объект должным образом, ни в форме (нулевом значении), ни в объекте (тот же выпуск).
Я правильно подошел к этой проблеме? Есть ли более чистый способ сделать это, или я могу просто решить это право таким образом? Спасибо заранее.
Я чувствую, что ваш вопрос слишком сложный. Что именно ты пытаешься сделать? –
Посмотрите, где ваша проблема, а затем просто разместите соответствующие строки. Мы не здесь, чтобы найти вашу проблему. –
Итак, я понимаю, что проблема заключается в вычислении одного из полей формы (платы) на основе значений других полей формы (тип и тариф).Это в основном означает, что это вычисленное поле напрямую не контролируется пользователем, поэтому не должно быть поле формы или части вашего типа PayStubType/DetailType. – nikita2206