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

Legacy Bridge Laravel Package

ezsystems/legacy-bridge

Symfony bundle bridging eZ Publish legacy (4.x) and eZ Platform (5.x), letting legacy extensions, modules, and the legacy kernel run alongside the modern Symfony stack so you can migrate incrementally without a full rewrite.

View on GitHub
Deep Wiki
Context7

Getting Started

Read this first: the package is archived (last release Nov 2020). It exists to run the eZ Publish Legacy kernel side-by-side with eZ Platform 2.x, and it is only useful for projects that are already in that migration window. Do not introduce it into a new project, and do not expect it to work on Ibexa 4 / Symfony 5 / PHP 8 — it is pinned to the eZ Platform 2.x + Symfony 3.4/4.x + PHP 7.x era. If you are on eZ Platform 2.x with a legacy install to retire, it is still the sanctioned path.

Minimal steps to a working install:

  1. Drop the legacy kernel in place. The bridge does not fetch eZ Publish Legacy for you. Put a working legacy install at ezpublish_legacy/ (with settings/, extension/, design/, var/, and its own autoload), matching the DB and settings/override of the platform you are migrating from.
  2. Require and register the bundle.
    composer require ezsystems/legacy-bridge
    
    Symfony 4/Flex: add EzSystems\EzPlatformLegacyBundle\EzPlatformLegacyBundle to config/bundles.php. Symfony 3: register it in app/AppKernel.php. It must be loaded after the eZ Platform bundles because it decorates/extends their routing and view configuration.
  3. Enable it in configuration (root key is ezpublish_legacy in the standalone bridge; older eZ Publish 5 docs show it nested under ezpublish.legacy — verify with bin/console debug:config ezpublish_legacy):
    ezpublish_legacy:
        enabled: true
        root_dir: "%kernel.project_dir%/ezpublish_legacy"
    
  4. Align siteaccess names. Every Symfony siteaccess that should reach legacy needs a matching legacy siteaccess under ezpublish_legacy/settings/siteaccess/<name>/, and a legacy_root_dir if you run more than one legacy tree.
  5. Verify routing. bin/console debug:router should show the legacy router in the chain, and hitting a known legacy URL (a legacy module/view, or content/view/full/<id>) should render through the legacy kernel instead of 404ing.
  6. Clear both caches (see Gotchas — this is the #1 time sink).

First use case: the shortest path to value is not templating — it is URL ownership. Enable the bridge, let unmigrated URLs fall through to legacy, and confirm a legacy module (e.g. a custom extension/<ext>/modules/<module>/<view>.php) still serves through the Symfony front controller. That gives you a working "some URLs are Symfony, some are legacy" baseline you can shrink over time.

Implementation Patterns

Migrate URL-by-URL with the chain router

The core day-to-day mechanism: the bridge appends a legacy router last in the chain. Any URL you have not defined a Symfony route for is handed to the legacy kernel. Migration then becomes mechanical:

  1. Pick a legacy URL.
  2. Implement a Symfony controller/route for it.
  3. Refresh — the Symfony route now wins, legacy never boots.
  4. Repeat until debug:router shows no legacy fallbacks in use.

This is by far the safest pattern because it is per-URL reversible: delete the Symfony route and you are back on legacy. Resist the urge to do a big-bang cutover of a whole module.

Keep legacy templates as content view templates

The bridge provides a legacy templating layer plus a view provider so you can leave .tpl templates in design/<design>/templates/ and reference them from content_view configuration. This lets you port controllers and content types before you port presentation — you get the Symfony request/response lifecycle (and its cache and profiling) while the markup is still rendered by legacy. Typical flow: move the routing and controller layer first, then replace design: templates with Twig view by view.

Confirm the enabled provider/service IDs from the bundle's Resources/config/*.yml rather than guessing — the naming changed between eZ Publish 5's LegacyBundle and this EzPlatformLegacyBundle.

Call into legacy from a Symfony controller

For logic you cannot yet reimplement (legacy workflows, custom extension data sources, legacy-only modules), the bridge exposes the legacy kernel as a service. Use the callback entry point rather than booting the kernel yourself:

// service: ezpublish_legacy.kernel (verify the ID with debug:container)
$result = $this->legacyKernel->runCallback(function () {
    // legacy eZ Publish code runs here, with legacy autoloading and INI settings
    return someLegacyFunction();
});

Rules for that callback body:

  • Keep it a thin adapter — it is a boundary between two autoloaders and two config systems, and it cannot be unit-tested in isolation.
  • Return scalars/arrays, not legacy objects. Legacy objects drag legacy dependencies (and their ezp* globals) into your Symfony code.
  • Prefer converting in the adapter over converting at every call site.
  • Do not call runCallback() in a loop; every invocation pays kernel bootstrap cost.

Run legacy scripts and cron through the Symfony console

The bridge ships ezpublish:legacy:script, which executes legacy PHP inside a correctly bootstrapped environment:

php bin/console ezpublish:legacy:script bin/php/ezcache.php --clear-all
php bin/console ezpublish:legacy:script bin/php/runcronjobs.php

Use this for all legacy cron jobs and maintenance scripts instead of calling the legacy runcronjobs.php directly — otherwise the legacy process may pick a different DB/cluster configuration than the Symfony app and corrupt or miss data. Move legacy crontab entries to Symfony console entries as part of the migration.

Run two legacy trees during the transition

legacy_root_dir is siteaccess-aware. That means you can point one siteaccess at the old tree (ezpublish_legacy) and another at a copy or a partially-customised tree, and migrate siteaccess by siteaccess rather than all at once. It is also the standard way to handle multi-site installs where legacy extensions differ per site. Verify the exact key (ezpublish.system.<sa>.legacy_root_dir vs ezpublish_legacy.system.<sa>.legacy_root_dir) with debug:config for your version — this is one of the settings that moved.

Integration and incident-control tips

  • Kill switch: ezpublish_legacy.enabled: false disables the whole bridge. Keep it available — if a legacy boot starts causing 500s in production, this is your one-line rollback.
  • Disable legacy in the test environment. Running the bridge in test makes functional tests boot the legacy kernel (seconds per test) and introduces legacy filesystem/session side effects. Put enabled: false in config/packages/test/.
  • Keep legacy extensions out of Composer. Legacy extensions live in ezpublish_legacy/extension/ and are autoloaded by the legacy autoloader. Do not add them to root composer.json and do not let PHPStan/PHP-CS-Fixer walk ezpublish_legacy/ — exclude the directory from all tooling and CI static analysis.
  • Treat the bridge as scaffolding. Every file under ezpublish_legacy/ is code you intend to delete. Track migration progress as "count of legacy-routed URLs / legacy templates remaining", not as tickets.

Gotchas and Tips

There are two caches, and you must clear both. This causes more wasted hours than anything else on this bundle. bin/console cache:clear does not clear legacy's ezpublish_legacy/var/cache/<siteaccess>/, and legacy caches INI settings aggressively. After any legacy settings/*.ini.append.php change:

php bin/console cache:clear
php bin/console ezpublish:legacy:script bin/php/ezcache.php --clear-all

Symptom of a stale legacy INI cache: "my config change had no effect" with no error anywhere. Always suspect this before debugging logic.

Two config systems, two logs, two error handlers. Legacy eZDebug::writeError() output goes to the legacy log under ezpublish_legacy/var/log/ and will not appear in the Symfony profiler or var/log/dev.log. When a legacy-routed page fails, check both. Legacy display_errors / EZP_DEBUG settings live in legacy's site.ini, not Symfony's .env, so "debug is on" in Symfony does not mean you get legacy stack traces.

The router order is load-bearing. Legacy is the last router in the chain. That is a feature (Symfony always wins) but also a trap: adding a broad Symfony route (e.g. a catch-all /{slug}) silently steals traffic from legacy pages, and the failure looks like a content bug, not a routing bug. When a legacy page suddenly renders as a Symfony 404, run debug:router and check for an overlapping pattern first.

Siteaccess names must match on both sides. ezpublish_legacy.system.<sa>.legacy_root_dir is useless if ezpublish_legacy/settings/siteaccess/<sa>/ does not exist. Symptoms are legacy falling back to the default siteaccess (wrong design, wrong INI, wrong language) rather than an error. Mismatched siteaccess is the second-most-common cause of "legacy behaves differently through the bridge than it did standalone."

Webserver rewrite rules must cover legacy asset paths. Legacy serves /design/..., /extension/..., /var/... (storage) directly from files under the legacy root. Behind the Symfony front controller these paths often need explicit nginx/Apache rules or they 404. Check this before blaming the bundle when images and CSS are broken but HTML renders. Budget for updating vhost config as part of the cutover.

File handlers / cluster configuration is duplicated. Legacy reads file.ini (var/storage, DFS/cluster settings) while eZ Platform uses its own dfs/IO configuration. If a legacy page shows missing images but the Symfony side is fine, the two configurations disagree. Legacy content files and platform binaries live in the same storage in eZ Platform 2.x, so a mismatch can produce silent 404s rather than errors.

Performance: legacy boot is expensive and all-or-nothing. Every request that touches the legacy kernel — whether through routing or a runCallback() — pays a full eZ Publish bootstrap plus legacy cache reads. There is no partial boot. Consequences:

  • Cache the results of runCallback() in Symfony cache when the underlying legacy data is stable.
  • Never call legacy from a hot Twig template or a listing render.
  • Watch for pages that are Symfony-routed but accidentally pull a legacy template fragment — they lose the whole Symfony cache advantage.

Sessions and authenticated users can desync. If login is handled by Symfony and a legacy page needs the user, the legacy kernel must be handed the right identity; otherwise you get "logged in on some pages, anonymous on others." If you see this, check the bundle's user/session bridging service rather than debugging legacy's auth code — and prefer keeping all authentication in Symfony with legacy pages reading the injected user.

Upgrade trap. Because the package is archived, composer update will happily keep it pinned while the rest of your dependencies move on, and the eventual eZ Platform/Ibexa major upgrade will break it with no upstream fix. Plan the bridge's removal — not just the legacy code's removal — as an explicit milestone in the migration, and verify the supported eZ Platform version in the bundle's composer.json constraints rather than the README before planning any platform upgrade.

Extension points, in the order you should reach for them: (1) a Symfony route shadowing a legacy URL; (2) a legacy template used as a content view while the controller is Symfony; (3) runCallback() inside a thin adapter service; (4) a custom legacy module. Anything below level 2 increases your legacy surface area and should have a delete-by date attached.

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.
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
glavweb/extra-bundle
glavweb/api-bundle
glavweb/admin-bundle