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 Follow Bundle Laravel Package

tourze/user-follow-bundle

Tourze User Follow Bundle adds user follow relationships to Symfony applications. It offers follow and unfollow actions, follower and following lists, and straightforward integration with existing user entities, helping you implement social features like subscriptions and activity feeds with less cu...

View on GitHub
Deep Wiki
Context7

Getting Started

Install the package and confirm what you actually pulled in:

composer require tourze/user-follow-bundle:^0.0.1

Before writing any code, read the tree in vendor/tourze/user-follow-bundle/src/. At 0.0.1 there is no published documentation, so the source is the documentation. Pay attention to three things, in this order:

  1. The entity/model classes — this is a Symfony bundle in the Tourze ecosystem, which means the follow relationship is expressed as a Doctrine entity (typically something like UserFollow with follower / following associations), not an Eloquent model. That distinction drives everything else.
  2. The manager/service class — the class that exposes follow(), unfollow(), isFollowing(), getFollowers(), getFollowing(). That is your day-to-day API surface.
  3. The bundle extension / config class — check whether the entity class names and table names are configurable. At this version they may be hardcoded.

Your first use case is almost always the same: a "Follow" button on a user profile page, plus a follower/following count. Wire the manager into a controller, call follow($currentUser, $targetUser), and render a boolean from isFollowing() to decide whether the button says Follow or Unfollow. Get that one round trip working end to end before touching feeds or notifications.

Because this is a Symfony bundle rather than a native Laravel package, budget time for the bridge step: doctrine/orm plus a Doctrine integration package (e.g. laravel-doctrine/orm) and a mapping configuration that points at the bundle's entity namespace. If your app is Eloquent-first, decide now whether you are willing to run a second ORM alongside Eloquent for one feature. For many teams the honest answer is no, and the alternative is to copy the schema and reimplement the two-table relationship in Eloquent — the business logic is small enough that this is often cheaper than a dual-ORM setup.

Implementation Patterns

Wrap the manager, don't scatter it. The bundle's manager will be referenced from controllers, API resources, policies, and feed builders. Put a thin application-level service in front of it (FollowService in app/Services) so that a 0.1.x rename of the vendor class is a one-file change, not a find-and-replace across the codebase. At 0.0.1 this is not optional defensive coding; it is the primary risk mitigation.

Treat follow/unfollow as idempotent commands. Users double-click, retry after a timeout, and hit stale buttons on cached pages. Guard the call site with an existence check, and make the underlying insert tolerant of a duplicate (unique index on the follower/following pair). Do not rely on the bundle to deduplicate — verify it, because a 0.0.1 package frequently does not.

Self-follow and blocked users are your responsibility. The bundle models a relationship; it does not model your product rules. Reject $user->id === $target->id at the service layer, and check your block/ban state before calling follow(). Centralizing this in the wrapper service keeps every entry point (web, API, artisan command) consistent.

Counters: denormalize or aggregate, pick one deliberately. Two shapes work:

  • Aggregate on read with count() on the follow repository — simpler, correct, but expensive on profile pages under load.
  • Denormalized followers_count / following_count columns on your user table, incremented alongside the follow operation — fast reads, but now you own consistency and need a reconciliation command.

Start with the aggregate while you are validating the feature, then move to denormalized counters once you have real traffic. Write the reconciliation artisan command at the same time you write the increment, not later.

Feed assembly: query in two steps. For a "posts from people I follow" feed, resolve the follow list first (getFollowing($user) → array of IDs), then query your posts table with whereIn('userable_id', $ids). Resist the urge to join the follow table into your content query — the follow table lives in a different mapping context and cross-ORM joins will fight you.

Events are the extension point to watch for. If the bundle dispatches domain events on follow/unfollow, hook notification and activity-log listeners to those events rather than to your controller. If it does not dispatch events at 0.0.1, add your own dispatch inside the wrapper service so listeners have a stable seam.

API responses. Follow relationships serialize badly by default (recursive user → follows → user). Never return the raw entity from a controller. Map to a small DTO: { following: bool, followers_count: int, following_count: int }.

Gotchas and Tips

Version 0.0.1 means the public API is not stable. The release carries only an auto-generated changelog link — no feature list, no migration notes, no BC promise. Pin the exact version in composer.json ("tourze/user-follow-bundle": "0.0.1", not ^0.0.1) and read the diff before every bump. Assume the next patch release may rename methods.

Symfony bundle in a Laravel app: registration is manual. There is no package discovery for Symfony bundles. You will need to register the bundle's service definitions yourself — either through a Doctrine integration package's bundle registration or by hand-binding the manager class in a service provider. If the constructor signature depends on Symfony's container or EntityManagerInterface, that binding is where the friction shows up. Solve this before you build features on top of it.

Migrations are yours. Doctrine's schema:update tooling and Laravel's migration system do not share a source of truth. Generate the SQL from Doctrine once, then commit it as a normal Laravel migration so your deploy pipeline stays uniform. Do not let two tools own the same tables.

Watch the N+1 on list pages. A followers list that renders each row with an isFollowing() check will issue one query per row. Batch it: pull the set of IDs the current user follows in a single query, then check membership in PHP.

Composite unique index. Confirm the schema actually enforces uniqueness on (follower_id, following_id). If it does not, add it in your migration. Without it, race conditions during double-submits silently create duplicate relationships, and every count downstream is wrong.

Deletion semantics. Decide what happens when a user is deleted: cascade the follow rows, or soft-delete and keep the graph. The bundle may only offer one behavior. Test it explicitly — orphaned follow rows produce confusing counts and broken feeds.

Debugging blind. With no docs and no debug toolbar integration, the fastest path is: log the manager's method calls in your wrapper, then dd() the raw repository result. If something returns unexpectedly empty, check the mapping configuration first — a mismatched entity namespace produces empty results rather than an error, which is the single most time-consuming failure mode with Doctrine-backed bundles.

Escape hatch. If the bundle's manager blocks a requirement (soft deletes, tenant scoping, a followed_at timestamp you need for sorting), you can usually keep the entity and mapping and query the repository directly with your own DQL. That is a legitimate move at this maturity level; you are not obligated to route everything through the vendor service.

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.
tequilarapido/trackit
gregsphotography/site-builder-filament
cabaoctavio/laravel-query-log
gregsphotography/site-builder-components
io-digital/clickatell
snowsoft/laravel-admin
oxygen/auth
relicsoftware/barakah-payment-gateway
tobya/work-with-composer
equipc/laravel-email-validator
equipc/laravel-email-database-log
adedsec/nova-translated-labels
wazza/laravel-db-encryption
hokny/laravel-generator
vonsogt/backup
jengo/queues
jeremykenedy/laravel-observability
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums