Post-visit reviews
Appointments are reviewable through reviews-for-laravel. review() returns a review builder, and the review it creates is stamped verified when the author really attended:
$review = $appointment->review($attendee)
->rating(5)
->title('Quick and thorough')
->content('Clear explanation and no waiting.')
->create();
$review->verified; // true: a participant of a completed appointment
$appointment->averageRating(); // ?float
$appointment->ratingSummary(); // RatingSummary DTO: average, count, distribution, …
$appointment->approvedReviewsCount(); // int- By default a review is verified when its author is a participant of a completed appointment. Anyone else gets an unverified review.
- With reviews.require_verified_attendance on, review() throws CannotReviewAppointmentException for an unverified author instead.
- averageRating(), ratingSummary() and approvedReviewsCount() count approved reviews only. Under reviews-for-laravel’s default moderation a new review waits for approval — set reviews.auto_approve to count reviews immediately.
Author models
Models that write reviews use the reviews CanReview trait:
use Illuminate\Foundation\Auth\User as Authenticatable;
use RoundlyConsulting\Appointments\Concerns\HasAppointments;
use RoundlyConsulting\Reviews\Concerns\CanReview;
class User extends Authenticatable
{
use CanReview;
use HasAppointments;
}Custom attendance resolver
Verification is decided by a VerifiedAttendanceResolver bound from config. Implement the one-method interface to apply your own rule:
namespace App\Reviews;
use Illuminate\Database\Eloquent\Model;
use RoundlyConsulting\Appointments\Enums\ParticipantRole;
use RoundlyConsulting\Appointments\Enums\Status;
use RoundlyConsulting\Appointments\Models\Appointment;
use RoundlyConsulting\Appointments\Reviews\VerifiedAttendanceResolver;
// Only attendees — not organisers — count as verified reviewers.
final class AttendeesOnlyResolver implements VerifiedAttendanceResolver
{
public function verified(Model $author, Model $appointment): bool
{
return $appointment instanceof Appointment
&& $appointment->status === Status::Completed
&& $appointment->participants()
->whereMorphedTo('participant', $author)
->where('role', ParticipantRole::Attendee->value)
->exists();
}
}// config/appointments.php
'reviews' => [
'verified_attendance_resolver' => App\Reviews\AttendeesOnlyResolver::class,
'require_verified_attendance' => true, // review() throws for unverified authors
],To turn verification off, set reviews.verified_attendance_resolver to NullVerifiedAttendanceResolver::class — every review stays unverified. Leaving the key out or blank keeps the verifying default, DatabaseVerifiedAttendanceResolver.
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 cryptoBy 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.