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

Referral Program Laravel Package

elcodi/referral-program

Referral program add-on for Elcodi e-commerce that helps you create and manage referral codes, track invites and conversions, and reward customers for bringing in new buyers.

View on GitHub
Deep Wiki
Context7

Getting Started

Before writing a line of code, confirm what you are actually adopting. elcodi/referral-program is one component inside the archived elcodi/elcodi monorepo — last tagged release 2016-02-15, EOL, zero dependents, built for Symfony 2.x / PHP 5.5–7.0. There is no maintainer, no security process, and no upgrade path. Treat this as reference material you vendor or fork, not a composer require you bolt onto a modern app.

Minimal evaluation steps:

  1. git clone https://github.com/elcodi/elcodi — do not install via Packagist into a Symfony 5/6/7 project; the DI extension, XML service definitions, and Doctrine mapping conventions will fail to load.
  2. Read in this order:
    • src/Elcodi/Component/ReferralProgram/Entity/ — the domain model (program, invitation, referral hash/token, and the rule that binds a program to a coupon).
    • src/Elcodi/Component/ReferralProgram/Resources/config/doctrine/ — the XML mappings; this is the real specification of the schema.
    • src/Elcodi/Component/ReferralProgram/Services/ — the managers (*Manager.php) that own the lifecycle.
    • src/Elcodi/Component/ReferralProgram/Events/ + EventListener/ — the extension surface.
  3. Skim elcodi/coupon and elcodi/user, since the referral component depends on both and inherits their base entity traits (id, enabled, createdAt, updatedAt).

The canonical first use case is invite-a-friend: an existing user gets a referral hash/link, a new visitor registers through it, an invitation record moves through its states, and a coupon is issued on conversion. Build that end-to-end in a scratch project (or a test harness around the entities) before deciding whether the abstraction is worth porting.

Implementation Patterns

Programs as seeded configuration, not admin-created rows. A referral program is a small aggregate: an identity, a set of rules, and a coupon linkage. Create them in fixtures or a Doctrine migration with stable slugs, and reference programs by slug in application code. Letting merchandisers create programs freely tends to produce orphaned invitations and unclaimable coupons.

The hash is the public identifier. Never expose user IDs in referral URLs. Generate the referral hash through the component's manager on user creation (or lazily on first "invite" click), persist it, and resolve inbound traffic with a single lookup service of your own that wraps the component's repository. Keep that resolver behind an interface — it's the one piece you will definitely rewrite.

Model the invitation lifecycle explicitly. The component gives you states around invited → registered → converted/rewarded. Push transitions through a thin application service rather than mutating entities from controllers, and make each transition idempotent: registerInvitation($hash, $newUser) should no-op if an invitation already exists for that pair. Duplicate invitation rows are the number one production bug in referral systems.

Issue coupons on the conversion event, not on registration. Listen for the referral conversion/reward event and call the elcodi/coupon coupon manager there. Store the issued coupon code on the invitation row so you can reconcile, revoke, and report. If you're porting the model, keep this as a domain event (ReferralConverted) so coupon issuance stays in a listener — it's the cleanest seam in the whole component.

Keep business logic in listeners/subscribers. The component is dispatcher-driven and was designed to be extended without editing it. If you fork it, preserve that: a ReferralProgramListener that reacts to your app's UserRegistered event, resolves the hash, and creates the invitation is preferable to subclassing a manager (which drags you into constructor signature churn across the Elcodi graph).

For modern Symfony, port — don't install. Copy the entity classes and XML mappings into your own namespace, re-express the mappings as attributes or YAML, and reimplement the two or three managers you actually need (hash generation, invitation creation, reward issuance). The domain is genuinely small; a faithful reimplementation is typically 300–500 lines and removes the elcodi/coupon, elcodi/cart, and elcodi/product transitive baggage entirely.

Reporting is a simple group-by. Conversion rate per program = invitations with a reward / invitations created, grouped by program ID over a date window. Build it as a query on your own invitation table; don't expect the component to ship analytics.

Gotchas and Tips

  • The dependency graph is the trap. Depending on this component pulls elcodi/coupon and elcodi/user, and in practice most of the Elcodi e-commerce stack. Audit composer why before assuming it's lightweight — it is not.
  • XML Doctrine mappings need manual registration. If you use the entities without the bundle, add Resources/config/doctrine to your doctrine.orm.mappings config explicitly, or you'll get "table not found" errors that look like cache problems.
  • Old DI and PHPUnit. Service definitions use Symfony 2.x XML/YAML schemas and the tests target PHPUnit 4/5. Neither will run on a current toolchain without edits; budget for that or skip the tests and write your own.
  • Entity base classes are shared. Elcodi entities commonly extend base classes and use traits for timestamps and enabled flags. When you copy an entity, copy its parents too, or flatten them into a self-contained class.
  • Coupon coupling assumptions. Coupon issuance assumes Elcodi's coupon semantics, including its currency and validity handling. Multi-currency or percentage-based promotions will need review — this is the most likely place for silently wrong discounts.
  • No community to fall back on. Zero dependents means Stack Overflow has nothing for you. Debugging is source reading; add dump() calls liberally around the manager methods rather than guessing at intended behavior.
  • Extension points, ranked. Event listeners (best, portable) → repository overrides via DI alias (fragile) → subclassing managers (avoid). If you're forking, replace the DI wiring outright rather than trying to satisfy the original service signatures.
  • Pin and vendor if you must ship it. Use a VCS repository entry pointing at your fork, pin PHP to the last version that works, and add integration tests around the invitation lifecycle immediately. There will be no upstream fixes, ever — the fork is yours to own.
  • Opportunity signal is low (0.27). Read that as: this package's ideas are more valuable than its code. Use it to sanity-check your own model — particularly the program/rule/coupon separation and the hash-as-identity pattern — then implement the 5% you need.
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.
coleus/frame
thtg88/journalism
filagora/filagora-ai-forums
rlacerda83/query-parser
socialdept/atp-orm
cboxdk/laravel-assistant-client
socialdept/atp-resolver
socialdept/tenant-domains
tautvydasr/blade-class-names
socialdept/color-scales
maherelgamil/controller
coleus/widgets
coleus/table
coleus/users
coleus/music
coleus/health
coleus/calendar
coleus/notes
coleus/support
coleus/settings