en un clic
add-grid
Add a Sylius admin grid for an existing Sylius Resource
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Menu
Add a Sylius admin grid for an existing Sylius Resource
Installer avec Codex ou Claude Copiez ce prompt, collez-le dans Codex, Claude ou un autre assistant, puis laissez-le vérifier la page du skill et l'installer pour vous.
Basé sur la classification professionnelle SOC
Implement the fix described in a GitHub issue and open a Pull Request that closes it
Apply the latest review feedback to a Pull Request and push it to the PR branch
Add an admin autocomplete form type for a Sylius Resource (translatable or not), optionally injected into another form via an extension
Add an admin FormType for an existing Sylius Resource
Add a multiple images collection (OneToMany) to an existing Sylius Resource
Add an admin menu entry for an existing Sylius Resource
| name | add-grid |
| description | Add a Sylius admin grid for an existing Sylius Resource |
| argument-hint | [ModelName] |
| allowed-tools | AskUserQuestion, Bash, Read, Edit, Write, Glob, Grep |
Ask the user for the ModelName if not provided. Read src/**/Entity/{ModelName}/{ModelName}.php to detect the entity's fields and relations.
Prerequisite: the model must already exist as a Sylius Resource (run /sylius-app:add-model first). To customize an existing Sylius core grid (e.g. sylius_admin_product), use /sylius-app:extends-grid instead.
One grid file per resource at a unified path: config/packages/grids/{model_snake}.yaml.
Add (or extend) an imports: block at the top of config/packages/_sylius.yaml (shipped by Sylius-Standard, user-editable) so the split files are loaded:
imports:
- { resource: "grids/*.yaml" }
# and "twig_hooks/**/*.yaml" if twig hooks are used by this project
sylius_addressing:
# ... existing content untouched
Based on the entity, ask:
show action (requires a show route — run /sylius-app:add-routes with a show operation if missing)Grid name convention: app_admin_{model_snake}.
sylius_grid:
grids:
app_admin_{model_snake}:
driver:
name: doctrine/orm
options:
class: "%app.model.{model_snake}.class%"
sorting:
# Must reference a field declared under `fields:` (the sort key is resolved against field names, not entity columns).
# If you want to sort by id but not display it, declare the `id` field and set `enabled: false`.
limits: [10, 25, 50]
fields:
# see §4
filters:
# see §5
actions:
# see §6
Translatable resource? Extend driver.options so the grid query joins translations under alias translation (the custom repository from /sylius-app:add-translatable-model is consumed only when you ask for it explicitly — same pattern as sylius_admin_product_option):
driver:
name: doctrine/orm
options:
class: "%app.model.{model_snake}.class%"
repository:
method: createListQueryBuilder
arguments: ["expr:service('sylius.context.locale').getLocaleCode()"]
The only valid grid field types are string, datetime, enum, twig, and callable.
| Doctrine type / use case | Grid type | Notes |
|---|---|---|
string, text, integer | string | plain display — integer on the entity still maps to grid type string |
datetime, date | datetime | option format (default Y:m:d H:i:s) |
boolean | twig | template @SyliusUi/Grid/Field/enabled.html.twig |
| Relation property (ManyToOne) | string with path: relation.property | e.g. author.username |
| Translatable field | string (no path:) | display falls back on the PHP getter, which delegates to getTranslation(). For SQL sort use sortable: translation.{field}. The grid driver must also call the locale-aware list builder — see §3 above. Pattern: sylius_admin_product_option. |
| Complex / multi-property render | twig with path: . | full object available as {{ data.* }} in template |
Common options on every field:
label: app.grid.{model_snake}.{field} — translation keysortable: ~ — enable sorting using this field's name as the sort path; use sortable: some.path to sort by a different column (useful with type: twig)position: N — display order (lower = earlier)Examples:
fields:
title:
type: string
label: app.grid.{model_snake}.title
sortable: ~
enabled:
type: twig
label: app.grid.{model_snake}.enabled
options:
template: '@SyliusUi/Grid/Field/enabled.html.twig'
author:
type: string
label: app.grid.{model_snake}.author
path: author.username
createdAt:
type: datetime
label: app.grid.{model_snake}.created_at
sortable: ~
options:
format: 'd-m-Y H:i'
| Use case | YAML |
|---|---|
| Single text field | type: string |
| Multi-field search | type: string + options.fields: [field1, field2] |
| Force one operator | form_options.type: contains (see note below) |
| Boolean flag | type: boolean |
| Date range | type: date |
| Related entity (small table) | type: entity + form_options.class: '%…model…class%' |
| Enum / choice list | type: select + form_options.choices: { label: value, … } |
| Field has any value | type: exists + options.field: {field} |
| Money range | type: money + options.currency_field: currencyCode |
String filter operators (for form_options.type:): contains, not_contains, equal, not_equal, starts_with, ends_with, empty, not_empty, in, not_in, member_of.
Useful options:
default_value: true — pre-fill the filter (e.g. enabled-only view by default)enabled: false — hide a filter inherited from a parent gridFor translatable fields: a string filter targeting a field defined on the *Translation entity must spell out the DQL path — options.fields: [translation.{field}]. Without it, Doctrine throws "field has no field named title" because the column lives on the join, not the root entity.
For an AJAX autocomplete filter on a related entity, Sylius ships two ready-to-use filter types — you do not need a custom filter class or to call /sylius-app:add-autocomplete:
ux_translatable_autocomplete — for entities with a translatable label (e.g. Taxon.name, Library.name)ux_autocomplete — for non-translatable entitiesfilters:
library:
type: ux_translatable_autocomplete
label: app.grid.{model_snake}.library
form_options:
multiple: false
extra_options:
class: '%app.model.library.class%'
translation_fields: [name]
choice_label: name
options:
fields: [library.id] # DQL path used by the filter, usually `{relation}.id`
Reserve /sylius-app:add-autocomplete for exposing an autocomplete in a form — grid filters do not need it.
Examples:
filters:
search:
type: string
label: app.grid.{model_snake}.search
options:
fields: [title, description]
enabled:
type: boolean
label: app.grid.{model_snake}.enabled
default_value: true
createdAt:
type: date
label: app.grid.{model_snake}.created_at
author:
type: entity
label: app.grid.{model_snake}.author
form_options:
class: '%sylius.model.admin_user.class%'
actions:
main:
create:
type: create
item:
update:
type: update
delete:
type: delete
# show: # uncomment if a show route exists
# type: show
# options:
# link:
# route: app_admin_{model_snake}_show
# parameters:
# id: resource.id
bulk:
delete:
type: delete
Other built-in types (use when relevant):
show (item) — read-only page; requires a show routearchive (item, bulk) — soft-delete workflow; entity must implement ArchiveInterface, supports restore_labelapply_transition (item, bulk) — workflow state machine transitionFor a per-row dropdown grouping several links (e.g. "Manage children"), use a subitem action group with type: links and a list of links: (each with route, parameters, optional visible: resource.hasXxx expression).
Get the project's default locale:
bin/console debug:container --parameter=kernel.default_locale
Add labels to translations/messages.{locale}.yaml. Grid field labels use the grid.{model_snake}.{field} namespace (keeps app.ui.* free for Sylius's auto-generated scalar keys like app.ui.{model_snake} used for page titles/breadcrumbs).
app:
grid:
{model_snake}:
title: Title
enabled: Enabled
created_at: Created at
search: Search
bin/console cache:clear
bin/console sylius:debug:grid app_admin_{model_snake} prints the grid definition (fields, filters, actions as declared)bin/console debug:translation {locale} --domain=messages 2>&1 | grep 'app.grid.{model_snake}' lists every label you added./sylius-app:add-routes/sylius-app:add-menu