Shaden's avatar
Level 4

Nova Action Does Not commit any changes

I have an issue with Nova Actions. When there is large loop of models, If one of them fails, the whole loop is not committed to database. This causes a problem because I sending external API requests that I need to commit each response to DB. I not sure how I can achieve this. need to commit any changes within the foreach loop regardless of the final outcome. any Ideas.

0 likes
2 replies
LaryAI's avatar
Level 58

To address the issue you're facing with Nova Actions where changes within a loop are not committed if one model fails, you can use database transactions and handle each model's update or creation individually. This way, even if one model update fails, the others can still be committed.

Here's a step-by-step solution using Laravel's database transaction methods:

  1. Start a Transaction for Each Model: Instead of wrapping the entire loop in a single transaction, start and commit/rollback transactions individually for each model within the loop. This ensures that each model is handled separately.

  2. Handle Failures Gracefully: If an exception occurs while processing a model, you can catch it and decide how to handle it (e.g., logging the error) without affecting the other models.

Here's how you could implement this:

use Illuminate\Support\Facades\DB;
use Laravel\Nova\Actions\Action;
use Laravel\Nova\Fields\ActionFields;

class UpdateModelsAction extends Action
{
    public function handle(ActionFields $fields, \Illuminate\Support\Collection $models)
    {
        foreach ($models as $model) {
            // Start a new transaction for each model
            DB::beginTransaction();
            try {
                // Perform your updates or external API requests here
                // For example, let's assume we're updating a field on the model
                $model->some_field = 'new value';
                $model->save();

                // Commit the transaction
                DB::commit();
            } catch (\Exception $e) {
                // Rollback the transaction
                DB::rollback();

                // Log the error or handle it as needed
                return Action::danger("Failed to update model with ID {$model->id}: {$e->getMessage()}");
            }
        }

        return Action::message('All models processed successfully.');
    }
}

Explanation:

  • DB::beginTransaction(): This starts a new database transaction.
  • $model->save(): This is where you update your model. If this operation fails, an exception will be thrown.
  • DB::commit(): If the model is saved successfully, the changes are committed to the database.
  • DB::rollback(): If there is an exception, any changes made in the current transaction are rolled back.
  • Action::danger() and Action::message(): These are Nova specific methods to return responses from actions.

This approach ensures that each model is processed independently, and failures in processing one model do not affect the others.

Shaden's avatar
Level 4

Looks OK, but can I commit more than one time, say I want to update a related table and commit it, and another commit of logs table, and finally the main model table commit

Please or to participate in this conversation.