Weave Code
Weaver
Helps Laravel developers discover, compare, and choose open-source packages. See popularity, security, maintainers, and scores at a glance to make better decisions.
Feedback
Share your thoughts, report bugs, or suggest improvements.
Subject
Message

Fireworks Laravel Package

hashemi/fireworks

Fireworks is a lightweight Laravel package for adding customizable fireworks animations to your web apps. Easily trigger celebratory canvas effects on page loads, user actions, or special events with a simple API. Minimal setup and easy to drop into any Blade view.

View on GitHub
Deep Wiki
Context7

Getting Started

Fireworks is a single trait that gives an Eloquent model a declarative map of "when attribute X changes, run Y." It is not a service-provider package — there is nothing to publish, no config file, no migrations. You install it, use the trait, and declare a property map.

composer require hashemirafsan/fireworks

The package name on Packagist is hashemirafsan/fireworks even though the repo is hashemirafsan/fireworks; if composer require hashemi/fireworks fails, check the repo's composer.json for the canonical name before assuming the package is broken.

Read the source before you write a line of app code. The whole package is a trait of roughly 30–60 lines in vendor/hashemirafsan/fireworks/src/. Because it is that small, the trait's source is the documentation — you need to know the exact array key names ($fireworks? $events? nested by event or by attribute?) and the exact dispatch mechanism (does it call a method name, fire a Laravel event, or resolve a class?). Five minutes in vendor/ saves an hour of guessing.

Attach it to a model:

namespace App\Models;

use Hashemi\Fireworks\Traits\HasFireworks; // confirm namespace in vendor/
use Illuminate\Database\Eloquent\Model;

class Post extends Model
{
    use HasFireworks;

    protected $fireworks = [
        'title' => ['updated'],   // shape defined by the trait — verify
        'status' => ['saved'],
    ];
}

First use case: a slug. When title changes on an existing post, regenerate slug — but only on update, and only when the title actually differed. That one scenario exercises every part of the package you care about: event selection, dirty-attribute detection, and avoiding re-entrancy. Build that before wiring it to anything with side effects.

Run the model's boot to confirm the trait hooked up at all:

php artisan tinker
>>> $p = Post::first(); $p->title = 'changed'; $p->save();

If nothing fires, the trait's boot{TraitName}() method isn't being called, which almost always means a namespace/use typo or a second trait already defining the same boot method.

Implementation Patterns

Change-gated hooks on updated. The dominant pattern: pair the trait with a dirty check so the handler runs only when the specific attribute moved. Laravel's wasChanged('title') inside an updated hook is the reliable check — isDirty() is already reset to false by the time updated fires, so isDirty() will always be false there. This is the single most common bug when people move code into this package from a plain saving observer.

Prefer saving/updating for mutation, saved/updated for side effects. If your hook needs to modify the model (slug, normalized value), it must run before the write completes. If it sends mail, dispatches a job, or writes an audit row, it must run after. Fireworks is just a thin façade over model events, so the same rules apply.

Push handlers out of the model. A trait-based hook map ages badly when handlers grow. Keep the map declarative and have each entry delegate to a dedicated class or an event, so the model stays readable and the handler is unit-testable without touching the database:

protected $fireworks = [
    'status' => ['updated' => PostStatusTransition::class],
];

Compose with observers, don't replace them. For per-model, per-attribute behaviour Fireworks reads better than an observer with a big switch. For cross-model behaviour or anything registered globally, keep using observers. Mixing both is fine as long as you know event registration order — traits boot before observers registered in a service provider, so a trait hook that mutates an attribute will be visible to an observer's dirty checks.

Queue anything slow. A hook fires synchronously inside save(), inside whatever transaction the caller opened. Wrap mail, HTTP, and third-party calls in ShouldQueue jobs and use ->afterCommit() so a rollback doesn't leave you with a sent notification for a row that never existed.

Test against the map, not the trait. Use Event::fake() or a mock handler class to assert the hook was invoked, and separate tests for the handler's behaviour. Testing the trait itself is testing the vendor's 40 lines — don't.

Gotchas and Tips

Maintenance risk is the headline. Last release April 2022, 16 stars, zero dependents. That is Laravel 9-era. The trait likely still works on 10/11/12 because model events haven't changed, but "likely" is not "tested." Pin the version in composer.json, put one integration test on it, and accept that if Laravel 13 changes boot trait semantics you will be maintaining your own fork. Realistically: read it, and if it does not fit, copy the 40 lines into app/Support/ and delete the dependency — you lose nothing but a composer entry.

Mass updates bypass everything. Post::where(...)->update(['status' => 'x']) never instantiates a model, so no events, no fireworks. Same for insert, upsert, increment, and raw statements. If a code path must trigger hooks, it must go through save().

Quiet saves and event suppression. saveQuietly(), withoutEvents(), and Model::withoutEvents(fn () => ...) all silence the trait. This is usually what you want in seeders and imports; when a hook mysteriously doesn't fire in a test suite, look for a global withoutEvents in the base test case first.

Re-entrancy loops. A saved hook that calls $this->save() (directly or via a related model) recurses until the stack dies. Guard with a flag or, better, restrict the mutation to saving/updating so it happens exactly once as part of the original write.

No-op saves don't fire. Assigning the same value leaves the attribute clean; Laravel's updated event still fires if anything else was dirty, but wasChanged('title') will be false. Never infer "the user submitted this form" from a hook firing — only from wasChanged().

Beware preventSilentlyDiscardingAttributes. In stricter Laravel configs, a hook that sets a non-fillable attribute through mass assignment will throw inside save(), and the exception surfaces from whatever controller triggered the save, not from the hook. If you see confusing MassAssignmentExceptions from an unrelated endpoint, that's the trait's handler writing to the model.

Trait conflicts. If the model already uses a trait defining the same boot method or the same handler method name, PHP will fatal. Resolve with insteadof/as in the use block, or rename your handlers with a prefix. Given the package's naming, collisions are plausible on models that already have status/lifecycle traits.

Transactions and afterCommit. Hooks fire inside the caller's transaction. If the outer transaction rolls back, anything your hook already wrote or dispatched is orphaned. This is the reason to route all side effects through queued jobs with afterCommit(), and the reason to keep hook handlers to a single line of delegation.

Extension points. The trait's boot method calls itself via Laravel's boot{TraitName} convention, so you can subclass the model and re-declare the map, but you cannot easily add attributes at runtime — the map is read at boot. If you need conditional hooks (per-tenant, per-environment), branch inside the handler rather than trying to vary the map.

Weaver

How can I help you explore Laravel packages today?

Conversation history is not saved when not logged in.
Prompt
Add packages to context
No packages found.
shitoudev/permissionmanager
johannesclimacus/laravel-tui
hocvt/seotools
vitalybaev/sypexgeo
amphibee/themosis-ignition
gito-me/fast-excel
frankyso/laravel-ipaymu
geolize-studio/laravel-chile
boomerangui/chat
jinas/dhivatar
store-doc/laravel-storage-driver
plus-it/laravel-translation-manager
diephp/perhaps
diephp/telegraph
osmaviation/spreadsheet
microsoft/fluentui-system-icons
mmccook/php-json-canonicalization-scheme
middlewares/firewall
qubiqx/montapacking
nyoncode/laravel-package-console