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

Json Ld Bundle Laravel Package

secit-pl/json-ld-bundle

A Symfony bundle for generating JSON-LD structured data in your applications. It provides services and Twig helpers to define schema.org objects, embed SEO-friendly rich snippets, and improve search visibility with minimal configuration and flexible integration.

View on GitHub
Deep Wiki
Context7

Technical Evaluation

Provenance caveat. The prior TPM assessment supplied with this package is a Laravel-package template and does not describe this artifact. It asserts a service provider with extra.laravel.providers auto-discovery, publishable migrations, Eloquent coupling, and queue-worker serialization — none of which exist here. This is a Symfony bundle: registered in config/bundles.php, exposing stateless builder services through the DI container, with a Twig extension for rendering. The practical consequence is that the template over-weights risks this package cannot have (schema ownership, global middleware, job serialization) and under-weights the two that actually block adoption (Twig 3 base-class removal, PHP 8 incompatibility). That assessment should be discarded rather than appended to.

Architecture fit. Conceptually, the fit is excellent. JSON-LD is a presentation-layer concern: no persistence, no migrations, no request lifecycle hooks, no network calls. It composes nested PHP objects and json_encodes them into a <script type="application/ld+json"> block. That is the lowest-coupling class of dependency available, and it belongs in a Symfony app. The mismatch is temporal, not architectural: the codebase targets Symfony 2.8/3.0 and the 2017 Twig/PHP era, and any modern Symfony baseline is six to eight majors past that. The bundle interface itself is stable — Bundle::build(), getContainerExtension(), Twig extensions — so the glue is salvageable, but only if we patch it.

Integration feasibility. Two concrete blockers, both knowable in an afternoon:

  1. Twig 3 removed the Twig_* class aliases, including Twig_Extension. A 2017 extension will reference the legacy base class and fail at container compile or first render. Mechanical fix, but the fix is ours.
  2. PHP 8 removed each(), curly-brace string offsets, and several loosely-typed call patterns common in that era. Expect fatal errors or deprecation noise depending on which paths we hit.

Neither is difficult. That is precisely the problem: if we patch it, we own a fork, and we own it indefinitely. The honest feasibility read is not installable as-is on a modern stack — roughly 1–2 days to fork and patch, or 2–4 days to rewrite the subset we'd actually use (Thing, Organization, Product, BreadcrumbList). Given a score of 0.57, 6 stars, and a last release of November 2017, the build-versus-buy calculation is not close.

