我有一个实体“ administration”,其中有一个字段“ firstPeriod”。此字段不可为空(在类定义或数据库中均不可为空),也不应该为null,因为此字段永远不应该为空,因此应用程序将失败。
但是,该字段没有默认值,因为如果遗忘的用户仅提交表单而不更改默认值,就会造成混乱。用户必须在这里做出自觉的选择。已经进行了验证,以确保该字段不为空并且在可接受的范围内。
当我尝试呈现表单时,formbuilder组件的'propertyAccessor'抛出此异常:
类型错误:AppBundle \ Entity \ Administration :: getFirstPeriod()的返回值必须为整数类型,返回null
formbuilder似乎试图在设置字段之前获取字段的值,这当然会导致所述异常。
如何处理这种情况,以便在不向用户提供默认值的情况下呈现表单?
要进一步说明:空不是可以的,但是我不能提供任何默认值,用户必须做出有意识的决定。任何直接实例化此实体的开发者也是如此。必须在实体持久化之前提供它,但是我不能给出默认值,因为如果保留默认值,该应用程序将无法运行12次(共13次)。
很抱歉出现下面的混乱情况,“代码示例”无法很好地处理此代码
我的(已截断的)实体
namespace AppBundle\Entity;
将Doctrine \ ORM \ Mapping用作ORM;
/ ** *行政 * * @ORM \ Table(name =“ administration”) * @ORM \ Entity(repositoryClass =“ AppBundle \ Repository \ AdministrationRepository”) * / 班级管理 { / ** * @var int * * @ORM \ Column(name =“ id”,type =“ integer”) * @ORM \ Id * @ORM \ GeneratedValue(strategy =“ AUTO”) * / 私人$ id;
/**
* @var int
*
* @ORM\Column(name="first_period", type="smallint", nullable=false)
*/
private $firstPeriod;
/**
* Get id.
*
* @return int
*/
public function getId()
{
return $this->id;
}
/**
* @return int
*/
public function getFirstPeriod(): int
{
return $this->firstPeriod;
}
/**
* @param int $firstPeriod
*/
public function setFirstPeriod(int $firstPeriod): void
{
$this->firstPeriod = $firstPeriod;
}
}
我的(被截断的)formType(据我所知,这是我最好的格式):
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('firstPeriod', null, [
'label' => 'First period'
])
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Administration::class
]);
}
public function getBlockPrefix()
{
return 'app_bundle_administration_type';
}
}
我的控制器:
namespace AppBundle\Controller\Admin;
class AdministrationController extends Controller
{
public function editAction(
EntityManager $em,
Router $router,
Security $security,
Session $session,
LoggerInterface $logger,
Request $request,
Administration $administration = null
): Response {
if ($administration === null) {
$new = true;
$administration = new Administration();
$pageTitle = 'New';
} else {
$new = false;
$pageTitle = 'Edit';
}
$breadcrumbs->add($crumbs);
$form = $this->createForm(AdministrationType::class, $administration);
$form->handleRequest($request);
if ($form->isSubmitted() && $form->isValid()) {
/** @var Administration $administration */
$administration = $form->getData();
try {
$em->persist($administration);
$em->flush();
} catch (ORMException $e) {
$logger->critical($e->getMessage());
$session->getFlashBag()->add('error', 'Database error.');
if ($new) {
return $this->redirectToRoute('administration_new');
} else {
return $this->redirectToRoute(
'administration_edit',
['administration' => $administration->getId()]
);
}
}
$session->getFlashBag()->add('success', 'Success!');
return $this->redirectToRoute('administration_index');
}
return $this->render(':Admin/Administration:edit.html.twig', [
'administrationForm' => $form->createView(),
'pageTitle' => $pageTitle
]);
}
}
我的验证:
AppBundle\Entity\Administration:
properties:
firstPeriod:
- NotBlank:
message: 'adm.firstperiod.empty'
- Range:
min: 1
max: 13
minMessage: 'adm.firstperiod.too_low'
maxMessage: 'adm.firstperiod.too_high'
答案 0 :(得分:1)
由于symfony表单使用属性修饰符,如@Cerad所说,您可以在表单中添加未映射的字段,并在表单事件中获取/设置该字段,并添加获取未初始化$ first_period的特定方法...
示例代码可能是...
<?php
namespace App\Entity;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity(repositoryClass="App\Repository\AdministrationRepository")
*/
class Administration
{
/**
* @ORM\Id()
* @ORM\GeneratedValue()
* @ORM\Column(type="integer")
*/
private $id;
/**
* @ORM\Column(type="integer")
*/
private $first_period;
public function getId(): ?int
{
return $this->id;
}
public function getFirstPeriod(): int
{
return $this->first_period;
}
public function setFirstPeriod(int $first_period): self
{
$this->first_period = $first_period;
return $this;
}
public function getFirstPeriodOrNull(): ?int
{
return $this->first_period;
}
}
<?php
namespace App\Form;
use App\Entity\Administration;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\FormBuilderInterface;
use Symfony\Component\OptionsResolver\OptionsResolver;
use Symfony\Component\Form\FormEvent;
use Symfony\Component\Form\FormEvents;
class AdministrationType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('first_period', null, [
'mapped' => false,
'required' => false,
])
->addEventListener(FormEvents::PRE_SET_DATA, function(FormEvent $event) {
/** @var Administration */
$a = $event->getData();
$event->getForm()->get('first_period')->setData($a->getFirstPeriodOrNull());
})
->addEventListener(FormEvents::POST_SUBMIT, function(FormEvent $event) {
$f = $event->getForm()->get('first_period')->getData();
if (is_int($f)) {
/** @var Administration */
$a = $event->getData();
$a->setFirstPeriod($f);
}
});
;
}
public function configureOptions(OptionsResolver $resolver)
{
$resolver->setDefaults([
'data_class' => Administration::class,
]);
}
}
在Symphony 4.2中可以正常工作