Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Document enum support #1348

Merged
merged 4 commits into from
Oct 31, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions docs/dev/framework/models/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -137,3 +137,6 @@ For documentation on creating your own model, [click here](customization).

## Collections
If you want to fetch multiple records from the database, have a look into [Collections](collections).

## Enumerations
Models are able to resolve the values stored for a record into [Enumerations](enumerations).
52 changes: 52 additions & 0 deletions docs/dev/framework/models/enumerations.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
---
title: "Enumerations"
description: "Resolve enumerations from DCA records"
---

{{< version "5.3" >}}

Models can be used to resolve the values stored for a record into enumerations:

## Set up the DCA

```php
// contao/dca/tl_member.php
$GLOBALS['TL_DCA']['tl_member']['salutation'] => [
'inputType' => 'select',
'enum' => App\Data\Salutation::class,
];
```

See the [DCA reference](../../../reference/dca/fields#enumerations) for more information.


## Resolve the Enumation

Only the `value` of an enumeration is stored in the database.
You can use `Model::getEnum()` to resolve the enumeration.

```php
$member = MemberModel::findById(42);

$member->salutation; // string value, e.g. 'ms'
$member->getEnum('salutation'); // App\Data\Salutation or null
```


## Type safe methods & fallback values

It is also possible to access the enumerations in a type-safe way using dedicated methods.
In this process, you can also specify a suitable fallback if an enumeration cannot be resolved from the record's value.

```php
use App\Data\Salutation;
use Contao\MemberModel;

class SalutableMember extends MemberModel
{
public function getSalutation(): Salutation
{
return $this->getEnum('salutation') ?? Salutation::mx;
}
}
```
78 changes: 78 additions & 0 deletions docs/dev/reference/dca/fields.md
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,7 @@ $GLOBALS['TL_DCA']['tl_example']['fields']['myfield'] = [
| inputType | Field type (`string`) | [`checkbox`][CheckboxWidget] Checkbox <br>[`checkboxWizard`][CheckboxWizardWidget] Checkbox Wizard <br>[`chmod`][ChmodWidget] CHMOD table <br>[`fileTree`][FileTreeWidget] File tree <br>`imageSize` Two text fields with drop-down menu (creates an [Image Size Array](/framework/image-processing/image-sizes/#size-array)) <br>`inputUnit` Text field with small unit drop-down menu <br>`keyValueWizard` Key » Value wizard <br>[`listWizard`][ListWizardWidget] List wizard <br>[`metaWizard`][MetaWizardWidget] Used for setting meta information in the file manager <br>`moduleWizard` Module wizard <br>`optionWizard` Option wizard <br>`pageTree` Page tree <br>`password` Password field <br>[`picker`][PickerWidget] General purpose picker <br>`radio` Radio button <br>`radioTable` Table with images and radio buttons <br>`sectionWizard` Used for defining sections in the page layout <br>[`select`][SelectWidget] Drop-down menu <br>`serpPreview` Search Engine Result Preview (SERP) widget <br>`tableWizard` Table wizard <br>`text` Text field <br>`textStore` Text field that will not display its current value <br>[`textarea`][TextareaWidget] Textarea <br>`timePeriod` Text field with drop-down menu <br>`trbl` Four text fields with a small unit drop-down menu |
| options | Options (`array`) | Options of a drop-down menu or radio button menu.<br />Specify as `['opt1', 'opt2', 'opt3']` or `['value1' => 'label1', 'value2' => 'label2']`.<br />Special case **ambiguous numerical value/index**: `[0 => 'label1', 1 => 'label2']` or `['0' => 'label1', '1' => 'label2']`: If option values are integers and starting with 0, the label will also be used as value. Use the eval option `isAssociative` to prevent this. |
| [options_callback](../callbacks/#fields-field-options) | Callback function (`array`) | Callback function that returns an array of options. Please specify as `['Class', 'Method']`. |
| enum | `BackendEnum` | {{< version-tag "5.3" >}} Prefill `options` and `reference` with the cases of an enum. See more information [below](#enumerations). |
| foreignKey | table.field (`string`) | Get options from a database table. Returns ID as key and the field you specify as value. The field can be a complete SQL expression, e.g.: `tl_member.CONCAT(firstname,' ',lastname)` |
| reference | `&$GLOBALS['TL_LANG']` (`array`) | Array that holds the options labels. Typically a reference to the global language array. |
| explanation | Array key (`string`) | Array key that holds the explanation. This is a reference to the `XPL` category of the `explain` translation domain. See more information [below](#explanation). |
Expand Down Expand Up @@ -295,6 +296,83 @@ model classes to load referenced data sets efficiently and developer friendly.
| table | Relation table (`string`) | A database table for this relation. Optional, by default Contao tries to extract it from the `foreignKey` attribute. |
| field | Relation table field (`string`) | Override the default relation field (`id`). Useful for relation with `tl_files.uuid` for example. |

### Enumerations

{{< version "5.3" >}}

By using [Enumerations](https://www.php.net/manual/language.types.enumerations.php), the options of a field can be
generated automatically.

If you store a `BackedEnum` as `enum` in the DCA, Contao will generate a matching `option` item for all `Enum::cases()`.


#### Automatic translations

By implementing the interface `Contao\CoreBundle\Translation\TranslatableLabelInterface`, Contao will also generate
a translation for each option and provide them as `reference`.

{{% expand "Show example" %}}
```php
// String backed enumeration that implements TranslatableLabelInterface
namespace App/Data;

use Contao\CoreBundle\Translation\TranslatableLabelInterface;
use Symfony\Component\Translation\TranslatableMessage;

enum Salutation: string implements TranslatableLabelInterface
{
case ms = 'ms';
case mr = 'mr';
case mx = 'mx';

public function label(): TranslatableMessage
{
return new TranslatableMessage(
'salutation.label.' . $this->value,
[],
'messages',
);
}
```

```yaml
# translations/messages.de.yaml
salutation:
label:
ms: Frau
mr: Herr
mx: ''
```

```php
// contao/dca/tl_member.php
$GLOBALS['TL_DCA']['tl_member']['salutation'] => [
'inputType' => 'select',
'enum' => App\Data\Salutation::class,
];

// Will result in:
$GLOBALS['TL_DCA']['tl_member']['salutation'] => [
'inputType' => 'select',
'options' => ['ms', 'mr', 'mx'],
'reference' => [
'ms' => 'Frau',
'mr' => 'Herr',
'mx' => '',
],
];
```

{{% notice note %}}
In fact, the options are generated via the `options_callback`. In the example above
the generated `options` are used for illustration purposes only.
{{% /notice %}}
{{% /expand %}}

{{% notice tip %}}
You can also [resolve the enumeration](../../../framework/models/enumerations) via the associated model.
{{% /notice %}}


### SQL Column Definition

Expand Down