Technical risk.

  • Abandonment (dominant). No release in eight years, negligible adoption signal, no observable maintainer activity. Assume zero upstream fixes and no security-patch channel. This is structural; no amount of due diligence mitigates it.
  • Transitive drag. Its composer.json will constrain symfony/* and twig/twig to 2017-era ranges. Installing it may force downgrades or, worse, become the single package blocking a platform upgrade. Check this before anything else.
  • Reinvention cost is low. The package's value is a fluent builder over nested arrays plus a dozen schema.org type definitions. JSON-LD serialization is json_encode. That caps the "buy" premium at near-zero and makes "copy the good parts under our namespace, with MIT attribution" the rational default.
  • Asymmetric failure modes. A builder bug silently degrades rich results — invisible, SEO-only, no exception. A container or Twig incompatibility is a site-wide 500. Loud-boot / silent-output asymmetry should drive where we install it and what we test.
  • Escaping. The classic JSON-LD vulnerability is unescaped </script> breaking out of the script block from user-controlled fields (product names, breadcrumb labels). A 2017 library may not set JSON_HEX_TAG. This is the one finding with security weight and should be read out of the source before adoption, not after.

Key questions.

  1. Which Symfony, PHP, and Twig versions must we support at go-live and twelve months out — and does this bundle resolve against them at all, or does it force downgrades in composer.lock?
  2. Which schema.org types do we actually render? If it's five or fewer, is a rewrite cheaper than a permanent fork?
  3. Is the builder layer cleanly separable from the Symfony/Twig glue? If yes, we vendor only the builders and drop the bundle, DI extension, and Twig service definition entirely.
  4. Does the library set JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT on output? (Security-relevant; verify in source.)
  5. Who owns the fork internally, and what is the patch SLA when Symfony or Twig ships a major?
  6. Is any of this markup currently hand-written in Twig templates? Scope the migration of existing pages, not just net-new ones.
  7. MIT license on a vendored fork — attribution obligations confirmed with legal before code lands. (Likely trivial, but confirm.)

Integration Approach

Stack fit. Symfony-native, stateless, no persistence, no middleware, no scheduled tasks. Verify the builders hold no accumulating state: a container-shared builder service reused across a loop or a long-running worker (RoadRunner, FrankenPHP, Messenger) could leak entities between renders if any builder mutates itself. The Twig function should be a pure function of its arguments. If it isn't, instantiate per call.

Migration path. Recommended: extract and own, not composer require.

  • Fork the builder and Twig extension classes into an internal namespace (e.g. App\Seo\JsonLd), retaining the MIT header and attribution.
  • Drop the Bundle class and DependencyInjection\Extension — they exist only to wire services we can declare in services.yaml with autowiring.
  • Port Twig_Extension to AbstractExtension with TwigFunction objects and namespaced classes; add return types; remove any removed-in-PHP-8 constructs.
  • If we instead insist on the upstream package: pin an exact version (never ^ on an abandoned package — the constraint buys nothing since no patch releases will arrive), patch via fork, register manually in bundles.php, and override its service definitions.

Compatibility. Test against our Twig major explicitly. Assertions that matter are output-level, not unit-level: is the emitted block valid JSON, is it valid schema.org, and is a hostile string in a product name safely escaped? Golden-file tests per page type catch silent schema drift across framework upgrades in a way that testing the builders in isolation will not.

Sequencing.

  1. Constraint spike — install attempt on our stack, capture composer.lock diff and breakage list (half day).
  2. Source read for escaping behavior and builder/glue separation (half day). This is the fork-versus-rewrite decision point.
  3. Port and patch in a branch; add golden-file tests over the real page types we emit.
  4. Ship to one template family only (e.g. product detail pages) behind a switch that falls back to existing hand-written markup.
  5. Watch Search Console for rich-result pickup over four to six weeks before expanding to additional page types.
  6. Do not let it spread to other services or page families until the first has run a full release cycle clean.

Operational Impact

Maintenance. We will own this code. Assign a named owner, schedule a review at every Symfony and Twig major, and treat it as internal source rather than a dependency — no Dependabot or Renovate signal will ever fire for it. Vendoring into our own tree makes this ownership explicit; leaving it as an upstream require creates the illusion of a supported dependency while the fork obligation is identical.

Support. There is none. No commercial backing, no disclosed security contact, no issue triage, no changelog history to reason from. Internal SLA is bounded by what the owning engineer knows. Ramp-up cost for the next engineer is reading the source — acceptable at a few thousand lines if it sits in our tree under our conventions, materially worse if it is an opaque third-party vendor directory.

Scaling. Runtime cost is negligible: building a nested array and encoding it is microseconds and allocates nothing durable. The only scaling concern is recomputing identical site-wide markup (Organization, WebSite, sitewide BreadcrumbList) on every request — precompute once into a Twig global or a container parameter rather than per-render. No database, no network, no queue, no cache invalidation surface. This being one of the cheapest dependencies we could adopt is exactly why it does not warrant taking on an unmaintained one.

Failure modes.

  • Container/Twig compile failure after an upgrade — site-wide 500. Mitigated by keeping the code in our tree, where CI compiles the container on every build and fails the pipeline rather than production.
  • Silent output corruption — valid JSON but schema.org-invalid, or entities silently dropped. No exception, just lost rich results over weeks. Mitigated only by golden-file tests asserting exact output per page type; Search Console is the backstop, not the detector.
  • Escaping regression — </script> breakout via user-controlled builder input. Highest-severity failure here. Assert the encode flags and add a test that feeds a hostile string through a builder and inspects raw output.
  • Data-shape drift — the product or breadcrumb data feeding the builders changes and the markup goes stale with nobody noticing. Monthly Search Console review as the standing check.

Ramp-up. Half a day for a Symfony-fluent developer to read the builders and the Twig extension and produce valid output for one page type; a further day for golden-file coverage and escaping tests. Taking the upstream package unpatched adds the fork-and-patch work in front of that plus permanent overhead: knowing we are on an unmaintained branch with no upgrade signal, which disproportionately penalizes whoever inherits this.

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/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
skyraptor/chatter
edlugz/sasapay
abbasudo/artisan-route