بنقرة واحدة
add-grid
Add a Sylius admin grid for an existing Sylius Resource
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
القائمة
Add a Sylius admin grid for an existing Sylius Resource
التثبيت باستخدام Codex أو Claude انسخ هذا Prompt والصقه في Codex أو Claude أو مساعد آخر ليراجع صفحة Skill ويثبّتها لك.
استنادا إلى تصنيف 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