How to use enumerations

Changed in version 13.0

Create an enumeration

To create a new enumeration you have to extend the class \TYPO3\CMS\Core\Type\Enumeration . Make sure your enumeration is marked as final, this ensures your code only receives a known set of values. Otherwise adding more values by extension will lead to undefined behavior in your code.

Values are defined as constants in your implementation. The names of the constants must be given in uppercase.

A special, optional constant __default represents the default value of your enumeration, if it is present. In that case the enumeration can be instantiated without a value and will be set to the default.

Example:

EXT:my_extension/Classes/Enumeration/LikeWildcard.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Enumerations;

use TYPO3\CMS\Core\Type\Enumeration;

final class LikeWildcard extends Enumeration
{
    public const __default = self::BOTH;

    /**
     * @var int Do not use any wildcard
     */
    public const NONE = 0;

    /**
     * @var int Use wildcard on left side
     */
    public const LEFT = 1;

    /**
     * @var int Use wildcard on right side
     */
    public const RIGHT = 2;

    /**
     * @var int Use wildcard on both sides
     */
    public const BOTH = 3;
}
Copied!

Use an enumeration

You can create an instance of the Enumeration class like you would usually do, or you can use the Enumeration::cast() method for instantiation. The Enumeration::cast() method can handle:

  • Enumeration instances (where it will simply return the value) and
  • simple types with a valid Enumeration value,

whereas the "normal" __construct() will always try to create a new instance.

That allows to deprecate enumeration values or do special value casts before finding a suitable value in the enumeration.

Example:

EXT:my_extension/Classes/SomeClass.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use MyVendor\MyExtension\Enumerations\LikeWildcard;

final class SomeClass
{
    public function doSomething()
    {
        // ...

        $likeWildcardLeft = LikeWildcard::cast(LikeWildcard::LEFT);

        $valueFromDatabase = 1;

        // will cast the value automatically to an enumeration.
        // Result is true.
        $likeWildcardLeft->equals($valueFromDatabase);

        $enumerationWithValueFromDb = LikeWildcard::cast($valueFromDatabase);

        // Remember to always use ::cast and never use the constant directly
        $enumerationWithValueFromDb->equals(LikeWildcard::cast(LikeWildcard::RIGHT));

        // ...
    }

    // ...
}
Copied!

Exceptions

If the enumeration is instantiated with an invalid value, a \TYPO3\CMS\Core\Type\Exception\InvalidEnumerationValueException is thrown. This exception must be caught, and you have to decide what the appropriate behavior should be.

Example:

EXT:my_extension/Classes/SomeClass.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use MyVendor\MyExtension\Enumerations\LikeWildcard;
use TYPO3\CMS\Core\Type\Exception\InvalidEnumerationValueException;

final class SomeClass
{
    public function doSomething()
    {
        // ...

        try {
            $foo = LikeWildcard::cast($valueFromPageTs);
        } catch (InvalidEnumerationValueException $exception) {
            $foo = LikeWildcard::cast(LikeWildcard::NONE);
        }

        // ...
    }

    // ...
}
Copied!

Implement custom logic

Sometimes it makes sense to not only validate a value, but also to have custom logic as well.

For example, the \TYPO3\CMS\Core\Versioning\VersionState enumeration contains values of version states. Some of the values indicate that the state is a "placeholder". This logic can be implemented by a custom method:

EXT:core/Classes/Versioning/VersionState.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

use TYPO3\CMS\Core\Type\Enumeration;

final class VersionState extends Enumeration
{
    public const __default = self::DEFAULT_STATE;
    public const DEFAULT_STATE = 0;
    public const NEW_PLACEHOLDER = 1;
    public const DELETE_PLACEHOLDER = 2;

    /**
     * @return bool
     */
    public function indicatesPlaceholder(): bool
    {
        return (int)$this->__toString() > self::DEFAULT_STATE;
    }
}
Copied!

The method can then be used in your class:

EXT:my_extension/Classes/SomeClass.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension;

final class SomeClass
{
    public function doSomething()
    {
        // ...

        $myVersionState = VersionState::cast($versionStateValue);
        if ($myVersionState->indicatesPlaceholder()) {
            echo 'The state indicates that this is a placeholder';
        }

        // ...
    }

    // ...
}
Copied!

Migration to backed enums

Class definition:

EXT:my_extension/Classes/Enumeration/State.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Enumeration;

use TYPO3\CMS\Core\Type\Enumeration;

class State extends Enumeration
{
    public const STATE_DEFAULT = 'somestate';
    public const STATE_DISABLED = 'disabled';
}
Copied!

should be converted into:

EXT:my_extension/Classes/Enumeration/State.php
<?php

declare(strict_types=1);

namespace MyVendor\MyExtension\Enumeration;

enum State: string
{
    case STATE_DEFAULT = 'somestate';
    case STATE_DISABLED = 'disabled';
}
Copied!

Existing method calls must be adapted.