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

Privacy Settings Bundle Laravel Package

symfinity/privacy-settings-bundle

A Symfony bundle for managing user privacy settings and consent preferences. Configure privacy options, persist choices, and integrate GDPR-style consent handling into forms, templates, and services with a simple, extensible API.

View on GitHub
Deep Wiki
Context7

Getting Started

First, the reality check — do this before anything else. Despite the domain fit, this is a Symfony bundle, not a Laravel package. Open composer.json and look at require: if it lists symfony/framework-bundle, symfony/http-kernel, doctrine/orm and no illuminate/*, then:

  • There is no extra.laravel.providers entry, so Composer auto-discovery does nothing.
  • php artisan vendor:publish has no tag to publish — config lives in a Symfony Extension/Configuration tree, migrations are Doctrine migrations, and storage is a Doctrine entity, not an Eloquent model.
  • Manually registering its *Bundle class in config/app.php will not work; a Symfony bundle expects a Symfony kernel/container.

So the day-to-day question is not "how do I install it" but "do I adopt it as a spec, or adapt it."

Where to look first (15–20 minutes of reading):

  1. composer.json — framework requires, PHP range, whether it's Packagist or VCS-only.
  2. DependencyInjection/Configuration.php — this is the category/purpose schema. It tells you what consent categories you can define and what the default-deny behaviour looks like.
  3. The consent-check service (in src/ — grab the FQCN; it's the one method you'll call everywhere).
  4. The storage entity + repository — the record shape you must map to your users table or an equivalent subject identifier.
  5. The Twig extension and the event classes — these are the two integration surfaces you'll be reimplementing.

Minimal steps, if you proceed:

composer require symfinity/privacy-settings-bundle:~0.2.3

Pin the exact minor. Read CHANGELOG.md at tag v0.2.3 (the release note is only a link) and run its test suite on your PHP/Laravel matrix before writing a line of glue.

First use case to target: a single cookie/marketing consent gate. Define two or three categories in its config, map its consent record onto a table keyed by a stable subject id (user id when authenticated, a device cookie otherwise), and expose exactly one method to your app: granted($subject, 'marketing'): bool. Nothing else — no banner redesign, no CMP replacement — until fail-closed semantics are proven.

Implementation Patterns

1. Wrapper-first, always. Do not let bundle classes leak into controllers, Blade, or jobs. Define a Laravel-side contract:

interface Consent
{
    public function granted(?string $subject, string $category): bool;
    public function record(string $subject, string $category, bool $granted, string $policyVersion, string $source = 'app'): void;
    public function withdraw(string $subject, ?string $category = null): void;
    public function export(string $subject): array;
}

Bind either a thin adapter over the bundle's service (if you keep the dependency) or a native implementation informed by its category schema. Every call site now survives the package being abandoned or replaced — which, given single-maintainer status and pre-1.0 versioning, you should assume will happen.

2. Resolve once per request, memoise hard. Consent lookups are per-page-view. Register the consent service as a scoped singleton and populate it from a middleware (or a queued Terminating listener) so @consent('marketing') in three partials costs one query, not three. Back the scoped instance with a short-TTL cache keyed consent:{subject} and bust it on the consent-changed event.

3. Mirror the Twig helpers as Blade directives. The bundle ships Twig; you live in Blade. Register a compiler directive that forwards to your contract:

Blade::if('consent', fn (string $category) => app(Consent::class)->granted($this->subjectKey(), $category));
// @consent('marketing') ... @endconsent

Keep the semantics identical to the package's so a future port is a swap, not a rewrite.

4. Bridge consent-change events to Laravel events. The bundle's hooks are Symfony events. If you keep it in-process, subscribe them and re-dispatch as ConsentChanged($subject, $category, $granted, $version). Listeners: cache invalidation, audit-log row, downstream CMP/vendor sync, marketing-tag suppression. This event is also your instrumentation point — log every decision with category and policy version at debug.

5. Map storage deliberately, not incidentally. Doctrine entity ≠ Eloquent model, and php artisan migrate will not create its table. Two viable paths: (a) let the bundle own the table and read/write it via DB::connection()->table(...) with a hand-written Laravel migration matching its schema, or (b) own an Eloquent ConsentRecord and dual-write while the package remains a shadow reader. Either way the record must carry, at minimum: subject id, category, granted, policy version/hash, timestamp, source/UI variant. That set is your DSAR export and your audit defence.

6. Treat a category-config change as a migration. Bumping the policy version in config means previously captured grants are stale and must be re-prompted — not silently carried forward. Ship config changes and the corresponding re-consent flow in the same release, and note it in the migration doc.

7. Backfill with an explicit "unknown/legacy" state. An artisan consent:backfill command mapping your current records into the new shape, with a documented third state so historical users are never silently reclassified as opted in. Pair it with consent:export {subject} for DSAR fulfilment — write it before you need it.

8. Roll out behind a flag with the legacy path retained. One release of coexistence (shadow-read: compute consent both ways, log mismatches, enforce the old path) before the new one becomes the system of record.

Gotchas and Tips

  • No vendor:publish, no auto-discovery, no Eloquent. If you're scanning for these, stop: they don't exist here. The absence of a publishable config tag is the tell.
  • Fail-open is disqualifying — verify it yourself. Inject a failure (kill the DB connection, throw from the consent service) and assert every call returns false. Wrap every call site in try/catch → false regardless of what the package does internally. This is the one test that must exist before production traffic.
  • Default for an undefined category. Confirm whether an unknown category denies or throws. Add a guard in your wrapper so a typo in a Blade directive can never evaluate truthy.
  • Anonymous → authenticated transition. The subject key must survive login (device cookie or pre-auth consent record merged on auth), or users re-consent on every session and your audit trail fragments.
  • Pre-1.0 semver. ^0.2 permits breaking changes on 0.3.0. Pin ~0.2.3, review every minor bump manually, and never let a dependency bot auto-merge one — this is a compliance control, not a utility library.
  • Opaque release notes. v0.2.3 links to CHANGELOG.md with no inline summary. Read the tag body and the diff before upgrading; you cannot otherwise distinguish a docs fix from a consent-evaluation bug.
  • Rebuilding the form-tier UI in Blade is unavoidable. Keep it server-rendered with a POST: "reject all" must work without JavaScript and be as prominent as "accept all", no pre-ticked boxes. JS-only consent UI is the most common way to invalidate the whole implementation.
  • Read amplification, not write volume. Writes are rare; reads are every request. If the package lacks caching, add it in the wrapper, and check multi-server cache invalidation on the consent-changed event.
  • Debugging is invisible by default. Log allow/deny with category, policy version, and subject hash — you will need it to explain to legal why a user saw a particular banner.
  • Bus factor. Single-maintainer namespace, no documented security contact, no LTS. Assume community-only support; the wrapper contract is your insurance policy. Ensure at least one reviewer outside engineering signs off on the default-deny behaviour before rollout.
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.
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console
pnscripts/filament-broadquill-lite
pnscripts/laravel-sentfold-lite
vleap/mx-sdk-laravel-internal
twidpay/utils
htetmyathlaing/scout-elasticsearch-driver
artisan-toolbox/front-awesome
ls/client-assistant
users-au/laravel-client
robertmarney/lara-hierarchial-collections
simonschaufi/rule-doc-generator
emissaoja/emissaoja
blackbricksoftware/gravityforms-civicrm-form-processor
al-rahabi/fancy-crud
jinas/dhivatar-component
mltstephane/laravel-quality
bernskiold/laravel-talentlms
bernskioldmedia/laravel-form-architect