friendsofvictoire/cookielaw-widget
A configurable cookie consent widget for Laravel and PHP applications. Display a GDPR-friendly cookie notice, let visitors accept or reject categories, and block scripts until consent is given, with simple Blade integration and customizable styling.
This is a Symfony bundle for Victoire DCMS, not a Laravel package. It ships a single Victoire "widget" that renders a cookie-law banner and remembers dismissal. Before writing any code, read three things in the repo:
composer.json — confirms type: symfony-bundle, requires victoire/core and Symfony 2.7/3.x constraints. This tells you immediately that composer require friendsofvictoire/cookielaw-widget in a Laravel app is a dead end (dependency conflicts with Laravel's symfony/* pins).Widget/ directory — one widget class extending Victoire's widget base type. This is the entire behaviour: define fields (message, policy link, button label) and point at a template.Resources/views/ and any bundled JS/CSS — this is what you actually want to copy. The banner markup, the accept-button handler, and the cookie name/expiry are all here.First use case: treat the repo as a reference implementation, not a dependency. Open the Twig template, translate it to Blade, and reproduce the two behaviours it provides: render a banner on first visit, persist acceptance so it doesn't render again.
Minimal Laravel equivalent to start from:
{{-- resources/views/components/cookie-law.blade.php --}}
@if (! request()->cookie('cookie_law_accepted'))
<div class="cookie-law" role="dialog" aria-label="Cookie notice">
<p>{{ $message }}</p>
<a href="{{ $policyUrl }}">Learn more</a>
<button type="button" data-cookie-law-accept>Accept</button>
</div>
@endif
Server-side gate (closest to the bundle's intent). The widget only renders when the visitor hasn't accepted. In Laravel, check the cookie in the request rather than the session, so it survives session expiry:
// AppServiceProvider::boot()
Blade::component('cookie-law', function () {
return view('components.cookie-law', [
'message' => config('cookie-law.message'),
'policyUrl' => config('cookie-law.policy_url'),
'expiry' => config('cookie-law.expiry_days', 365),
]);
});
Client-side acceptance with a long-lived cookie. The original widget sets the cookie from JavaScript after the click. Mirror that with a small inline script; set path=/, SameSite=Lax, and Secure on HTTPS:
document.querySelector('[data-cookie-law-accept]')?.addEventListener('click', (e) => {
document.cookie = `cookie_law_accepted=1; max-age=${60*60*24*365}; path=/; SameSite=Lax`;
e.target.closest('.cookie-law').remove();
});
Config-driven content. The Victoire widget exposes editable fields. Replace that with a config file so marketing can change copy without a deploy:
// config/cookie-law.php
return [
'message' => 'We use cookies to improve your experience.',
'policy_url' => '/privacy',
'expiry_days'=> 365,
];
Consent gating for third-party scripts. This is where a Laravel implementation earns its keep over the 2016 widget. Use a middleware or a Blade directive to conditionally emit analytics:
// app/Http/Middleware/ShareConsent.php
public function handle($request, Closure $next)
{
view()->share('hasConsent', (bool) $request->cookie('cookie_law_accepted'));
return $next($request);
}
Then in your layout: @if ($hasConsent) <script src="...analytics..."></script> @endif.
Categories, not a single flag. If you're in the EU, extend the cookie to encode categories (necessary:1,analytics:1,marketing:0) and expose a settings panel. The bundle predates this expectation; don't copy its binary accept-only model if compliance matters.
Integration tip: ship it as an anonymous Blade component (<x-cookie-law />) placed once in layouts/app.blade.php, and keep the accept handler in resources/js/app.js rather than inline so Vite can bundle it.
@WidgetCookieLaw/... template reference will fail in Laravel's view finder. Translate paths to resources/views/.cookie_law), you'll get silent "banner never shows" bugs — inspect document.cookie in devtools, not just the source.path=/ means the banner reappears on every subdirectory; missing Secure on HTTPS gets flagged; a naive max-age in seconds vs. a date string is an easy typo.role="dialog", aria-live, focus management on the accept button, and a visible close control — regulators and auditors look for this.{!! !!}.{% extends %}, widget tags). In Laravel there are none — treat the repo as a spec and write ~50 lines of Blade plus a cookie helper.How can I help you explore Laravel packages today?