becklyn/javascript-context
Send server-side data from PHP to JavaScript via a Twig helper that renders a JSON script container. Set values through the JavaScriptContext service and optionally use context providers/domains to inject shared data automatically.
Install the Package
composer require becklyn/javascript-context
Ensure your Laravel project uses Symfony 5+ (Laravel 8+ is compatible by default).
Register a Provider (Optional but Recommended) Create a service provider to inject global JavaScript context data:
// app/Providers/JavaScriptContextProvider.php
namespace App\Providers;
use Becklyn\JavaScriptContext\Context\JavaScriptContext;
use Becklyn\JavaScriptContext\Provider\ContextProviderInterface;
use Illuminate\Support\ServiceProvider;
class JavaScriptContextProvider extends ServiceProvider implements ContextProviderInterface
{
public function register()
{
$this->app->bind(ContextProviderInterface::class, self::class);
}
public function provideJavaScriptContext(JavaScriptContext $context, ?string $domain): void
{
$context->set('app_name', config('app.name'));
$context->set('user', auth()->user()?->toArray());
}
}
Register it in config/app.php under providers.
First Use Case: Pass Data to JavaScript
Inject JavaScriptContext into a controller or service:
use Becklyn\JavaScriptContext\Context\JavaScriptContext;
public function show(JavaScriptContext $context)
{
$context->set('dynamic_data', ['key' => 'value']);
return view('welcome');
}
Render in Blade/Twig Add the context to your template:
{{- javascript_context("app") -}}
Or in Blade (if using Twig):
@twig('javascript_context("app")')
Access in JavaScript Parse the data in your frontend:
const data = JSON.parse(
document.getElementById("_javascript-context").textContent
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/&/g, "&")
);
console.log(data.dynamic_data);
Use the $domain parameter to segment data (e.g., app, admin):
// Controller
$context->set('admin_settings', [...], 'admin');
{# Admin panel #}
{{- javascript_context("admin") -}}
Attach runtime data (e.g., flash messages, API responses):
public function store(Request $request, JavaScriptContext $context)
{
$context->set('flash', ['success' => 'Item created!']);
return redirect()->back();
}
Decouple context logic from controllers:
// app/Services/ContextService.php
class ContextService
{
public function __construct(private JavaScriptContext $context) {}
public function setUserData(): void
{
$this->context->set('user', auth()->user()?->toArray());
}
}
Use in controllers:
public function __construct(private ContextService $contextService) {}
public function index()
{
$this->contextService->setUserData();
return view('dashboard');
}
@twig('javascript_context("app")')
// app/Providers/BladeServiceProvider.php
Blade::directive('jsContext', function ($domain) {
return "<?php echo Becklyn\JavaScriptContext\Twig\JavaScriptContextExtension::renderContext($domain); ?>";
});
Usage:
@jsContext('app')
Combine multiple providers for layered data:
// app/Providers/AuthContextProvider.php
class AuthContextProvider implements ContextProviderInterface
{
public function provideJavaScriptContext(JavaScriptContext $context, ?string $domain): void
{
if ($domain === 'app') {
$context->set('auth', auth()->only('id', 'name'));
}
}
}
Leverage Laravel’s Service Container Bind the context to a facade for cleaner syntax:
// app/Providers/AppServiceProvider.php
public function boot()
{
app()->singleton('jsContext', function () {
return app(JavaScriptContext::class);
});
}
Usage:
jsContext()->set('key', 'value');
Middleware for Global Context Attach data to every request:
// app/Http/Middleware/SetJavaScriptContext.php
public function handle($request, Closure $next)
{
app(JavaScriptContext::class)->set('request_id', $request->id());
return $next($request);
}
Vue/React Integration Expose context as a global variable:
window.jsContext = JSON.parse(
document.getElementById("_javascript-context").textContent
.replace(/</g, "<")
.replace(/>/g, ">")
.replace(/&/g, "&")
);
Use in Vue:
export default {
computed: {
user() {
return window.jsContext.user;
}
}
};
Testing Mock the context in tests:
$context = Mockery::mock(JavaScriptContext::class);
$context->shouldReceive('set')->with('test', 'value');
$this->app->instance(JavaScriptContext::class, $context);
HTML Escaping Quirks
<, >, and & are escaped. If your data contains " or ', it may break JSON parsing.json_encode() in PHP to ensure safe strings:
$context->set('html_content', json_encode('<div>Safe</div>'));
Then decode in JS:
const safeHtml = JSON.parse(data.html_content);
Domain Mismatches
$domain strictly. A typo (e.g., "app" vs "APP") will skip data injection.if (strtolower($domain) === 'app') { ... }
Twig Dependency
<script id="_javascript-context" class="js-context">
{{ json_encode($javascriptContextData) }}
</script>
Service Provider Tagging
javascript_context.provider) will prevent them from running.# config/services.yaml
services:
App\Providers\MyProvider:
tags: ['javascript_context.provider']
Performance with Large Data
->set() selectively.Symfony 5 Dependency
composer.json for symfony/* dependencies and pin versions:
"require": {
"symfony/http-client": "^5.0"
}
Inspect Rendered Output Check the DOM for the context container:
console.log(document.getElementById("_javascript-context").textContent);
Provider Debugging Log provider execution:
public function provideJavaScriptContext(JavaScriptContext $context, ?string $domain): void
{
\Log::debug("Provider running for domain: $domain");
$context->set('debug', ['domain' => $domain]);
}
JSON Parsing Errors
JSON.parse() fails, the data may contain unescaped characters.function parseJsContext() {
const text = document.getElementById("_javascript-context").textContent
How can I help you explore Laravel packages today?