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

Content Browser Sylius Laravel Package

netgen/content-browser-sylius

Netgen Content Browser integration for Sylius adds a unified content browsing and selection interface to the admin. Editors can search and pick items from configured content sources, with Sylius-specific setup and item type support.

View on GitHub
Deep Wiki
Context7

Getting Started

Understand what you're installing first. Despite the Laravel framing, this is a Symfony bundle — there is no service provider, no config/*.php, no Eloquent. The realistic path is: you either already run Sylius (which is Symfony), or you are building a Laravel app that talks to a separately deployed Sylius/Content Browser service over HTTP. If it's the latter, this package does not go in your composer.json; it lives in the Sylius service and you integrate against its API from Laravel. Clarify that boundary before writing a line of code, because the mental model changes everything.

If you are the Sylius-side developer, the install chain is three deep and all of it must be version-aligned:

composer require netgen/content-browser-bundle netgen/content-browser-sylius

Then register the bundles in config/bundles.php, import the Content Browser routes (usually under your admin firewall), publish the frontend assets, and configure at least one backend. Check composer.json constraints on this package before installing — it pins against a specific netgen/content-browser API era, and floating that constraint on a low-traffic bridge is how you get a 3am ClassNotFoundError on deploy.

Where to look first. Skip the README after skimming the config sample and go straight to src/. The package is small; the backends implement BackendInterface (item loading, search, subtree navigation, serialisation) against Sylius repositories. That's the whole contract. For everything else — the config tree, route names, the JS picker — read the upstream netgen/content-browser docs, because this package ships none of that and won't document it.

First use case: one product picker, end to end. Don't try to wire every entity at once. Configure a single product backend under netgen_content_browser.config.product, find the backend service id via bin/console debug:container | grep -i content_browser, mount the browser on one admin route, browse the taxon tree, search for a product, and persist the selected (item_type, item_id) pair onto your entity as two scalar columns. That round trip — browse → select → save → reload → resolve — is the entire integration in miniature. Everything after is repetition and refinement.

From the Laravel side, "getting started" means: hit the browse/search endpoint with an admin token, parse the paginated item list, render your own modal or Livewire picker, and store the item type + id. You are re-implementing the picker UI, not this package's value. Be honest with stakeholders about that — if the picker is the only thing you need, a native Sylius Grid or a plain API endpoint may be strictly less surface area.

Implementation Patterns

One backend per entity family, not per picker. The idiomatic shape is a product backend and a taxon backend, each configured once, reused by every admin form that needs a picker. Resisting the temptation to spin up a featured_product backend or a sale_product backend is the single biggest maintainability win. Customise by extending the shipped backend and overriding its query method, not by registering new backends.

final class FeaturedProductBackend extends ProductBackend
{
    protected function getQueryBuilder(): QueryBuilder
    {
        return parent::getQueryBuilder()
            ->andWhere('p.featured = :featured')
            ->setParameter('featured', true);
    }
}

Register it as a service, alias it to the backend interface or reference it under the config node, and you now have a "featured products" picker without a second implementation of browse/search/pagination.

Wrap selection in a small value object. Store item_type + item_id as scalars on your entity, but expose them through a tiny DTO (ContentItemReference) with a resolve(): ?object method that goes back to the backend or repository. This keeps Twig templates, serialisers, and API responses from knowing about Content Browser internals, and means a future switch away from the package is a resolve() implementation change, not a schema and template rewrite.

Integrate via form types on the Sylius side, HTTP on the Laravel side. If you're the Sylius developer, the picker belongs in a custom form type that renders a hidden field plus a "Browse" button and a small JS initialiser — treat it like any Symfony form widget. If you're the Laravel developer, mirror the contract: a ContentItemPicker component (Livewire or plain JS) that calls the browse/search endpoint, shows server-paginated results, resolves the saved reference for display, and writes back item_type + item_id via a form request. Same shape, different runtime.

Search and pagination belong to the server, always. The browser endpoint should never fetch-all-then-filter. For catalogues in the tens of thousands, an unpaginated Sylius repository query turns a modal into a timeout during editorial peaks. Define sources with explicit search on name/SKU and a bounded page size, and make sure the admin endpoint accepts q, page, limit (or whatever the core calls them) rather than assuming defaults.

