rich remer
rich remer

Reputation: 3577

Laravel/Eloquent save validation with parent/child relationships

I have a parent model which must never exist without at least one associated hasMany relation. I am attempting to write validation for the model to ensure this never happens.

public static function boot()
{
    parent::boot();
        // reject model with no children
        if (count($workflow->children) === 0) {
            throw new RuntimeException("need at least one child");
        }
    });
}

But now I have a chicken and egg problem. I can't write the child record without the parent id. And I can't write the parent record until the save validation passes. But when I try to associate the children and call ->push() on the parent model, I get various issues depending on how I try to associate the two.

The following causes a FK constraint failure on the child column which references the parent:

$parent->children->add($child);
$child->parent()->associate($parent);
$parent->push();

Is Laravel just too stupid to handle this (seemingly reasonable) use case?

Upvotes: 2

Views: 3369

Answers (1)

Tim Lewis
Tim Lewis

Reputation: 29268

Use Laravel's DB::beginTransaction(), DB::commit() and DB::rollback() functions to prevent any stray information getting saved to the database. Take the following rough example:

public function save(){
  DB::beginTransaction();
  try {
    $parent = new Parent();
    $parent->save();
    $child = new Child();
    $parent->children()->save($child);
    DB::commit();
  } catch(Exception $e()) {
    Log::error($e->getMessage());
    DB::rollback();
  }
}

Basically, using a try { ... } catch() { ... } block with DB::beginTransaction(), DB::commit() and DB::rollback(), you can try saving something to the database, and if no exceptions are caught, DB::commit() the changes. If something goes horribly, terribly wrong, and exception will be caught, the error message will be logged and the changes will be discarded using DB::rollback().

Hope that helps!

Upvotes: 3

Related Questions