- What does ganyicz/nova-callbacks actually do?
- It lets you run custom code when a Laravel Nova resource is created, updated, or deleted from the Nova admin panel. You add the HasCallbacks trait to a resource and define a callbacks() method that returns closures for the events you care about, and each closure receives the affected model instance. Internally it is a small piece of glue that hooks Nova's store, update, and destroy flow rather than registering real Eloquent observers. The point is to keep event logic co-located with the fields it relates to instead of in a separate observer class.
- How do I install ganyicz/nova-callbacks in a Laravel Nova project?
- Run composer require ganyicz/nova-callbacks, add the HasCallbacks trait to your Nova resource, and implement a callbacks() method returning your closures. No service provider registration, config file, migration, or published assets are involved. The real setup friction is that Nova is paid and closed source, so local development and CI both need NOVA_USERNAME and NOVA_PASSWORD credentials. Teams that have not automated Nova auth in CI often spend more time on secrets than on the package itself.
- Which Laravel and Nova versions does nova-callbacks support?
- The last tagged release was June 2022, so its composer.json constraints were written against the Nova major available at that time. Check the package's composer.json to see which Nova majors it permits, then confirm it resolves against your current pinned Nova version. A clean composer require only proves the constraint graph is satisfiable, not that the callbacks still fire on your Nova release. Add a small feature test per resource before trusting it in production.
- Should I use Nova callbacks instead of model observers?
- Only if Nova is the sole write path for that model. Callbacks defined in a resource fire for changes made through the Nova UI, which is ideal for admin-scoped side effects like audit rows stamped with the acting admin, admin notifications, or cache busts that only matter when a human edits a record. They are the wrong choice for anything an API endpoint, console command, queue worker, or CSV import must also trigger. If your app has multiple mutation surfaces, keep the logic in an observer, domain event, or service so every path is covered.
- Do nova-callbacks fire for Nova actions, lenses, bulk updates, or CSV imports?
- No. The package hooks the resource store, update, and destroy flow, so it only runs for changes made through those standard Nova resource operations. Bulk actions, lenses, inline-created related records, and custom import tooling generally bypass those hooks, which means rows can differ depending on how they were created. If any of those paths exist in your app, test them explicitly and keep business rules out of the callbacks.
- What arguments do the callback closures receive?
- Each closure receives the affected model instance, so you can read attributes, relationships, and the primary key directly. The underlying implementation invokes named methods such as afterCreate and afterUpdate, and those receive the model plus the NovaRequest. Argument order and exact signatures depend on the installed version, so read the source in vendor/ganyicz/nova-callbacks/src rather than relying on the README. It is a five-minute read and more reliable than the docs.
- Are Nova callback side effects wrapped in a transaction, and do I need afterCommit?
- Do not assume the save and the callback are wrapped in a single transaction on your Nova version. That detail determines whether jobs you dispatch from a callback can see the record, so verify it in the source before shipping. The safe pattern is to make every callback body idempotent and to chain ->afterCommit() on any dispatched job or notification. Retries by admins also mean callbacks can run more than once, so avoid non-idempotent side effects like incrementing counters or sending duplicate mail.
- Do the callbacks run on soft deletes and force deletes?
- The package only exposes created, updated, and deleted events, hooked into Nova's destroy flow. Whether that covers soft deletes, force deletes, or restore operations on your Nova version needs to be confirmed by reading the source and testing against your model configuration. If you rely on soft deletes, write a feature test that deletes through the Nova endpoint and asserts the callback ran. Do not assume parity with Eloquent's deleting, deleted, and forceDeleted events.
- Is ganyicz/nova-callbacks still maintained, and what are the alternatives?
- No release has shipped since June 2022, it has a single maintainer and effectively no dependents, so treat it as an unowned component in your admin write path. The capability is roughly one hundred lines of glue and only a few hours to replicate, which makes copying the pattern or forking it a reasonable plan from day one. Before adopting it, check whether your Nova version now ships first-party lifecycle hooks that make it redundant. Also check whether other installed Nova extensions wrap store and update, since trait bootstrap order can affect which code runs first.
- How do I test that Nova callbacks actually fire?
- Write a feature test that hits the Nova resource store, update, and destroy endpoints and asserts the expected side effect happened. Keep one canary test per resource that uses a callback, because silent breakage after a Nova major upgrade usually shows up as missing side effects in production rather than as a build error. Explicitly cover bulk actions and import paths if they exist, and limit yourself to one package per resource that wraps store or update to avoid method-override collisions. Testing is cheap here compared to debugging why an audit row was never written.