NewWe open-sourced 50+ Laravel packages
Custom AI apps, agents and automation — Roundly ConsultingRoundly
All packages
Likes for Laravel

Configuration

The published config/likes.php, without its comments:

use RoundlyConsulting\Likes\Models\Like;

return [
    'model' => Like::class,
    'table' => env('LIKES_TABLE', 'likes'),
    'key_type' => env('LIKES_KEY_TYPE', 'bigint'),
    'reactions' => ['like'],
    'default_reaction' => env('LIKES_DEFAULT_REACTION', 'like'),
    'actor_resolver' => null,
    'facade_alias' => env('LIKES_FACADE_ALIAS', 'Likes'),

    'weights' => [
        // 'like' => 1,
        // 'love' => 4,
    ],
    'default_weight' => 1,

    'trending' => [
        'window' => '7 days',
        'recent_multiplier' => 3,
        'driver_expressions' => [
            // 'pgsql' => 'SUM(1 / POWER(EXTRACT(EPOCH FROM (NOW() - created_at)) / 3600 + 2, 1.8))',
        ],
    ],

    'broadcast' => [
        'enabled' => env('LIKES_BROADCAST', false),
        'channel_prefix' => 'likes',
        'channel_type' => 'private',
    ],
];

Every key

KeyDefaultEnvPurpose
modelLike::class—Eloquent model that stores likes. Must be the package model or extend it; any other class throws InvalidConfigurationException.
tablelikesLIKES_TABLELikes table — read by the migration, the model and every scope. A string; a blank value (LIKES_TABLE=) is not set and takes the default.
key_typebigintLIKES_KEY_TYPEKey type of the actor and likeable morph columns — bigint, uuid or ulid. Set it before migrating when your actors or likeables use UUID/ULID keys; any other value throws InvalidConfigurationException.
reactions['like']—Allowlist of reaction types — a non-empty list of strings. Any other type throws InvalidReactionTypeException.
default_reactionlikeLIKES_DEFAULT_REACTIONReaction used when none is given. Must be listed in reactions.
actor_resolvernull—How the facade resolves the actor: null uses auth()->user(); or a callable / invokable class-string returning a model or null. A value that doesn’t resolve to a callable throws.
facade_aliasLikesLIKES_FACADE_ALIASGlobal class alias for the Likes facade. null or false/0/off/no (LIKES_FACADE_ALIAS=false) skips the alias; a blank value is not set, so Likes is registered.
weights[]—Per-reaction weights for orderByLikeScore() and orderByTrending(). Empty means the score is the raw count. Every weight must be an int or a float.
default_weight1—Weight of any reaction not listed in weights (applies once weights is non-empty); an int or a float.
trending.window7 days—Recency window used by orderByTrending(); a string (blank takes the default).
trending.recent_multiplier3—How much likes inside the window outweigh all-time activity (int or float; anything else throws).
trending.driver_expressions[]—Optional raw SQL aggregate per database driver (sqlite, mysql, pgsql, …) that replaces the trending score for queries on a connection of that driver. Every ? is bound to the window cut-off. A non-string expression throws; a blank one is not set, so the portable score applies.
broadcast.enabledfalseLIKES_BROADCASTOpt-in broadcasting of Liked, Unliked and ReactionChanged. Env strings such as true/1/on and false/0/off are understood; anything else throws InvalidConfigurationException.
broadcast.channel_prefixlikes—Channel name prefix, e.g. likes.posts.42; a string (blank takes the default).
broadcast.channel_typeprivate—private, public or presence; anything else throws.

A key that is not set — absent, null, or blank like a host’s LIKES_TABLE= — takes its default (a blank driver expression: the portable score). A value that is set must fit: a non-string table, default_reaction, trending.window or broadcast.channel_prefix, a reactions list that is empty or holds a non-string, a non-numeric weight, multiplier or default weight, a non-string driver expression or a broadcast.channel_type typo — it no longer reads as private — throws InvalidConfigurationException instead of falling back or being dropped.

Environment

The deployment-sensitive keys are env-backed, so you rarely need to publish the config at all:

LIKES_TABLE=likes
LIKES_KEY_TYPE=bigint
LIKES_DEFAULT_REACTION=like
LIKES_FACADE_ALIAS=Likes
LIKES_BROADCAST=false

Rules worth knowing

  • table and key_type are read when the migration runs — set them before you migrate.
  • default_reaction must be one of reactions; otherwise every call without an explicit type throws InvalidReactionTypeException.
  • A closure in actor_resolver works, but Laravel can’t cache config that contains closures — prefer an invokable class-string with php artisan config:cache.
  • Broadcasting is off until broadcast.enabled is true; the events are dispatched to your listeners either way.

Show your open-source love

This package is free and MIT-licensed. If it saves you time, a one-off donation or a Patreon membership keeps it maintained, tested and documented.

More ways to support, including crypto

By donating, you agree to our donation terms.

Want this built into your product?

We integrate our packages into custom Laravel and AI builds. Tell us what you're working on and we'll reply within 48 hours.