Skip to content

Latest commit

 

History

History
56 lines (40 loc) · 5.8 KB

File metadata and controls

56 lines (40 loc) · 5.8 KB

Forms Component

Purpose

Infrastructure for building, populating, and handling back-office forms. PrestaShop has two distinct form patterns that share almost no code: settings forms (config blocks) and CRUD forms (entity add/edit). Picking the wrong pattern is the most common AI mistake — see the decision section below.

Pattern-specific rules live in companion files. Read them on demand, not preemptively:

  • Settings forms: SETTINGS.md — base Handler, hooks, anti-patterns, allowed exception, YAML folder, canonical example.
  • CRUD forms: CRUD.md — base FormBuilder/FormHandler factories, hooks, anti-pattern, YAML folder.

Settings forms vs CRUD forms — which one is this page?

Three yes/no questions, in order:

  1. Does the page persist values into ps_configuration (or another flat key/value store)? → settings form.
  2. Is the data identified by an entity ID and listed in a grid for create/edit/delete? → CRUD form (a.k.a. identifiable form).
  3. Is there (or should there be) a CQRS Add{Domain}Command / Edit{Domain}Command for it? → CRUD form. Otherwise → settings form.

A single admin page may carry both patterns side-by-side (e.g. Shop parameters > Contact > Stores has a CRUD grid for store entities and a settings form for global contact details). Treat each block independently.

Pattern Use case Read Skill
Settings form options block, page-level configuration, fields_options migration SETTINGS.md create-settings-form
CRUD form entity add/edit (with grid listing) CRUD.md create-crud-form-type + create-crud-form-data-handling

Critical YAML folder distinction

The two patterns use different service-definition folders:

  • src/PrestaShopBundle/Resources/config/services/bundle/form/settings forms (base Handler)
  • src/PrestaShopBundle/Resources/config/services/core/form/CRUD forms (IdentifiableObject factories)

Easy to mix up. Wrong folder won't raise a hard error — the service simply isn't picked up by auto-discovery, and the page fails at runtime with "service not found". Details in each pattern's companion file.

Shared concerns (both patterns)

Topic Note
Reusable form types PrestaShopBundle\Form\Admin\Type\ holds 80+ generic, PrestaShop-specific form types (SwitchType, TranslatableType, MoneyType, CountryChoiceType, CurrencyChoiceType, ColorPickerType, IpAddressType, EmailType, MaterialChoiceTreeType, etc., plus the Common/ and Material/ sub-namespaces). Check this namespace before reinventing a field — there is almost always a ready-made type.
Form extensions PrestaShopBundle\Form\Extension\ holds 24+ Symfony AbstractTypeExtension classes that add custom options to all form types globally: help, hint, external_link, modify_all_shops, autocomplete, multistore_configuration_key, download_file, disabling_switch, etc. Check this namespace before inventing a new field option — the option you want probably already exists.
Field validation For character-set / format validation, prefer TypedRegex (Core\ConstraintValidator\Constraints\TypedRegex) over an inline Symfony\...\Regex. Pass a type (e.g. TypedRegex::TYPE_GENERIC_NAME, TYPE_ZIP_CODE_FORMAT); the pattern lives once in TypedRegexValidator::getPattern(). Reuse an existing type first; if none fits, add a TYPE_* constant + a case in the validator (referencing the domain VO's *_PATTERN constant when one exists, like CallPrefix::CALL_PREFIX_PATTERN) — never hard-code a raw pattern in the FormType. NotBlank / Length are fine inline.
Translatable fields TranslatableType (in Form\Admin\Type\) wrapping the inner type. Data is an array keyed by language ID. Multilingual textareas wrap TextareaType / FormattedTextareaType.
Money / decimal MoneyType for static currency, AmountType for multi-currency. PrestaShop stores prices with 6 decimal places — always set explicit decimal scale, never round to float. Commands carry DecimalNumber, never native float.
File uploads FileType with 'mapped' => false, 'required' => false. Actual file saving happens in the DataHandler (CRUD) or DataConfiguration (settings), not the form type.
Choice providers ChoiceProviderInterface services injected into form types for dynamic select options. FormOptionsProviderInterface for options evaluated at render time (e.g. carrier lists). Located under src/Core/Form/ChoiceProvider/ (61+) + src/Adapter/Form/ChoiceProvider/ (26).
Tab layout NavigationTabType is a generic Symfony composition pattern — applicable in either pattern but used today almost exclusively by complex CRUD forms (Carrier, Product). See create-form-tab-layout.
Form utilities FormBuilderModifier, FormCloner, FormHelper under src/PrestaShopBundle/Form/ — tools for mutating form builders at runtime (mostly module use).

Skills

Skill Trigger Pattern detail to load
create-settings-form "create settings form for {Page}" SETTINGS.md
create-crud-form-type "create CRUD form type for {Domain}" CRUD.md
create-crud-form-data-handling "create CRUD form data handling for {Domain}" CRUD.md
create-form-tab-layout "create tab layout for {Domain} form" — (generic)