Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Shopware Custom Fields Sync Laravel Package

mich418/shopware-custom-fields-sync

A Laravel/PHP package for synchronizing Shopware custom fields, helping keep field definitions and values consistent across environments. Useful for developers managing Shopware integrations who need a simple, repeatable sync workflow.

View on GitHub
Deep Wiki
Context7

Getting Started

First, calibrate your expectations: despite the "bundle" wording, this is a Shopware 6 plugin (type: shopware-platform-plugin), not a Laravel package. You will not get a service provider auto-discovered by Laravel, and there is no php artisan. If your Laravel app is the source of truth for product metadata, the realistic integration is: Laravel owns the definitions → Shopware plugin (or Admin API calls) reconciles them into custom_field_set / custom_field.

Minimal steps:

  1. composer require mich418/shopware-custom-fields-sync inside the Shopware project (or drop into custom/plugins/), then bin/console plugin:refresh and bin/console plugin:install --activate <TechnicalName>.
  2. Read three files before anything else:
    • composer.json — confirms Shopware version constraint (shopware/core: ~6.x) and the plugin technical name.
    • src/<Name>Plugin.php — shows whether it registers a console command, a subscriber, or just a public service.
    • src/Resources/config/services.xml — this is where the real sync service is aliased. That alias is your integration point; everything else is wiring.
  3. Run bin/console list and grep for the plugin namespace to discover the command (typically custom-fields:sync or similar). Run it once with no arguments on a staging DB and diff custom_field_set before/after. That single diff tells you more about the package's semantics than any README.

The first use case worth wiring: a field set you currently create by clicking through Settings → Custom fields (e.g. acme_product_specs with a pack_size int and material select), expressed as a definition file in git, synced on deploy. That is the whole value proposition — reproducibility across dev/staging/prod.

Implementation Patterns

Definition-first, deploy-time sync. Treat field definitions like migrations: versioned in the repo, applied by CI, never hand-edited in the admin. Keep one definition file per domain area (product_specs, customer_b2b, order_flags) rather than one monolith, so a bad sync has a small blast radius.

Idempotency is the contract you must verify. Before trusting it in CI, run the sync command twice in a row against staging and confirm the second run is a no-op (no new custom_field rows, no updated_at churn). If the package is not idempotent, wrap it: compute a hash of your definition and skip the call when unchanged.

Wrap the service, don't call it from controllers. In the Shopware plugin, alias the package's sync service behind your own CustomFieldSynchronizer interface and inject that into commands, test fixtures, and (if needed) an admin API controller. This lets you swap in a direct Admin API implementation later without touching call sites — the package has zero stars, so assume you may need to replace it.

Laravel-side pattern: export, don't reach across. Have Laravel emit a JSON manifest (GET /internal/custom-fields/manifest) generated from your own Eloquent models/config, and let the Shopware plugin consume it via a scheduled command. Do not have Laravel write custom_field rows directly with raw SQL — you will miss the DAL events and index/cache invalidation.

Programmatic use in fixtures and tests. Custom fields are a prerequisite for entity extension tests. Calling the synchronizer in a test bootstrap is far more reliable than loading SQL dumps, because it respects whatever ordering the package has already solved for you (set before fields, translations after fields).

Translations. Field labels live in custom_field translations, not on the parent row. Assert explicitly that your sync writes all configured locales — a silent single-locale write shows up much later as blank labels in the storefront.

Removal as an explicit, opt-in mode. Never let a routine deploy command delete fields. Gate deletion behind a flag (--prune) that a human runs after a dry run, and log every removed field name.

Gotchas and Tips

Deletion is destructive and irreversible. Dropping a custom_field cascades to the stored values in custom_field relations / entity JSON columns. There is no undo, and plugin:update will not restore data. Always mysqldump the affected tables before a first prune on production.

Renaming is a delete + create. Custom field technical names (acme_product_specs_material) are the storage key. Renaming one orphans every existing value. If you must rename, plan a data migration script, not a definition edit.

Type changes are not supported. Switching text → select or int → float generally requires delete-and-recreate; the DAL will not coerce existing values. Same for changing custom_field_set relation targets (product vs customer) once values exist.

Name-prefix rules. Shopware convention (and often enforcement) is <set_name>_<field_name>. Violating it causes collisions across sets and confusing admin behavior. Validate this in your definition layer before the sync runs.

Shopware minor-version drift. The CustomFieldService / custom_field DAL surface changed across 6.4 → 6.5 → 6.6. Pin both the plugin and Shopware version in composer.json, and run the sync command in CI against the exact Shopware image you deploy. With zero dependents, upstream compatibility reports do not exist — you are the QA.

Vendor it or fork it. Zero stars and no dependents means no bus factor. Read and pin the code (composer.lock + a fork under your org) before it touches production. If the service is ~200 lines, forking is cheaper than the debugging you will otherwise do at 2am.

Cache and index invalidation. After a sync that adds fields, run bin/console cache:clear and bin/console dal:refresh:index. Storefront theme compilation (theme:compile, or the admin theme refresh) is sometimes needed before new field labels render.

In containers, bin/console is not on your host. docker compose exec -T shopware bin/console custom-fields:sync. Wire the sync as a deploy step after plugin:update and before httpd restart, and make it non-zero-exit on failure so deploys halt rather than shipping half-applied field sets.

Extension point, not a substitute for entity extensions. This package manages definitions only. If you need an actual PHP EntityExtension with a getter (getAcmePackSize()) on ProductEntity, that is a separate plugin concern — the field existing in the DB does not create a typed accessor.

Debugging checklist when a field "doesn't appear": (1) row exists in custom_field but not custom_field_set relation → set membership bug; (2) row exists but admin shows nothing → cache, not data; (3) label blank → translation scope; (4) field renders in admin but not storefront → Twig/theme not reading the field name correctly. Confirm each layer with SQL before re-running the sync — re-running rarely fixes a membership bug and can mask it.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums