whilesmart / eloquent-feedback
Customer feedback, reviews and testimonials for Laravel: a triage and sentiment layer over eloquent-forms.
Requires
- php: ^8.3
- laravel/framework: ^12.0
- whilesmart/eloquent-forms: ^0.1
- whilesmart/eloquent-owner-access: ^1.0
Requires (Dev)
- fakerphp/faker: ^1.24
- laravel/pint: ^1.22
- orchestra/testbench: ^9.0|^10.0
This package is auto-updated.
Last update: 2026-07-23 23:56:12 UTC
README
Customer feedback, reviews and testimonials for Laravel. A triage and sentiment
layer built on top of whilesmart/eloquent-forms:
your app collects submissions through any feedback form it likes, and this
package turns the ones you care about into owner-scoped feedback with a
lifecycle you can act on.
How it fits together
- Forms collect, feedback interprets. You define feedback forms with
eloquent-forms(a bug report, an NPS prompt, a "leave a testimonial" box). A submission is raw input; a feedback record is a triageable item with a type, a status, a rating and a sentiment. - A form key maps to a feedback type.
config('feedback.forms')maps each form key to the kind of feedback its submissions become. When a mapped form is submitted, a listener creates aFeedbackrecord owned by the form's owner. Unmapped submissions are ignored (a plain contact form stays a submission, not feedback). - Ownership is polymorphic. Feedback belongs to an
ownermorph (a workspace, a product, a page) exactly like the rest of the WhileSmart packages. Access is enforced throughwhilesmart/eloquent-owner-access.
Install
composer require whilesmart/eloquent-feedback
Publish the config to set up your form map:
php artisan vendor:publish --tag=feedback-config
// config/feedback.php 'forms' => [ 'bug-report' => 'bug', 'nps' => 'nps', 'testimonials' => 'testimonial', ],
Endpoints
Owner-scoped (behind route_middleware):
GET /api/feedback— triage list, filter bytype,status,sentiment,is_public,qGET /api/feedback/summary— totals, average rating, NPS, breakdownsGET /api/feedback/{feedback}PATCH /api/feedback/{feedback}— move status, set sentiment/rating, publishDELETE /api/feedback/{feedback}
Public (behind public_middleware):
GET /api/testimonials?owner_type=&owner_id=— feedback the owner marked public
Sentiment
Sentiment is a seam. Out of the box nothing is inferred (NullSentimentAnalyzer).
Bind your own to classify feedback text as it arrives:
$this->app->bind( \Whilesmart\Feedback\Contracts\SentimentAnalyzer::class, \App\Feedback\LlmSentimentAnalyzer::class, );
Events
FeedbackReceived— a submission became feedback. Bridge to notifications, CRM, Slack.FeedbackStatusChanged— the lifecycle moved. Carries the previous and new status.
Owning feedback
Add the trait to any model that should own feedback:
use Whilesmart\Feedback\Traits\HasFeedback; class Workspace extends Model { use HasFeedback; // $workspace->feedback }