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

Layouts Ezplatform Laravel Package

netgen/layouts-ezplatform

Integrates Netgen Layouts with eZ Platform, enabling editors to build and manage page layouts using eZ content, site structure, and reusable blocks. Provides content-aware layout components and configuration to embed dynamic layouts into eZ Platform sites.

View on GitHub
Deep Wiki
Context7

Getting Started

Before you type composer require, do a compatibility audit. This is not a Laravel package — it's a Symfony bundle that adapts Netgen Layouts to the eZ Platform / Ibexa kernel. If you're coming from Laravel, the mental model is closest to "Nova + a page builder, wired into an existing Symfony CMS." There is no service provider, no Eloquent, no facade, and no way to boot it outside an eZ/Ibexa app. Treat that as a hard prerequisite, not an obstacle to work around.

Minimum viable install:

  1. Pin the matrix first. Read the package composer.json and match it against your exact eZ Platform / Ibexa version, the Netgen Layouts major, Symfony, and PHP. Version skew here typically surfaces as a container compile failure on deploy, not a clean Composer conflict — so resolve it by inspection, not by trial install.
  2. Install the engine and the bridge together. You need netgen/layouts core plus netgen/layouts-standard and netgen/layouts-ui (for the editorial admin), alongside this package. The bridge alone does nothing.
  3. Register bundles in config/bundles.php. Open src/ in the repo and read the bundle class names directly — they differ across integration versions, and guessing them is the single most common time sink on first install. Expect a Layouts core bundle, a Layouts admin bundle, and an eZ Platform integration bundle.
  4. Configure from Resources/config/. That directory is your authoritative reference for service definitions, block definitions, and default config. Copy the shapes into config/packages/netgen_layouts.yaml rather than inventing config keys.
  5. Wire routes and assets for the admin UI, then bin/console cache:clear and confirm the Layouts admin screen loads and can see eZ content as a target/query source.

Where to look first, in order: README.md (install + compatibility) → src/ (bundle class, block handlers, target types, item value converters) → Resources/config/ (services, block definitions, defaults) → Netgen Layouts core docs for concepts (layouts, zones, blocks, block definitions, handlers, resolver rules, view providers) → eZ/Ibexa repository docs for the content API you'll call inside custom blocks.

First useful use case — a landing page driven by rules instead of templates:

  1. Create a Landing Page content type in eZ with a title, intro richtext, and a hero_image field.
  2. In the Layouts admin, create a layout: a hero zone with a content field block bound to intro/hero_image, and a second zone with a content list block whose query filters by parent location.
  3. Add a resolver rule targeting the Landing Page content type (or a specific location subtree).
  4. Publish a Landing Page object, clear caches, and load it on the front end. If you see the layout instead of your default eZ view template, the bridge is wired correctly and you can start iterating.

That single loop — content type → rule → layout → block → render — is the entire package's value proposition. Everything below is variations on it.

Implementation Patterns

Rule-based resolution is the core abstraction — lean on it hard. Don't create one layout per page. Create a handful of layouts and let resolver rules select them by content type, section, location depth, siteaccess, or a custom rule you write. A rule implements a small interface and returns a layout ID or null; the first non-null in priority order wins. This is where the package earns its keep over hardcoded Twig: three brand microsites sharing one repository, each with its own siteaccess-scoped theme and layout set, is a config exercise rather than a fork.

Block definitions vs. block handlers. A block definition is the thing editors see in the admin (name, icon, which collections/zones it can go into, default values). A block handler is the PHP that produces the rendered output. They are separate registrations and you will confuse them at least once. Definition goes in YAML config (or a PHP config file under Resources/config); handler is a service implementing the handler interface, tagged for the block type. Keep handlers thin: resolve parameters from the block's config, hand off to a repository query or a view provider, return a value object.

Custom block handler skeleton (verify exact interface signatures against src/ in your installed version):

final class RelatedArticlesHandler implements BlockHandlerInterface
{
    public function __construct(private ContentService $contentService) {}

    public function handle(BlockInterface $block, array $parameters, bool $isContextual): View
    {
        $locationId = (int) $block->getParameter('parent_location_id')->getValue();
        $items = $this->contentService->loadContentList(...);

        return new TemplateView(
            '@app/blocks/related_articles.html.twig',
            ['items' => $items, 'block' => $block]
        );
    }
}

Serve block output as a TemplateView and let editors override templates per theme rather than per block.

Use the built-in content query for 80% of blocks. The eZ integration contributes query types that filter by location, subtree, content type, section, and manual/random selection, with limit, offset, and sort. Before writing a custom handler, check whether a query-backed content list block already covers your case — it usually does, and it means editors can reconfigure the block without a deploy.

