【发布时间】:2019-05-14 21:28:40
【问题描述】:
我有一个实体“管理”,它有一个字段“firstPeriod”。该字段不可为空(无论是在类定义中还是在数据库中),也不应该为空,因为该字段永远不应为空,应用程序将失败。
但是,这个字段没有默认值,因为如果一个不知情的用户只是简单地提交表单而不更改默认值,就会出现混乱。用户必须在这里做出有意识的选择。已进行验证以确保该字段不为空且在可接受的范围内。
当我尝试渲染表单时,formbuilder 组件的“propertyAccessor”会抛出此异常:
类型错误:AppBundle\Entity\Administration::getFirstPeriod()的返回值必须是整数类型,返回null
看起来表单构建器在设置字段之前尝试获取字段的值,这当然会导致上述异常。
如何处理这种情况,以便在不向用户提供默认值的情况下呈现表单?
进一步澄清:Null 是不行的,但我也不能提供任何默认值,用户必须做出有意识的决定。任何直接实例化该实体的开发人员也是如此。它必须在实体被持久化之前提供,但我不能给出默认值,因为如果保留默认值,应用程序将无法运行 13 次中的 12 次。
- 如果我在实体字段“?int”上允许为空,我实际上是在使一个字段可以为空永远不应该为空
- 如果我提供默认值,则可能会盲目接受默认值,这会导致应用程序中的错误结果进一步导致大多数用户很难发现。
- 我已经尝试在formType中设置'empty_data => 0',但无济于事
抱歉下面的混乱,“代码示例”不能很好地处理此代码
我的(截断的)实体:
namespace AppBundle\Entity;
使用 Doctrine\ORM\Mapping 作为 ORM;
/** * 行政 * * @ORM\Table(name="管理") * @ORM\Entity(repositoryClass="AppBundle\Repository\AdministrationRepository") */ 班级管理 { /** * @var 整数 * * @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'
【问题讨论】:
-
只需在您的实体中使用默认值。私人 $firstPeriod = 1;无论如何,这是您想做的事情。如果你能帮助它,让一个实体漂浮在无效数据周围是没有意义的。
-
@Cerad 你读过这个问题吗?
-
当然没看过。随机发布 cmets 更有趣。故意让实体拥有无效数据让我觉得这是一个非常糟糕的主意。但是如果 null 没问题,那么只需将 getFirstPeriod 上的返回类型更改为 ?int。
-
@Cerad Null 不行,但我也不能提供任何默认值,用户必须做出有意识的决定。任何直接实例化该实体的开发人员也是如此。它必须在实体被持久化之前提供,但我不能给出默认值,因为如果保留默认值,应用程序将无法运行 13 次中的 12 次。我将编辑这个问题,希望能更清楚地说明这一点。
-
@Cerad,我希望避免这种情况,当我说我截断了我在此处发布的实体时,我并不是在开玩笑,还有 很多 其他属性和复杂性。我认为这是一件微不足道的事情,我根本不知道修复,比如“使用 ignore_getters 约束”或其他东西:(也许这个问题不像我想象的那么普遍,但它在我们的领域很常见。
标签: symfony symfony-forms