---
title: "The Likes facade — Likes for Laravel | Roundly"
description: "One-line likes as the signed-in user, the actor()/as() builder, the Likes::for() read handle and custom actor resolution."
url: https://roundly-consulting.com/open-source/docs/likes-for-laravel/facade
language: en
---

[All packages](https://roundly-consulting.com/open-source.md)

[Likes for Laravel](https://roundly-consulting.com/open-source/docs/likes-for-laravel.md)

# The Likes facade

RoundlyConsulting\\Likes\\Facades\\Likes resolves the actor from the authenticated user by default, so the common path is one line. Override the actor or reaction type with the fluent builder, and read one likeable with Likes::for():

```php
use RoundlyConsulting\Likes\Facades\Likes;

Likes::like($post);                     // as the authenticated user
Likes::unlike($post);
Likes::toggle($post);
Likes::react($post);                    // one active reaction per actor + likeable
Likes::has($post);                      // bool
Likes::likeMany([$post, $comment]);
Likes::unlikeMany([$post, $comment]);

Likes::actor($user)->like($comment);    // as any actor
Likes::actor($team)->toggle($post);
Likes::as('love')->like($post);         // typed reaction
Likes::actor($user)->as('wow')->toggle($post);
Likes::actor($user)->as('love')->react($post);  // switch reaction in place
Likes::actor($user)->has($post);
Likes::actor($user)->likeMany([$post, $comment]);

Likes::for($post)->count();             // int — all reactions (uses an eager-loaded likes_count)
Likes::for($post)->count('love');       // int — one reaction type
Likes::for($post)->summary($viewer);    // ReactionSummary (viewer defaults to the resolved actor)
Likes::for($post)->likedBy($user);      // bool — default reaction type unless given
```

## Methods

| Method | Returns | Description |
| --- | --- | --- |
| `actor(Model $actor)` | PendingLike | Start a chain for a specific actor. |
| `as(string $type)` | PendingLike | Start a chain for a specific reaction type. |
| `like(Model $likeable)` | bool | Ensure liked; returns true. |
| `unlike(Model $likeable)` | bool | Ensure not liked; returns false. |
| `toggle(Model $likeable)` | bool | Toggle; returns the new state. |
| `react(Model $likeable)` | bool | Set the actor’s single reaction, switching in place. |
| `has(Model $likeable)` | bool | Whether the actor has the reaction (default type unless as() is used). |
| `likeMany(iterable $likeables)` | void | Bulk like. |
| `unlikeMany(iterable $likeables)` | void | Bulk unlike. |
| `for(Model $likeable)` | LikeableLikes | Read handle for one likeable — count(), summary(), likedBy(). |
| `fake()` | LikesFake | Swap in the recording test fake. |

## The for() read handle

Likes::for($likeable) returns a LikeableLikes handle: count(?type) uses an eager-loaded likes\_count when no type is given, summary(?viewer) returns a ReactionSummary for the viewer (the resolved actor by default), and likedBy($actor, ?type) checks the default reaction type unless you pass one.

## The model traits are sugar

HasLikes and GivesLikes call the same manager, so everything here — including Likes::fake() — applies to them:

```php
$user->like($post);          // = Likes::actor($user)->like($post)
$post->likesCount();         // = Likes::for($post)->count()
$post->reactionSummary();    // = Likes::for($post)->summary()
```

## An immutable builder

actor() and as() return a new PendingLike each time, so a partially built chain is safe to keep and reuse:

```php
$asLove = Likes::as('love');            // an immutable PendingLike — safe to keep

$asLove->like($post);
$asLove->actor($user)->toggle($photo);  // a new builder; $asLove is unchanged
Likes::actor($user)->has($post);        // checks the default reaction
```

## Resolving the actor

With no explicit actor, the facade asks actor\_resolver: null uses auth()->user(); a callable, or an invokable class-string resolved from the container, must return a model or null; a value that doesn’t resolve to a callable throws InvalidConfigurationException. Configure it for non-web guards or non-user actors:

```php
// config/likes.php
'actor_resolver' => fn () => auth('api')->user(),
// or an invokable class-string:
'actor_resolver' => \App\Likes\CurrentActorResolver::class,
```

```php
namespace App\Likes;

use Illuminate\Database\Eloquent\Model;

final class CurrentActorResolver
{
    public function __invoke(): ?Model
    {
        return auth('api')->user();
    }
}
```

Laravel can’t cache config that contains closures, so prefer the invokable class when you run php artisan config:cache.

## When no actor resolves

```php
Likes::like($post);   // a guest request with no resolvable actor

// RoundlyConsulting\Likes\Exceptions\NoAuthenticatedActorException:
// No actor could be resolved. Authenticate a user or pass an actor
// explicitly via Likes::actor($model).
```

Reads that must render for guests — withLikedState(), reactionSummary(), toLikeArray(), LikeResource and @liked — resolve the actor the same way but fall back to an empty viewer state instead of throwing.

## Global alias

facade\_alias registers a short global alias — Likes by default — so the facade works without an import. Set it to null or false (LIKES\_FACADE\_ALIAS=false, also 0/off/no) to skip the alias; a blank value is not set, so Likes is still registered:

```php
\Likes::toggle($post);   // the global alias from facade_alias — no import needed
```

## 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](https://roundly-consulting.com/support-us.md)

By donating, you agree to our [donation terms](https://roundly-consulting.com/donation-terms.md).

[Support our open source work (opens in a new tab)](https://donate.stripe.com/dRmeVe8FX5PF1Qd9pXcEw00) [Join us on Patreon (opens in a new tab)](https://www.patreon.com/cw/roundly)

## 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.

[Get a quote in 48 hours](https://roundly-consulting.com/contact.md) [Browse all packages](https://roundly-consulting.com/open-source/docs/likes-for-laravel.md)
