create-crud-form-type
Scope: this skill builds the FormType for a CRUD (identifiable) form — an entity with an ID, a grid listing, and an
Add/EditCQRS command. For a settings form (options block,ps_configurationrows), usecreate-settings-forminstead. Settings FormTypes are flat, have nogetParent(), no_idfield, and no entity binding.
Read @.ai/Component/Forms/CONTEXT.md (decision tree, shared concerns) and @.ai/Component/Forms/CRUD.md (base FormBuilder/FormHandler factories, hooks, anti-pattern) for the conventions this skill builds on.
1. Root form type
Create src/PrestaShopBundle/Form/Admin/{Section}/{Domain}/{Domain}Type.php:
- Extend
TranslatorAwareType(provides$this->trans()) orAbstractTypefor simple forms buildForm(): add all fields for the entityconfigureOptions(): set defaults as needed- Form types define structure and validation only — no knowledge of commands/queries
Reference: src/PrestaShopBundle/Form/Admin/Improve/International/Tax/TaxType.php (simple), src/PrestaShopBundle/Form/Admin/Sell/Catalog/Manufacturer/ManufacturerType.php (with image)
2. Standard field types
The table below is a starter, not the full catalogue. Before picking a Symfony native type, scan
PrestaShopBundle\Form\Admin\Type\for a PrestaShop-specific equivalent** — there are 80+ purpose-built types (SwitchType,IpAddressType,ColorPickerType,CountryChoiceType,CurrencyMoneyType,EmailType,MaterialChoiceTreeType, etc.). And before inventing a new option on a field, **scanPrestaShopBundle\Form\Extension\for an existing extension that already provides it (help,hint,external_link,modify_all_shops,autocomplete,disabling_switch, …).
| PS field concept | Symfony/PS type | Notes |
|---|---|---|
| Text | TextType |
Standard input |
| Boolean toggle | SwitchType (PS-specific) |
On/off switch |
| Select with static options | ChoiceType |
Inline choices array |
| Select with dynamic options | ChoiceType + ChoiceProvider |
See section 5 |
| Textarea / HTML | TextareaType or FormattedTextareaType |
3. Translatable fields
For multilingual fields (entity has _lang table):
->add('name', TranslatableType::class, [
'type' => TextType::class,
'options' => ['constraints' => [new NotBlank()]],
])
TranslatableTyperenders one input per active shop language- Submitted data:
['name' => [1 => 'English', 2 => 'French']] - Map to command's
setLocalizedNames()setter in the DataHandler
For translatable textareas: wrap TextareaType or FormattedTextareaType.
4. Money / price fields
For monetary fields (see Forms/CONTEXT.md for decimal scale convention):
- Static currency:
MoneyType::classwith'currency' => $defaultCurrencyIsoCode - Multi-currency: PS-specific
AmountTypeif available - Use appropriate transformers to convert between form display and storage
5. Choice providers
For select fields with dynamic options from DB:
- Create
{Domain}{Field}ChoiceProvider.phpimplementingChoiceProviderInterface - Inject repository or DBAL connection
getChoices(): array— return['Label' => value]array- Inject into the form type and pass as
choicesoption
Reference: src/Core/Form/ChoiceProvider/ (61+ existing providers)
6. File upload fields
For image/logo uploads (see Forms/CONTEXT.md for file upload conventions):
- Add
FileType::classwith'mapped' => false, 'required' => false - Add
Fileconstraint with allowed MIME types - Display existing image in the edit template via custom Twig block
Rules
Conventions (base classes, file uploads, choice providers, NavigationTabType) are in Forms/CONTEXT.md. Skill-specific reminders:
- Add Symfony validation constraints directly on form fields. Use
NotBlank/Lengthinline; for character-set / format validation preferTypedRegex(with a reused or newly-addedTYPE_*) over an inlineRegex— never hard-code a raw pattern in the FormType. See the "Field validation" row in Forms/CONTEXT.md - For multi-tab layout, use the
create-form-tab-layoutskill instead - If the page persists into
ps_configuration(and not into an entity table), this is NOT a CRUD form — switch tocreate-settings-form