---
title: "DI and actions — Reviews for Laravel | Roundly"
description: "Inject ReviewsManager instead of the facade, or run the action behind each verb — CreateReview, ApproveReview, VoteOnReview and more."
url: https://roundly-consulting.com/open-source/docs/reviews-for-laravel/without-facade
language: en
---

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

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

# DI and actions

The facade is the recommended default, not the only way in. Three equivalent entry points run the same code:

- The Reviews facade — the shortest form, used throughout these docs.
- The manager — RoundlyConsulting\\Reviews\\ReviewsManager, the Macroable container singleton and the facade root. Inject it for the same API with an explicit dependency and no static calls.
- Actions — each flat verb resolves one small action class from the container. Call execute() on it to compose reviews into your own actions, jobs and commands.

## Injecting the manager

```php
use RoundlyConsulting\Reviews\ReviewsManager;

final class ProductReviewController
{
    public function __construct(private ReviewsManager $reviews) {}

    public function store(Product $product, Request $request): Review
    {
        return $this->reviews->for($product)->by($request->user())->rating(5)->create();
    }
}
```

Reviews::fake() swaps the injected instance too — ReviewsFake extends ReviewsManager, so a class that type-hints the manager receives the recording fake in tests.

## Calling an action

```php
use RoundlyConsulting\Reviews\Actions\CreateReview;
use RoundlyConsulting\Reviews\Actions\MarkReviewVerified;
use RoundlyConsulting\Reviews\DataTransferObjects\CreateReviewData;

$review = app(CreateReview::class)->execute(new CreateReviewData(
    author: $user,
    reviewable: $restaurant,
    content: 'Great place',
    title: 'Loved it',
    rating: 5,
    meta: collect(['visit' => 'dinner']),
));

app(MarkReviewVerified::class)->execute($review, verified: true);
```

## Facade method → action

| Facade method | Action | Signature | Fires |
| --- | --- | --- | --- |
| `Reviews::create($data) — and for()->by()->create()` | `CreateReview` | `execute(CreateReviewData $data): Review` | `ReviewCreated` |
| `Reviews::approve($review)` | `ApproveReview` | `execute(Review $review): Review` | `ReviewApproved` |
| `Reviews::reject($review, $reason)` | `RejectReview` | `execute(Review $review, ?string $reason = null): Review` | `ReviewRejected` |
| `Reviews::update($review, $data)` | `UpdateReview` | `execute(Review $review, UpdateReviewData $data): Review` | `ReviewUpdated` |
| `Reviews::delete($review)` | `DeleteReview` | `execute(Review $review): void` | `ReviewDeleted` |
| `Reviews::respond($review, $author, $content, $title)` | `RespondToReview` | `execute(Review $parent, Model $author, string $content, ?string $title = null): Review` | `ReviewResponded` |
| `Reviews::vote($review, $voter, $helpful)` | `VoteOnReview` | `execute(Review $review, Model $voter, bool $helpful = true): ReviewVote` | `ReviewVoted` |
| `Reviews::removeVote($review, $voter)` | `RemoveReviewVote` | `execute(Review $review, Model $voter): bool` | `ReviewVoteRemoved` |
| `Reviews::verify($review) / unverify($review)` | `MarkReviewVerified` | `execute(Review $review, bool $verified = true): Review` | `ReviewVerified` |

- CreateReviewData carries author, reviewable, content, title, rating, meta, approved, verified and photos; UpdateReviewData carries title, content, rating, meta and verified, where null means “leave unchanged”.
- ValidatesRating (the rating range guard), ValidatesReviewContent (the rating-or-content guard) and RecountReviewVotes (the denormalized vote tallies) are @internal building blocks of those actions — not for host use.
- An action you call directly skips the manager, so Reviews::fake() does not record it.

## 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/reviews-for-laravel.md)
