nurikabe/star-rating-bundle
A Symfony bundle for adding reusable star-rating fields to forms and views, making it easy to collect and display user Ratings with lightweight, configurable integration and Twig-friendly rendering.
This is a Symfony 2-era bundle (last tagged release April 2015). Laravel does not use Symfony bundles, so you will not composer require this into a Laravel app and get anything useful — the bundle service provider registers a Symfony FormType and TwigExtension, both of which assume the Symfony Form component and Twig bundle conventions.
Treat it as a reference implementation for wiring FyneWorks' star-rating jQuery widget into a form, not as a dependency.
Minimal steps to get value out of it:
StarRatingType form type and the Twig extension. That is the entire integration surface.jquery-bar-rating-style plugin) as a static asset or via npm and load it after jQuery.First use case to target: a single integer rating (1–5) on a reviews table, rendered as clickable stars on a review form, persisted as an integer, and displayed read-only on the review list.
The smallest viable port:
{{-- resources/views/components/star-rating.blade.php --}}
@props(['name', 'value' => 0, 'max' => 5, 'readonly' => false])
<div class="star-rating"
data-max="{{ $max }}"
data-readonly="{{ $readonly ? 'true' : 'false' }}">
<input type="hidden" name="{{ $name }}" id="{{ $name }}" value="{{ old($name, $value) }}">
</div>
Then initialize the widget against #{name} — the plugin reads/writes the hidden input.
Blade component as the FormType replacement. The Symfony form type's only job is rendering a container plus a bound value. Your Blade component does the same: accepts name, value, max, and readonly, emits a hidden input and a container the JS plugin attaches to. Pass old($name, $value) so validation failures preserve state.
Livewire / reactive forms. The widget is a jQuery plugin that mutates a hidden input directly, which does not fire Livewire's model events. Bind with wire:model on the hidden input and wrap the widget container in wire:ignore so Livewire does not re-render and wipe the plugin's DOM. After any Livewire update, re-run the plugin init in a Livewire.hook('message.processed', ...) or dispatch a browser event:
<div wire:ignore>
<x-star-rating name="rating" :value="$rating" />
</div>
document.addEventListener('livewire:load', () => {
Livewire.hook('message.processed', () => { initStars(); });
});
Validation. The plugin writes to a hidden field, so validate exactly that field name in a FormRequest:
'rating' => ['required', 'integer', 'between:1,' . $max],
Never trust the client for the max — keep max in a config value and validate against it.
Read-only display. The extension supports a display mode in the original bundle. Mirror this as a separate prop (readonly) that renders static SVG/glyph stars on the index/show views instead of instantiating the plugin — cheaper and server-renderable.
Eloquent model + cast. Cast the column so views stay tidy:
protected $casts = ['rating' => 'integer'];
Reusable partial for lists. Iterate reviews and render the read-only component per row; do not instantiate the interactive plugin inside a loop unless you truly need per-row editing.
Integration tip — Vite. The 2015 bundle assumed script tags in a Twig base template. In a modern Laravel app, import the widget's JS and CSS in resources/js/app.js and resources/css/app.css, ensure jQuery is available globally before the plugin loads, and only call initStars() after DOMContentLoaded.
composer require nurikabe/star-rating-bundle expecting working code. The value is entirely in reading its form type and Twig extension and porting ~50 lines.id and the name validation reads. Keep one source of truth (name) and derive the id from it.wire:ignore is mandatory; forgetting it produces "stars reset after save" bugs that look like validation failures.getName() returning the bundle alias, Resources/views template paths, and a Twig extension registered via services.yml — all of which map to a Blade component + composer-autoloaded class in Laravel, not a service provider tagged call.name your FormRequest validates? (4) After a Livewire update, did you re-init? (5) With Vite, is the CSS actually imported, or are the stars rendering as unstyled text?max and value formatting. Preserve that configuration surface in your component (max prop, :value prop) so you can reuse the same component for 5-star and 10-point scales without duplicating markup.How can I help you explore Laravel packages today?