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

User Agreement Bundle Laravel Package

tourze/user-agreement-bundle

A Symfony bundle for managing user agreements, terms acceptance, and consent records, with configurable entities and services to track agreement versions and user approvals in PHP applications.

View on GitHub
Deep Wiki
Context7

Getting Started

The package ships as a Symfony-style bundle (user-agreement-bundle), not a Laravel package. There is no Tourze\UserAgreement\ServiceProvider, no vendor:publish, and no config file merged into config/. That shapes every step below.

  1. Install and inspect what you actually got.

    composer require tourze/user-agreement-bundle
    

    Then read, in this order:

    • composer.json → the require block. Check the symfony/* and doctrine/* constraints against the versions your Laravel app can support. This is the single biggest compatibility risk.
    • src/Entity/ → the persistence model (agreement document, agreement version, and a per-user acceptance record — naming varies).
    • src/Repository/ → the read entry points you'll actually call.
    • src/Resources/config/ → the service wiring, which tells you what is injectable and what needs manual construction.
  2. Decide how you'll bridge it. Two viable routes:

    • Doctrine in Laravel (doctrine/orm + a DB connection config) and use the entities as shipped. Most faithful to the package, most setup work.
    • Port the entities to Eloquent and use the bundle as a reference implementation for the domain logic. Less setup, but you're maintaining a fork of the model.
  3. First use case: gate a route on "user has accepted the current Terms version." Register an alias in bootstrap/app.php for a middleware that resolves the current agreement version, looks up the user's latest acceptance record, compares version IDs, and redirects to a re-consent page on mismatch.

Implementation Patterns

Versioned acceptance, not boolean flags. The durable pattern is agreement → versions → acceptance_records(version_id, user_id, accepted_at). Never mutate an agreement in place; publish a new version row and let acceptance point at the version ID. Your "has this user agreed?" check becomes "does a record exist for the current version," which stays correct across policy updates.

Middleware gate. Resolve the active version once per request, compare against the user's latest acceptance, and short-circuit to a re-consent route. Cache the "current version ID" (it changes rarely) and only hit the acceptance table on the hot path.

Re-consent flow on version bump. When current_version_id changes, every user with an older acceptance becomes pending. Prefer a lazy check at request time over a mass backfill job — it avoids a migration storm and degrades gracefully for inactive accounts.

Audit trail. Store accepted_at, IP, user agent, and the version ID together. This is the only thing that makes the feature defensible in a dispute, and it is cheap to add at write time.

Where to put the boundary. Keep a thin app-level service (or repository wrapper) between your controllers and the bundle's classes. Symfony bundles frequently expose concrete classes rather than interfaces, and that wrapper is what saves you when a patch release reshuffles a constructor.

Seed agreements in a migration or seeder, not in application code, so environments stay consistent and the version IDs are reproducible.

Gotchas and Tips

  • No Laravel integration is provided. Everything is manual: no service provider, no facade, no config merge, no auto-discovery. Budget for wiring time.
  • Doctrine vs Eloquent is a real fork in the road. Doctrine in Laravel works but drags in its own entity manager, proxies, and console commands. If your app is otherwise Eloquent-native, porting the ~3 entities is often cheaper than the integration.
  • 1.0.x is pre-stabilization territory. The 1.0.2 release note is only a changelog compare link with no described changes. Treat patch bumps here as unreviewed: read the diff (.../compare/1.0.1...1.0.2) before deploying, and pin an exact version in composer.json rather than a caret constraint.
  • Schema ownership is ambiguous. A Symfony bundle usually ships Doctrine mapping metadata, not Laravel migrations. You will likely be generating migrations yourself — verify table/column names against the mapping rather than guessing.
  • Cache invalidation on version bump. If you memoize the current version, make sure publishing a new agreement clears it. A stale cache here silently lets users through without re-consent.
  • Extension points to prefer: the repository classes (override or wrap them) and any Symfony event dispatcher hooks, if the bundle fires acceptance events. Those are more stable across patches than the entities' constructors.
  • Debugging tip: when an acceptance check misbehaves, dump the resolved version ID and the record's version ID side by side. Nearly every bug in this domain is a mismatch between "current" and "recorded," not a persistence failure.
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