Php 条令失败,列不能为空错误;看不出值如何可以为空

Php 条令失败,列不能为空错误;看不出值如何可以为空,php,symfony,doctrine-orm,doctrine,symfony4,Php,Symfony,Doctrine Orm,Doctrine,Symfony4,我有一个Symfony 4应用程序,它使用条令进行所有数据库访问。 该表中有许多列是用NOTNULL定义的 编写实体类中的所有getter方法时,如果当前值为null,它们将返回空字符串 public function getApartment(): string { return $this->apartment ?? ''; } 我的理解是,在将对象持久化到数据库中时,条令调用实体的getter方法来检索当前值 我不知道像上面那样编写的getter如何可能导致空值,但是这种错误偶

我有一个Symfony 4应用程序,它使用条令进行所有数据库访问。 该表中有许多列是用NOTNULL定义的

编写实体类中的所有getter方法时,如果当前值为null,它们将返回空字符串

public function getApartment(): string
{
  return $this->apartment ?? '';
}

我的理解是,在将对象持久化到数据库中时,条令调用实体的getter方法来检索当前值

我不知道像上面那样编写的getter如何可能导致空值,但是这种错误偶尔会发生。请注意,这种情况并非总是发生,只是有时发生,而且我还没有发现任何类型的模式

除了getter之外,实体的几个字段定义都带有@Assert\NotBlank注释,因此表单组件不应该从isValid方法返回true

下面是var/log/prod.log中稍微编辑的示例错误:

[2020-03-02 22:23:22] request.CRITICAL: Uncaught PHP Exception 
  Doctrine\DBAL\Exception\NotNullConstraintViolationException: 
  "An exception occurred while executing 
    'INSERT INTO FreeClassQueries 
    (apartment, city, comment, dateCreated, email, migrated, name, phone, state, street, zip, spamInfo) 
    VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' 
    with params [null, null, null, "2020-03-02 22:23:20", null, null, null, null, null, null, null, null]:  
  SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'apartment' cannot be null" 
    at /var/www/prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php line 103 
    {"exception":"[object] (Doctrine\\DBAL\\Exception\\NotNullConstraintViolationException(code: 0): 
    An exception occurred while executing 
      'INSERT INTO FreeClassQueries 
      (apartment, city, comment, dateCreated, email, migrated, name, phone, state, street, zip, spamInfo) 
      VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)' 
      with params [null, null, null, \"2020-03-02 22:23:20\", null, null, null, null, null, null, null, null]:
  SQLSTATE[23000]: Integrity constraint violation: 1048 
  Column 'apartment' cannot be null 
    at /var/www/prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/AbstractMySQLDriver.php:103, 
  Doctrine\\DBAL\\Driver\\PDOException(code: 23000): SQLSTATE[23000]: 
    Integrity constraint violation: 1048 Column 'apartment' cannot be null 
    at /var/www/prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:123, 
  PDOException(code: 23000): SQLSTATE[23000]: Integrity constraint violation: 1048
    Column 'apartment' cannot be null at /var/www/prod/vendor/doctrine/dbal/lib/Doctrine/DBAL/Driver/PDOStatement.php:121)"} []
如您所见,唯一不为null的值是dateCreated。它是通过使用@ORM\PrePersist注释标记的方法设置的

仅当表单已提交且有效时,操作方法才会尝试持久化对象,这意味着所有标记为@Verify\NotBlank的字段都不能为空

$form->handleRequest( $request );
if( $form->isSubmitted() && $form->isValid())
{
  $em = $this->getEntityManager();
  $repository = $em->getRepository( FreeClassQuery::class );
  $em->persist( $classQuery );
  $em->flush();
  ...
}

您假设条令将使用实体的getter,但事实并非如此。从信条中:

条令从不涉及实体中方法的公共API 类,如getter和setter,也不是构造函数方法。相反,它使用反射从实体对象获取/设置数据。当Doctrine从DB获取数据并将其保存回数据库时,get/set方法中的任何代码都不会被隐式考虑

不要将此逻辑放在getter中,只需为对象属性创建一个默认有效值。这也将有助于您获得更干净的getter,而无需借助技巧:

class Foo
{
    private string $apartment = '';

    public function getApartment(): string
    {
        return $this->apartment;
    }
}

您有一个基本的Php问题:您的变量被视为“falsy”。变量是未定义、null、false、0或空字符串的变量视为空

可能的解决方法:设置默认值


无论如何,请尝试对您的应用程序最好的方法,并小心处理。

我的理解是,在将对象持久化到数据库中时,条令调用实体的getter方法来检索当前值。从技术上讲,这就是所谓的错误思维。条令使用反射直接访问属性,因此您需要对其进行初始化,以排除存在空值的可能性。正如下面回答的那样,条令使用反射进行水合作用,但问题的原因可能是您没有表单正在使用的setter或表单未正确映射。在flush之前尝试转储$classQuery并查看其内部状态。我将进行适当的更改,查看其运行情况,稍后再发回。谢谢