Content field blocks are the cheap win. Rendering a single eZ field (image, richtext, title) through a content field block requires zero PHP. Push back on custom handlers when all you need is "show this field of this object here."

Theming and view overrides. Layouts resolves a template through view rules, typically keyed on block definition + view type + theme. Override Twig templates per theme directory instead of editing vendor templates. Themes are configured per siteaccess, which is how you give each microsite its own visual identity off shared layouts and blocks.

Caching, deliberately. Design the cache topology at spike time, not after rollout:

  • Full-page HTTP cache for the layout render, with Vary set for anything user-contextual.
  • Block-level caching for expensive handlers (repository-heavy lists, cross-location queries).
  • ESI/fragments for zones that genuinely vary per user — don't try to make one page-wide cache key encode personalization.
  • Tag every cached layout and block with the content/location IDs it depends on, so a publish event can invalidate precisely.

The bridge ships with HTTP cache client and tagger abstractions (including a Varnish client and a no-op). Confirm which one your environment actually uses — a silent no-op client is the difference between "fast" and "correct until someone publishes."

Multi-site is a first-class scenario here. Layouts can be scoped per siteaccess, so the same content repository backs multiple brands with distinct templates and rule sets. If cross-brand reuse is on your roadmap, prototype it during the spike; retrofitting siteaccess scoping later is painful.

Local development loop. Editors compose; you extend. Your routine becomes: add a block definition or handler → clear container + cache → open the Layouts admin → drag the block into a test layout → hit preview. Preview mode in the admin is the fastest way to iterate on block markup — bookmark it and wire it against a non-production siteaccess.

Gotchas and Tips

Cache invalidation is the sharp edge, not rendering. A content publish in eZ must invalidate every layout and block that references that content. Verify the invalidation listener is actually enabled and its tags are propagating on your install before you call the spike a success. Stale-content bugs here look like "the editor published and nothing changed," are intermittent, and will be blamed on the CMS rather than the bridge. Write an explicit test: publish an item, assert the dependent layout re-renders fresh, repeat under concurrent load.

Version lockstep comes three ways. This bridge pins a Netgen Layouts major and an eZ/Ibexa major, which pins Symfony and PHP. Breakage almost always appears first as a DI container compile failure — which is why a CI job that resolves the matrix and boots the kernel is worth more than a unit test suite for this integration. Treat Ibexa upgrades (~twice yearly) as coordinated events, never opportunistic composer updates.

GPL-2.0 is a gate, not a footnote. Netgen pairs the open-source core with a commercial license. If you're shipping a closed-source product, embedding a distribution, or modifying and redistributing, get the licensing answer before the spike, not after you've built three landing pages on it.

"Block not found" at render time usually means a handler service tag typo, a missing definition, or a definition that exists but is not assigned to the current theme. debug:container for the tagged handler services and check the block type string matches exactly between definition and handler.

Blank zones are almost always rule misconfiguration. Editors perceive a blank zone as "the page is broken"; you'll see it as "no block matched." Add a fallback layout at lowest priority so a misconfigured rule degrades to something visible rather than an empty page — debugging an invisible failure is far more expensive than a slightly wrong page.

cache:clear after every definition change. Block definitions and view rules are compiled into the container. Editing the YAML and refreshing the admin without clearing cache will show you the old admin form and send you chasing a bug that doesn't exist.

Don't fight the native page builder blindly. Ibexa ships its own page/landing-page capability. This package wins specifically when you need rule-based, cross-content-type, multi-site composition applied without per-object authoring. If you just need a page builder for a handful of pages, you're adding a second layout system and a schema to maintain. Be honest about which problem you have.

Vendor concentration is the real maintenance risk. 14 stars, zero dependents means no Stack Overflow safety net. Budget for a named owner, a quarterly dependency review, and a commercial support contract that explicitly covers this adapter, not just Layouts core. Assume you may need to fork and vendor the package, and keep your changes to block handlers and config so a fork stays cheap.

Extension points to prefer. Block handlers, query types, view providers, and resolver rules are the supported seams. Avoid subclassing vendor layout resolvers or monkey-patching the admin — those break on every upstream bump and are impossible to reason about when the vendor goes quiet.

Naming drift will bite you. The codebase, docs, and config keys straddle the eZ Platform → Ibexa rename. When a class, config key, or command isn't where the docs say, assume it was renamed rather than that it's missing, and grep src/ before concluding anything.

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.
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings
coleus/apps
seampact/laravel
emmyconceptng/laravel-ng-postcode
jjsquady/round-robin