Download the PHP package core45/laravel-cookieconsent without Composer

On this page you can find all versions of the php package core45/laravel-cookieconsent. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.

FAQ

After the download, you have to make one include require_once('vendor/autoload.php');. After that you have to import the classes with use statements.

Example:
If you use only one package a project is not needed. But if you use more then one package, without a project it is not possible to import the classes with use statements.

In general, it is recommended to use always a project to download your libraries. In an application normally there is more than one library needed.
Some PHP packages are not free to download and because of that hosted in private repositories. In this case some credentials are needed to access such packages. Please use the auth.json textarea to insert credentials, if a package is coming from a private repository. You can look here for more information.

  • Some hosting areas are not accessible by a terminal or SSH. Then it is not possible to use Composer.
  • To use Composer is sometimes complicated. Especially for beginners.
  • Composer needs much resources. Sometimes they are not available on a simple webspace.
  • If you are using private repositories you don't need to share your credentials. You can set up everything on our site and then you provide a simple download link to your team member.
  • Simplify your Composer build process. Use our own command line tool to download the vendor folder as binary. This makes your build process faster and you don't need to expose your credentials for private repositories.
Please rate this library. Is it a good library?

Informations about the package laravel-cookieconsent

core45/laravel-cookieconsent

A Laravel wrapper for orestbida/cookieconsent v3 and its companion iframemanager. It gives you a PHP-first configuration file instead of a hand-written JS blob, i18n through normal Laravel lang files, server-side reads of what the visitor consented to, Blade-driven script gating, and a database audit trail of every consent decision whose model write path is append-only.

The package bundles orestbida/cookieconsent 3.1.0 and iframemanager 1.3.0, served self-hosted from resources/dist / the published vendor/cookieconsent assets — no CDN request is made. Upstream updates are re-vendored and checksum-verified by the maintainers, then shipped as a new package release; there is no auto-update mechanism, so pin the package version if you need a specific upstream JS version.

Capability What you get
Configuration A single config/cookieconsent.php array, passed through to CookieConsent.run() almost verbatim
Translations Standard Laravel lang files (lang/vendor/cookieconsent/{locale}/cookieconsent.php), active or all locales
Script gating @cookiescript Blade directives that emit blocked <script type="text/plain"> tags
Server-side reads @consent/Consent/CookieConsent facade + a consent:* route middleware
Audit trail A consent_logs table with an append-only model write path, export/prune Artisan commands, optional Filament resource (v3, v4 or v5)
Media consent An @iframemanager / @iframe() integration for YouTube-style click-to-load embeds
Security Optional CSP nonce injection for every script tag the package renders

Installation

Requires PHP 8.4+ and Laravel 12 or 13. Filament is optional; if you have it, v3, v4 and v5 are all supported.

Laravel 11 support was dropped in 3.0: every laravel/framework 11.x release is now covered by unfixed security advisories, so Composer refuses to install it by default. On PHP 8.2/8.3 use ^1.1; on Laravel 11 use ^2.0, understanding that the framework underneath it is out of security support.

Other publishable tags, used only if you need to customize them:

Add @cookieconsent to your layout's <head>. This is the recommended placement — the banner script waits for DOMContentLoaded internally, so it's safe to load it before the rest of the page:

The package auto-registers its consent cookie (cookieconsent.cookie.name, default cc_cookie) as an exception to Laravel's EncryptCookies middleware on boot. You do not need to edit bootstrap/app.php yourself.

Configuration

config/cookieconsent.php is published as a plain PHP array. Every key except translations_mode, csp_nonce, logging, and iframemanager is passed straight through to CookieConsent.run() — see the configuration reference for every option orestbida/cookieconsent understands.

RegExp cookie matching

autoClear.cookies[].name normally does an exact string match. To emit a real JS RegExp instead, use the CookieConsent::regex() helper — it returns a sentinel array that the package's Blade view revives into new RegExp(...) client-side:

A plain string (['name' => '_gid']) is always an exact match.

Translations

Publish the language files and edit them like any other Laravel translation:

