Search code examples
typo3fluidtypo3-10.x

How to fix 'Field doesn't have a default value'?


I am using femanager in TYPO3 10.4 for front end registration. I have created some new fields and they all work fine except for the textarea ones.

Submitting the registration form gives me the error Field 'my_new_field' doesn't have a default value'

The entry in my fe_users.sql looks like this:

my_new_field text DEFAULT '' NOT NULL

My user.php has the same setup for my textarea as it does for my input fields:

protected $myNewField;
public function getMyNewField(): string
{
  return $this->myNewField;
}
public function setMyNewField($myNewField): void
{
  $this->myNewField = $myNewField;
}

So I tried setting the sql to NULL, and this enables the registration to work.

However the Show Fluid template now gives the error getMyNewField() must be of the type string, null returned when I use <f:if condition="{user.myNewField}">


Solution

  • analysis

    Let's check your field definition first:

    my_new_field text DEFAULT '' NOT NULL
    

    NOT NULL tells the database that the value must not be null, and it is required to have it set for an INSERT statement. Generally it would use the DEFAULT value if NOT set or set as NULL in the insert statement.

    However, declaring a DEFAULT value for an TEXT field is not allowed by all database vendors TYPO3 supports - so it's not cross database compatible.

    However the Show Fluid template now gives the error getMyNewField() must be of the type string, null returned when I use <f:if condition="{user.myNewField}">

    Your model has an untyped property, neither nativ nor having a docblock comment. At least the docblock comment needs to be there, albeit not being the solution here. With PHP7.4 you could use native typeing here. Additionally, you should set a proper default value here - and that means having a default assignment to an empty string.

    The fluid error occured, because the property could be empty (null) but you had a typed return value (string) - which is not compatible and hence the error message from PHP.

    solution

    I would suggest to use following in your ext_emconf.sql

    my_new_field text NOT NULL
    

    to avoid both traps for all DBMS systems. This still enforces that a proper value needs to be set (string) and cannot be omitted by any sql statement inserting row(s).

    Instead of declaring the default value on the database level, configure it in your TCA definition for that field Configuration/TCA/my_table.php

    return [
      'my_new_field' => [
        // ...
        'config' => [
          'type' => 'textarea',
          'default' => '',
          // ...
        ],
      ],
    ];
    

    and use a default for the property in your extbase model:

    /**
     * @var string
     **/
    protected $myNewField = '';
    
    public function getMyNewField(): string
    {
        return (string)$this->myNewField;
    }
    
    /**
     * @param string $myNewField
     **/
    public function setMyNewField($myNewField): void
    {
        $this->myNewField = (string)$myNewField;
    }
    

    Depending on the minimum PHP version you can ensure for development and production/staging you may also add native types to the setter and the property. So with PHP7.4 ensured you could use following in your extbase model

    /**
     * @var string
     **/
    protected string $myNewField = '';
    
    public function getMyNewField(): string
    {
        return $this->myNewField;
    }
    
    public function setMyNewField(string $myNewField): void
    {
        $this->myNewField = $myNewField;
    }
    

    edit1: You should update that field for existing records if you change this now:

    UPDATE fe_users SET my_new_field = '' WHERE my_new_field IS NULL;
    

    or with a QueryBuilder in an custom update wizard:

    $queryBuilder = GeneralUtility::makeInstance(ConnectionPool::class)
      ->getConnectionForTable('fe_users')
      ->getQueryBuilder();
    $queryBuilder
      ->update('fe_users')
      ->set('my_new_field', '')
      ->where(
        $queryBuilder->expr()->isNull('my_new_field')
      )
      ->executeStatement();