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

Symfony Cookie Consent Bundle Laravel Package

kpeu3u/symfony-cookie-consent-bundle

A Symfony bundle for cookie consent management: display a customizable banner, let visitors accept or reject cookie categories, and gate scripts until consent is recorded. Simple configuration for GDPR-style consent flows.

View on GitHub
Deep Wiki
Context7

Getting Started

First, a reality check: kpeu3u/symfony-cookie-consent-bundle is a Symfony bundle, not a Laravel package. It ships no service provider, no config/cookie-consent.php, and no Blade views. In a pure Laravel app you cannot composer require it and expect a banner to appear. The realistic day-to-day paths are:

  1. A Symfony app you maintain alongside your Laravel apps (shared domain, shared cookie policy) — install it there.
  2. A Laravel app that must match the consent behaviour of an existing Symfony frontend — mirror the consent cookie contract in Laravel middleware/Blade.
  3. Borrowing the UX (categories, necessary-cookies-always-active, layout/theme options) and reimplementing in Blade — in which case read the config and templates as a spec, not as a dependency.

If you are on the Symfony side, the minimum steps are:

composer require kpeu3u/symfony-cookie-consent-bundle:^2.0 -W
php bin/console assets:install public
php bin/console cache:clear

Then register the bundle in config/bundles.php, add a config/packages/*cookie_consent* file with your categories and vendors, and render the banner from your base layout template.

Where to look first: docs/upgrading.md (mandatory if you are on 1.x), then the README's configuration reference, then the bundle's own templates under its Resources/views/templates directory — those are your override surface.

First use case: define two categories (e.g. analytics, marketing), one vendor each, render the banner once in the base layout inside the <body>, and guard a single optional integration (Google Analytics) behind a consent check. Ship that end-to-end before touching themes, logging or translations.

Requirements to pin in CI: PHP 8.3+ (PHP 8.4+ if you run Symfony 8), Symfony 7.4+.

Implementation Patterns

Config-driven catalogue, code-driven enforcement. Categories, vendors, labels and layout/theme all live in bundle config. But the bundle explicitly does not block third-party scripts and does not delete cookies. Every optional integration needs an explicit guard. The pattern that scales best is a single "consent state" accessor plus per-integration checks at the exact injection point.

Guard at the edge, not in the layout. Rather than conditionally rendering a <script> block in Twig/Blade, emit all optional scripts as inert type="text/plain" (or data-consent-category) tags and activate them from a small listener bound to the consent-changed event. This survives SPA-style navigation and avoids cache-key explosions from per-visitor HTML.

<script type="text/plain" data-consent="analytics" data-src="https://www.googletagmanager.com/gtag/js?id=..."></script>

Treat the stored decision as the only source of truth. In 2.0, optional services are preselected in the settings form for visitors with no saved preferences. That is a UI default, not consent — consent is granted only on submission. So your guard must read the persisted cookie/record and default to deny when absent.

Server-side guards too. For anything rendered server-side (a tracking pixel, an embedded iframe, a personalisation block), inject the current consent decision into the render context and branch there. Keep the category names in one constant/class so config and guards cannot drift apart.

Laravel-side mirroring. If a Laravel app shares a domain with the Symfony frontend, define the consent cookie name and payload shape once (a small shared doc or a config value), then read it in a Laravel middleware and expose it as a request attribute or a Blade directive. Do not let Laravel re-implement its own banner on the same domain — two banners writing the same cookie name is a guaranteed support ticket.

Single-vendor categories. 2.0 collapses categories with one vendor into a simplified toggle. Model your config accordingly — if a category will only ever have one vendor, embrace it; if you expect to add vendors later, ship it with two so the UI doesn't silently change shape on a future release.

Doctrine logging. If you enable database logging, it is opt-in and requires the bundle's Doctrine mapping plus an up-to-date schema. Keep it on a separate connection or table prefix if you have GDPR-driven retention policies; log rows are personal data.

Testing. Functional-test the round trip: clear cookies, request a page, assert the banner renders and nothing optional loads; submit the form with the CSRF token; assert the cookie is set and the optional script now renders. Add a test that an unsubmitted settings form (preselected boxes) still blocks optional scripts.

Gotchas and Tips

  • This is a major release. 1.x config and template overrides will very likely need edits. Read docs/upgrading.md before touching composer.json, and expect custom form markup to break — CSRF protection and form handling were reworked.
  • Reinstall assets after every upgrade. php bin/console assets:install public + cache:clear. Skipping this is the classic "I upgraded and the banner still looks like 1.x" report. If you use AssetMapper/Encore, confirm whether the bundle assets are copied or symlinked, and clear the built asset cache too.
  • Nothing is blocked for you. The single most common production bug with this class of bundle: the banner looks perfect, consent is collected, and Google Analytics has been firing the whole time. Do a full audit of third-party snippets (including ones injected by other bundles, tag managers, and chat widgets) after install.
  • Rejection doesn't clean up. The bundle does not delete cookies. If a user rejects, previously-set first-party cookies from your own optional features are still there. Add explicit cleanup on the reject path if your policy promises it.
  • Preselection is not consent. Any analytics or dashboard that counts "checked boxes" as opt-in will over-report. Count only persisted submissions.
  • "Reject all" visibility is configurable — check the law first. Hiding it may be convenient for conversion and non-compliant in the EU/UK. Make this a config decision that is reviewed, not a design decision.
  • Doctrine logging fails loudly if the schema is stale. If submissions start throwing after an upgrade, check the mapping and run migrations before debugging the form.
  • Version matrix. Symfony 8 requires PHP 8.4. If your CI still tests 8.3, pin symfony/* to 7.4 or your matrix will fail for reasons unrelated to your code.
  • Theme and layout are CSS-level knobs. light/dark/automatic and top/bottom banner vs dialog should be handled via config, not by forking templates. automatic follows prefers-color-scheme; override CSS custom properties rather than editing bundle markup so upgrades stay cheap.
  • Translate, don't hardcode. Category and vendor labels are translatable in 2.0 — use translation keys in config and add the catalogue to your translations/ directory. Mixing raw English strings into config is the thing you'll regret when the second locale lands.
  • Debugging checklist: banner missing → bundle not registered / template not extended / assets not installed; form submit does nothing → CSRF token or the bundle's route/controller; consent never persists → cookie domain/SameSite mismatch (common when Symfony and Laravel share a domain on different subdomains); optional script still loading → the guard is on the wrapper, but the snippet is also inlined elsewhere.
  • Extension points, in order of preference: config → translation overrides → template overrides under templates/bundles/... → service decoration. Avoid patching vendor files; 2.0 changed enough that a fork will be painful to carry.
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.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console