hospect/php-vars-to-js-bundle
A Symfony bundle that passes PHP variables to JavaScript, letting you expose server-side data to frontend scripts in a simple, centralized way. It reduces boilerplate by keeping configuration and dynamic values in sync between PHP and JS.
Initial-state hydration policy (the core call). Deciding whether to embed server-rendered state — current user, permissions, feature flags, tenant/org config, i18n strings, CSRF tokens, pagination cursors — directly into the page on first paint instead of firing 3–5 follow-up XHR calls. This package only supports one answer (inline <script> hydration), so adopting or rejecting it is effectively a decision to constrain that policy to inline state. Record the decision either way; the mechanism matters less than the policy.
Build vs. buy (verdict: build, not buy). The whole value proposition — collect a PHP array, json_encode it with safe flags, emit one <script> block into the layout — is roughly a day of work as a Twig function plus a small service. "Buying" here means importing an unmaintained Symfony 2-era wrapper (9 stars, 0 dependents, health score 0.075) for code we can own outright. That is a decision to reject as a dependency but harvest the pattern.
Frontend architecture / roadmap. Choosing between inline state hydration, a cacheable bootstrap JSON endpoint, data-* attributes, or a heavier framework-level solution (Inertia shared props, Ziggy route exposure, a typed API client). This package validates only the first option, so it constrains that roadmap call regardless of whether we install it.
Security posture (the defensible win). The real benefit is consistent JS-context escaping — JSON_HEX_TAG|HEX_AMP|HEX_APOS|HEX_QUOT — instead of engineers hand-rolling json_encode inside templates, a recurring source of stored-XSS findings. That is a policy and linting win we can adopt without adopting the library.
Standardization decision. Whether to set a cross-team convention for how server data reaches the browser. The decision is yes to a convention, no to this implementation — standardize on a shared internal helper and the escaping flags, not on a single-maintainer, end-of-life bundle.
Deprecation triage / avoid re-litigating. Logging "pattern-valid, package-rejected" so the same question does not resurface each quarter.
Consider it only if all of the following hold:
Look elsewhere (or write it yourself) when:
laracasts/PHP-Vars-To-Js-Transformer directly (the bundle is the wrong artifact); on Symfony 5/6/7, a ~20-line Twig function or a small StateProvider service is the idiomatic answer.To executives (30 seconds): There is a small, real pain point — every page load spends a handful of extra API calls fetching bootstrap data, and engineers sometimes write inline JSON by hand, which is a known source of XSS bugs. This bundle addresses exactly that, but it is built for an end-of-life Symfony version, has essentially no community, and we would own it forever. We are not adopting the package. We are taking the pattern — safe JSON encoding into a namespaced script block — and implementing it in-house for roughly one day of engineering, with a test asserting <, >, &, ', " are hex-escaped. Net: a small performance and security upside, near-zero cost, no new vendor or maintenance risk.
To engineering (the actual ask): Do not add hospect/php-vars-to-js-bundle. It wraps laracasts/PHP-Vars-To-js-Transformer for Symfony 2, which we do not run, and it has zero dependents. Instead: add a single toJs() Twig function backed by a small service that JSON-encodes with JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT | JSON_THROW_ON_ERROR, emits into a namespaced global (e.g. window.__STATE__), and is covered by one test. Enforce it with a linter rule banning raw json_encode inside templates. If we later adopt Inertia or a typed API client, this helper is deleted in an afternoon — no migration cost. On a Laravel codebase, skip the bundle and use the upstream package's facade directly.
Bottom line: The opportunity is real but small; this implementation is not the vehicle. Score it as pattern-valid, package-rejected.
How can I help you explore Laravel packages today?