Product Decisions This Supports
- Build vs. buy for social-graph features. The bundle's domain — friends, contacts, followers, org membership, "related items" — maps onto recurring roadmap items. It is a reference point for the build side of that decision only, not a viable buy: it is a Symfony 2 bundle (not Laravel), unmaintained, with 10 stars and 0 dependents. It informs what to build, not what to install.
- Schema and feature scoping. Relations are not a bare join table. They need relation types (friend vs. contact vs. block), symmetry (mutual vs. directional), and lifecycle status (pending → accepted → revoked). The bundle's abstraction is a useful checklist to pressure-test your own data model before committing to a migration.
- Roadmap triage: do-not-adopt / decommission entry. With an explicit "NOT MAINTAINED ANYMORE" notice and a Symfony 2 footprint, this belongs in the "avoid" column. It is only actionable as technical-debt inventory if a legacy service already vendors it.
- Framework-fit as a hard gate. This is a Symfony 2 bundle targeting Doctrine ORM; a Laravel codebase cannot consume it without a bridge or port. That converts a "cheap dependency" into a build project whose starting point is a foreign, dead codebase.
- Vendor-risk calibration. Treat it as a floor example in your package-evaluation rubric: unmaintained + no modern PHP/framework support + zero downstream adoption = score near zero (the 0.23 is directionally correct).
When to Consider This Package
Consider it only in narrow, non-production contexts:
- Reference reading. You want a worked example of typed/stateful relations in a Doctrine/Symfony codebase and are extracting schema and semantics — not code.
- Legacy archaeology. An inherited Symfony 2 app already depends on it and you need to scope a migration off it before EOL forces the issue.
- Throwaway spike. A disposable prototype where the bundle is already vendored and you accept zero maintenance guarantees.
Look elsewhere — actively — when:
- Your stack is Laravel. Framework mismatch is dispositive. Eloquent's
morphToMany / morphMany with a polymorphic pivot already covers the stated problem; there is no functional gap this fills.
- You need supported PHP versions. Symfony 2 implies a PHP 5.x lineage; assume PHP 8.x compatibility is broken until a test proves otherwise.
- You need a security response path. "Not maintained" means no one answers the CVE call.
- You need team legibility. Zero adoption means no Stack Overflow answers, no fork lineage, no one on the team has seen it — onboarding cost is entirely yours.
- You need graph traversal at scale. For friend-of-friend, recommendations, or permission inheritance, plan a purpose-built adjacency/closure design, not an ORM relationship bundle.
- A pivot table plus a small service is cheaper. That covers ~80% of friends/contacts needs at a fraction of the TCO.
How to Pitch It (Stakeholders)
For executives: Short version — we are not adopting this. It is an unmaintained Symfony 2 bundle (10 stars, 0 dependents, author has declared it dead) being weighed against a Laravel codebase, so it is a framework mismatch on top of outright abandonment. Recommended decision: no-go as a dependency. TCO, not license cost, is the deciding factor. The problem space — follows, contacts, relationships — is real and on our roadmap; we solve it with a small in-house Eloquent implementation, which for typical requirements is days of work, not a migration project. The bundle's only durable value is the problem framing, worth about a day of reading before we design our own tables.
For engineering: The bundle offers a sensible conceptual model (typed relations, symmetry, status lifecycle) worth ~30 minutes of reading for schema ideas before we build. Do not add it to composer.json. Extract the shape — a single relations pivot (source type/id, target type/id, relation type, status, timestamps) with a composite unique index on the source/target/type tuple and reverse-lookup indexes on the target columns — then reimplement with morphToMany plus a pivot model for state transitions. Keep symmetry enforcement in one service class, write the invariant tests first (bidirectional dedupe, self-relation rejection, block precedence, idempotent accept, polymorphic orphan cleanup), and budget the work as a short self-contained cycle with one owner, not a "quick win" behind other work. If a legacy service already uses it, flag it as technical debt with a concrete exit in the next framework-upgrade cycle.