The package ships bg, cs, de, el, en, es, et, fi, fr, hr, hu, it, lt, lv, nl, pl, pt, sk, sl, sq, sv and uk out of the box. cookieconsent.php maps directly onto orestbida's language.translations.{locale} shape (consentModal, preferencesModal, etc); iframemanager.php supplies the per-service loadBtn/notice/... strings.

config('cookieconsent.translations_mode') controls how many locales are sent to the browser:

Trimming the shipped sections

Laravel applies a published lang/vendor/cookieconsent/{locale}/cookieconsent.php on top of the package file with array_replace_recursive. A shorter preferencesModal.sections list therefore cannot delete the package's trailing entries, and an omitted string key falls back to the package default. Two things follow:

Replacing the shipped strings

Set config('cookieconsent.translations_override') to 'replace' and a published lang/vendor/cookieconsent/{locale}/cookieconsent.php (or iframemanager.php) is used wholesale for that locale instead of being merged over the package file. What the published file contains is exactly what the browser receives: a two-entry preferencesModal.sections list renders two sections, and a key you leave out stays out. Locales without a published file still fall back to the package strings. The default, 'merge', keeps Laravel's usual behaviour.

Script gating

@cookiescript blocks a <script> tag until the visitor has consented to its category, using orestbida's type="text/plain" data-category="..." convention.

External script:

Inline script:

You can also negate a category to run cleanup code when consent is not given (or is withdrawn), and pass extra HTML attributes as a third argument:

Blade quirk: don't glue @endcookiescript directly onto a word character with no whitespace or punctuation between them — Blade's compiler won't recognize someCode@endcookiescript as a directive boundary. This is rarely an issue in practice because inline scripts almost always end in ;, }, or a newline before the closing directive, as in the examples above.

Letting visitors change their mind

Once the banner has been answered it never shows again on its own, so the site must provide a way back into the preferences modal — GDPR requires that consent be as easy to withdraw as it is to give. @cookiepreferences renders that trigger:

It emits a button carrying orestbida's data-cc="show-preferencesModal" hook:

The default label is the consentModal.showPreferencesBtn translation line, so it follows the current locale with no extra strings to publish (falling back to Manage preferences if you've removed that line — sites offering only accept-all/reject-all in the banner do). Pass your own label and any HTML attributes to style it:

Attribute values are escaped; true renders a bare attribute and false/null omits it. data-cc and type are owned by the directive and cannot be overridden, so the trigger can't be silently detached from the modal. Inline on* event handlers are dropped — the nonce-based CSP this package supports would block them anyway.

Put it wherever your privacy links live — footer, cookie policy page, account settings. Reopening the modal and saving new choices fires cc:onChange, which is logged as a change action when the audit trail is enabled.

Any element works, not just the directive's button — the attribute is what matters:

Dynamically inserted triggers: the library binds these listeners once, when CookieConsent.run() executes. A trigger injected later (Livewire re-render, Turbo/htmx swap, modal opened from JS) won't be wired up. Call window.CookieConsent.showPreferences() from your own handler in that case.

Server-side consent

Read what the visitor has consented to from PHP, without waiting for JavaScript:

Gate a whole route behind a category with the consent:* middleware — it aborts with 403 when consent is missing:

Not an authorization boundary. @consent, Consent::has(), and the consent:* middleware all read the unencrypted cc_cookie (it's excluded from EncryptCookies because orestbida/cookieconsent needs to read/write it as plaintext client-side). A visitor can freely edit that cookie's contents. Treat these checks as a UX/ compliance gate that reflects the visitor's own stated preference — never as access control for sensitive resources; use real authorization (policies, gates, middleware backed by server-side state) for that.

useLocalStorage warning. If you set cookie.useLocalStorage to true in the config, orestbida/cookieconsent stores consent in the browser's localStorage instead of a cookie. That value never reaches the server, so @consent/@endconsent, Consent::has(), CookieConsent::has(), and the consent:* middleware will always report "no consent" — they degrade silently to false/[]/null, except for a one-time Log::warning() the first time a read is attempted (guarded by a static flag, so it fires once per PHP process — once per request under classic PHP-FPM, once total under Octane). Leave useLocalStorage off (the default) if you rely on any server-side consent check.

Consent audit trail

Every accept/change interaction the banner fires (cc:onFirstConsent, cc:onChange) is POSTed to an internal cookieconsent.log route and written as a new row in consent_logs. The ConsentLog model's write path is append-only: it throws if you try to update an existing row through the model. This guard is model-instance-level only — it does not stop raw DB::table('consent_logs')->update(...), a mass ConsentLog::where(...)->update(...), or delete(), all of which bypass Eloquent's saving hook. For a hard guarantee, restrict UPDATE/DELETE grants on the consent_logs table at the database user level, or add a database trigger that rejects them outright.

Hardening the audit trail at the database level

The model guard only covers writes made through Eloquent instances. For a guarantee that holds even against raw SQL, DB::table(...), or a compromised app process, revoke UPDATE/DELETE on consent_logs from the application's database user and grant it only SELECT/INSERT:

The cookieconsent:prune command deletes expired rows, so if you apply this hardening, run pruning under a separate, more privileged database role/connection instead of the app's normal user.

Column Contents
consent_id, revision orestbida's own consent identifier and config revision
action first_consent or change
accept_type all, custom, or necessary
accepted_categories, rejected_categories, accepted_services JSON arrays
language_code locale active on the banner at the time of consent
policy_version, policy_hash your configured version string, and a canonicalized sha256 of the effective config — see CookieConsent::policyHash()
ip_address, user_agent evidentiary metadata, subject to the PII config below
user_type, user_id polymorphic link to the authenticated user, if any
payload the full raw cookie payload, for future-proofing

Evidentiary fields (ip_address, user_agent, user_type/user_id, policy_hash) are always derived server-side from the request — they are never trusted from client input.

Delivery. The consent-log POST does not block or affect the banner UI. It retries transient failures (network errors, 429, 5xx) up to twice with backoff, and each event carries a server-checked idempotency key so a retried or duplicated delivery never creates a second row. If the tab closes or navigates away before the request completes, the pending payload is sent as a last-chance navigator.sendBeacon() call on pagehide/tab- hidden. Non-retryable client errors (other 4xx) and exhausted retries are logged to the browser console, not retried further.

PII configuration

Legal note. Storing an IP address and/or user agent alongside a consent decision is itself an act of processing personal data, even though the purpose is to prove consent. Document this processing activity in your own privacy policy, and tune capture_ip ('hashed' or false) and retention_days to match your data minimization obligations under GDPR/LOPD-GDD or the regime that applies to you. This package stores evidence; it does not decide your retention policy for you.

Security note. capture_ip => 'raw'/'hashed' relies on $request->ip(), whose accuracy depends on your application's trustProxies configuration (bootstrap/app.php → ->withMiddleware()->trustProxies(...), or App\Http\Middleware\TrustProxies on older skeletons). Behind a load balancer, reverse proxy, or CDN, an unconfigured trusted-proxy list means every request is logged with the proxy's IP, not the visitor's.

Retrieval

--to accepts a date-only value (as above) and treats it as inclusive of the whole day — a row created at 2026-06-30 23:00 is included, not excluded by an implicit midnight bound. --user alone matches user_id only; it is not scoped by user_type, so ids can collide across different morph types (e.g. an Admin and a Customer both with id 42). Pass --user-type alongside --user to scope the match to a specific morph class. --format only accepts json or csv; anything else fails with an error and a non-zero exit code.

The underlying ConsentLog model exposes matching Eloquent scopes:

between() bounds are used verbatim. Unlike the export command's --to, the between() scope passes its bounds straight to whereBetween('created_at', [$from, $to]) — it does not auto-expand a date-only end bound to end-of-day. ConsentLog::between('2026-01-01', '2026-06-30') excludes anything after 2026-06-30 00:00:00. Pass an explicit time ('2026-06-30 23:59:59') or a Carbon endOfDay() instance to include the whole day.

Retention

Deletes rows older than logging.retention_days. It's a no-op (logs an info message, deletes nothing) when retention_days is null. Schedule it if you want automatic pruning:

Filament plugin

An optional, read-only ConsentLogResource is available if filament/filament is installed. Filament v3, v4 and v5 are all supported, from the same one-line registration — the plugin detects the installed major and registers the matching resource, so there is no version to pass.

There is nothing to publish. The resource is plain PHP registered at runtime; no vendor:publish tag covers it, and no assets or views are involved. You only add the plugin to your panel provider — typically app/Providers/Filament/AdminPanelProvider.php:

Reload the panel and a Consent Logs item appears in the sidebar, at /{your-panel-path}/consent-logs.

Two reasons it might not show up:

The resource sets no navigation icon and no navigation group, so it appears at the top level of the sidebar with an empty icon slot.

To see which Filament build was detected:

The two builds are feature-identical; only the Filament API differs. Filament v4 moved infolists onto Filament\Schemas\Schema and renamed the table row-action method, and that changed the signature of Resource::infolist() — so a resource written for one side of that break is a fatal error at class-load time on the other, not a recoverable failure. That is why the two live in separate namespaces (Filament\Resources\… for v4/v5, Filament\V3\Resources\… for v3) and why the branch is a class-name probe rather than a runtime check. Only the matching one is ever autoloaded. If you reference the resource class directly rather than through the plugin, use Core45\CookieConsent\Filament\FilamentVersion::resourceClass() instead of naming it yourself.

The resource has no create/edit pages — consent logs are evidence, not editable records. Each row opens a read-only modal showing every stored field, including rejected_categories, accepted_services, policy_hash and the raw payload.

That modal is a ViewAction, which is authorized by a view() policy method. If you run Filament's strictAuthorization() and have a ConsentLog policy, it now needs view() alongside viewAny(), otherwise Filament throws a LogicException. Apps with no policy, or without strict authorization, are unaffected.

iframemanager

Gate third-party embeds (YouTube, Vimeo, maps, ...) behind a consent category with a click-to-load placeholder, using iframemanager.

Place @iframemanager near @cookieconsent (typically right after it):

Then drop a placeholder wherever you'd normally embed the iframe:

Per-service copy (loadBtn, notice, ...) comes from lang/vendor/cookieconsent/{locale}/iframemanager.php, keyed by service name (youtube in the example above), just like the main cookieconsent.php lang file.

Advanced JS / custom callbacks

Two ways to hook into the banner's behavior beyond what the config array exposes:

*1. `cc:window events** — orestbida/cookieconsent dispatchescc:onFirstConsent,cc:onConsent,cc:onChange, cc:onModalReady,cc:onModalShow, andcc:onModalHideonwindow`. Listen to them from any script on the page, inline or bundled:

2. The cookieconsent:config push stack — runs after the revived config JS variable is declared but before CookieConsent.run(config) is called, so you can mutate config in place (e.g. make a static option dynamic):

Google Consent Mode recipe

Combining both mechanisms to wire up Google Consent Mode v2:

Content Security Policy

If your app runs under a strict CSP, set csp_nonce to a callable that returns the per-request nonce:

Every inline and external <script> tag the package itself renders (@cookieconsent, @iframemanager) gets a nonce="..." attribute automatically.

CSP caveat. Scripts you push via @push('cookieconsent:config') are plain Blade/HTML — they do not automatically inherit the configured nonce. Under a strict CSP you must add nonce="..." to your own pushed <script> tags yourself, e.g. <script nonce="{{ $nonce }}">...</script>.

Versioning & License

This package follows Semantic Versioning. It is open-sourced under the MIT license, Copyright (c) 2026 core45.


All versions of laravel-cookieconsent with dependencies

PHP Build Version
Package Version
Requires php Version ^8.4
illuminate/support Version ^12.0|^13.0
illuminate/http Version ^12.0|^13.0
illuminate/database Version ^12.0|^13.0
Composer command for our command line client (download client) This client runs in each environment. You don't need a specific PHP version etc. The first 20 API calls are free. Standard composer command

The package core45/laravel-cookieconsent contains the following files

Loading the files please wait ...