I want to store some options in the DB like this:
'question_options' => [
'exclude' => false,
'label' => 'xxx',
'description' => 'xxx',
'config' => [
'type' => 'json',
'default' => ''
],
],
What would the correct type for my Model.php be?
/**
* questionOptions
*
* @var string ?? array ?? object ?? mixed ??
*/
protected $questionOptions;
Array shows null and string gets escaped when setting it through a setter.
You could make use of TYPO3's TypeInterface
which will get raw data passed as constructor argument by the DataMapper
. This works similar for the PropertyMapper
which does this via the CoreTypeConverter
.
This allows you to use classes which implement the TypeInterface
as type for domain model properties. In this particular case you can automatically convert the raw JSON string to an array-like structure like this:
<?php
declare(strict_types=1);
namespace Acme\Package\Domain\Data;
use TYPO3\CMS\Core\Type\TypeInterface;
final class JsonData extends \ArrayObject implements TypeInterface
{
public function __construct(string $jsonString)
{
$data = json_decode(
json: $jsonString,
associative: true,
flags: \JSON_THROW_ON_ERROR,
);
parent::__construct($data);
}
public function __toString(): string
{
return json_encode(
value: $this,
flags: \JSON_THROW_ON_ERROR,
);
}
}
Your domain model can now use this as property type:
declare(strict_types=1);
namespace Acme\Package\Domain\Model;
use Acme\Package\Domain\Data\JsonData;
use TYPO3\CMS\Extbase\DomainObject\AbstractEntity;
final class Example extends AbstractEntity
{
public ?JsonData $data = null;
}
Now all instances allow you to transparently access the already decoded JSON data. Assuming an object $example1
of this Example
model which has {"foo":"bar"}
as data in its tx_package_domain_model_example.data
column:
$example1->data['foo'];
{example1.data.foo}
You can see a real-life implementation of this in the pagemachine/typo3-formlog
package: