exs/schema-breadcrumb-bundle
Symfony bundle that generates schema.org BreadcrumbList JSON-LD script tags from Twig. Pass an ordered array of breadcrumb items with name, URL, and optional image to the getJsonBreadcrumb() function to output valid structured data for search engines.
Architecture fit. Despite the "Laravel/PHP package" framing, exs/schema-breadcrumb-bundle is a Symfony bundle, not a Laravel package. It is built for the legacy AppKernel::registerBundles() registration model (Symfony 2.x/3.x era) and exposes a Twig global function getJsonBreadcrumb(). It ships no service provider, no facade, no config publishing, and no package auto-discovery — so it cannot be dropped into a Laravel application as distributed. The architectural fit for Laravel is effectively zero. The mitigating factor is that the actual work — serializing an ordered array of {name, url, image} items into a schema.org BreadcrumbList JSON-LD <script> block — is a pure-PHP concern with no framework coupling. The capability is portable; the package is not.
Integration feasibility. Low technical effort, but it is a fork-and-own / reimplement operation rather than a composer require. The extraction is one or two small classes plus JSON encoding and escaping logic — on the order of half a day to a day to lift into a Laravel Blade component or View\Component, including tests. Attempting to install the bundle itself into Laravel will fail or pin the platform on Symfony 2/3 components, Twig 1.x, and PHP 5.5–7.0-era constraints.
Technical risk. The headline risk is abandonment, not complexity: 0 stars, 0 dependents, a Travis CI badge (a CI service effectively deprecated for OSS), no visible release history, no test suite, no security policy. That means no upstream fixes, no PHP 8.x / modern-framework compatibility, and no CVE response process. The functional risk surface is small and well-bounded: JSON encoding, output escaping inside a <script> context, and schema.org conformance. The concrete risks are (a) XSS/script-injection via unescaped name/url/image values, (b) json_encode silently returning false on invalid UTF-8 and emitting a broken tag, and (c) malformed or relative URLs producing Google Rich Results validation errors. All three are addressable with a small, well-tested internal implementation.
Key questions.
composer.json pin, and does it install anywhere on the current stack?ListItem position numbering and item-omission rules?image support actually required, or is name + URL sufficient?spatie/schema-org (Laravel-native, maintained, supports schema graphs) or a ~50-line in-house builder?Stack fit. Poor for Laravel out of the box; acceptable only for a legacy Symfony 3 codebase already using kernel registration. The Twig global function is a hard friction point because Laravel templates are Blade — the package provides no equivalent.
Migration path. Two viable routes; neither is the literal "install and wrap":
spatie/schema-org is Laravel-native, supports BreadcrumbList/ListItem, is actively maintained, and composes with other schema types (Organization, Product, Article, FAQPage) you will inevitably need — which this bundle cannot do.App\Support\StructuredData\BreadcrumbList builder plus a <x-breadcrumbs-schema :items="..."/> Blade component. Identical output, no dependency, no maintenance/license question.If the application is genuinely Symfony 2/3 and only needs the script tag, direct use is defensible — but wrap the Twig call and audit output escaping before production given the maturity signals.
Compatibility. Expect the bundle to require Symfony ~2.3|~3.0, Twig ~1.x, and PHP ≤7.x. Assume incompatibility with Laravel 9/10/11 and PHP 8.2+. Any path using the bundle on a modern stack needs a shim or hard fork — at which point the in-house option is cheaper.
Sequencing.
name, absolute url, optional image, explicit position) so ordering is not implicit in array order — the README's array-order-as-hierarchy is a fragility to eliminate.JSON_UNESCAPED_SLASHES | JSON_UNESCAPED_UNICODE | JSON_THROW_ON_ERROR.Maintenance. As a third-party dependency, operational burden is unsustainable: no maintainer means every PHP upgrade, framework upgrade, or security advisory becomes our problem with no upstream path. As an internalized component, maintenance is a small, predictable surface we fully control — the honest trade. TPM recommendation: do not carry the dependency; own ~50 lines of code.
Support. No community, no dependents, no issue history to lean on. Any defect must be diagnosed internally from source. There is no vendor SLA and effectively no support channel beyond reading the code.
Scaling. Emitting a <script> block per page template is trivial at any traffic volume — this is render-time serialization, not a service. The real scaling concern is governance: a one-script-per-schema-type pattern becomes hard to validate and maintain as you add Organization, Product, and Article markup. A single JSON-LD @graph strategy (via spatie/schema-org or a custom builder) scales far better across a growing content surface.
Failure modes. (1) Unescaped values inject into the script block — XSS risk, must be closed before any production use. (2) json_encode returns false on invalid UTF-8, silently dropping the tag with no signal — use JSON_THROW_ON_ERROR and handle it. (3) Array order drift breaks position numbering silently — mitigate with an explicit DTO carrying position. (4) Relative or non-canonical URLs fail Rich Results validation and erode SEO value. (5) Abandoned upstream yields no fix when the platform moves on.
Ramp-up. Near-zero learning curve: the README is a single example and the domain knowledge (schema.org BreadcrumbList, JSON-LD) is well-documented by the spec and Google. Any engineer can reimplement it in an afternoon; the effort goes into doing it correctly (escaping, encoding, URL canonicalization, validation), not in understanding the package. The team should budget the day for a properly tested internal component and treat the package strictly as a behavioral reference.
How can I help you explore Laravel packages today?