Feature-flag the picker and keep the native flow. Introduce the picker on a single low-risk admin route behind a flag, with the existing Sylius Grid selection still available as a fallback, and only promote it once it survives a Sylius minor upgrade. This is the pattern that lets you adopt the package without betting the admin UX on a 14-star dependency.

Cache resolved references. Repeatedly resolving the same product or taxon reference for display is a cheap query but a common N+1 in pickers rendered in lists. Resolve in bulk (one query per entity family per page) or cache with a short TTL keyed on item_type + item_id.

Gotchas and Tips

The Laravel/Symfony mismatch is the first gotcha. This package is Symfony-bundle-shaped; there is no Laravel integration and none is planned. If your app is Laravel-native, treat this as an external service's integration package and do not attempt to drop it into a Laravel composer.json expecting it to boot. Communicate that clearly to product, because the "10 minute install" story only holds on a Sylius stack.

Version drift is the dominant operational risk. Sylius and Symfony move fast; a low-traffic bridge lags. Pin netgen/content-browser-sylius, netgen/content-browser, sylius/sylius, and symfony/* to an explicitly tested combination and do not float constraints. Add a CI job that runs on the pinned Sylius minor so an upstream break surfaces in CI, not in your editor's browser modal.

The asset pipeline is the most fragile surface. Content Browser ships its own JS/CSS and expects an asset setup that may not match your host's Encore or AssetMapper configuration. Asset publication failures render the modal blank after a deploy while everything else looks healthy — add a smoke check that loads the browser route and asserts the JS is served. Theming the modal to match admin design language is also where schedule overruns live; budget for it explicitly.

Secure the endpoint as admin-only, explicitly. The browser route queries the catalogue and returns serialised resources; mounting it outside the admin firewall, or letting it inherit a permissive default, becomes an information-disclosure path. Add it to the admin firewall by name, verify Sylius resource-level authorization on every returned item (don't let a source leak unpublished or out-of-channel products), and review the serialisation surface — it's easy to leak fields not intended for the admin UI. From a Laravel client, authenticate with a scoped token and never proxy this endpoint to untrusted callers.

Translations surface as raw keys when missed. The package relies on the upstream translation domain; if you install without publishing or registering those resources, editors see netgen_content_browser.product.name in the picker. Publish translations as part of install and add the domain to your admin's translator config. Same for untranslated entity fields — decide early whether you fall back to any locale or block selection without one.

Debugging is source-reading, not community-searching. With 14 stars and zero dependents there is effectively no Stack Overflow signal. Keep the upstream core docs open, use bin/console debug:container, debug:router, and debug:config netgen_content_browser, and be prepared to read src/ of both this package and the core. Write internal docs on your config and service wiring the moment it works — institutional knowledge otherwise leaves with whoever ran the spike.

Extension points are the right lever. The shipped backends are meant to be subclassed; the config node is meant to be layered. Customise via subclass + service alias, not by editing vendor/. If you truly need to patch, vendor the package (path repository or fork) rather than relying on patches files that will silently break on the next composer update.

Plan for maintenance ownership. No SLA, no commercial backing evident, single-vendor bus factor. Name one engineer as the owner, keep the fork path open (vendor only when upstream goes dormant), and schedule a review each time Sylius ships a minor. Budget roughly one to two days for a Sylius-fluent developer to absorb Content Browser's Source/Item/Backend concepts, plus half a day for assets and another for authorization hardening — and treat "we'll just upgrade it later" as a costed decision, not a deferral.

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.
diephp/sequences
users-au/socialite-provider
twidpay/twid-logger
mrnewport/laravel-plaid
mrnewport/laravel-repo
mrnewport/laravel-docsign
mrnewport/laravel-stow
mrnewport/laravel-flow
mrnewport/laravel-priceable
mrnewport/laravel-nestedterms
fredmeng/laravel-apidoc-generator
itstructure/laravel-multilingual-tools
pdustdar/elasticsearch
markupai/php-sdk
rlacerda83/lumem-microservice-shipment
uni-method/symfony-lib
tacticmedia/scim-server-bundle
neika-ai/symfony-bundle
mattleads/agent-publishing-bundle
glavweb/framework-bundle