Laravel Error while creating a pivot model

293 Views Asked by At

I have the following models and relationships:

class Fence extends Model {
    public function fenceLines(){
        return $this->hasMany('App\Models\FenceLine');
    }

    public function newPivot(Model $parent, array $attributes, $table, $exists){
        if ($parent instanceof FenceLine) {
            return new FenceLine($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

class FencePoint extends Model {
    public function fenceLines(){
        return $this->hasMany('App\Models\FenceLine');
    }

    public function newPivot(Model $parent, array $attributes, $table, $exists){
        if ($parent instanceof FenceLine) {
            return new FenceLine($parent, $attributes, $table, $exists);
        }
        return parent::newPivot($parent, $attributes, $table, $exists);
    }
}

class FenceLine extends Pivot {
    protected $table = 'fences_fence_points';
    public function fence(){
        return $this->belongsTo('App\Models\Fence');
    }

    public function fencePoint(){
        return $this->belongsTo('App\Models\FencePoint');
    }
}

when I call $fence->fenceLines() I get the following error:

Argument 1 passed to App\Models\Fence::newPivot() must be an 
instance of Illuminate\Database\Eloquent\Model, none given

I have read many blogs about this exact issue and I couldn't find any with the solution.

2

There are 2 best solutions below

0
On BEST ANSWER

I FINALLY found it.

There were 2 issues.

  1. You should not create the relationship to the Pivot Model directly in your models, but rather define the relationship to the opposing model that goes through the Pivot Model.

Such as:

class Fence extends Model {
    public function fencePoints(){
        return $this->hasMany('App\Models\FencePoint');
    }
    ...
}
  1. In the newPivot function that I defined on the Models was wrong. Instead of using the Pivot Model in the instanceof call, you should use the opposing model.

such as in Fence Model:

 public function newPivot(Model $parent, array $attributes, $table, $exists){
     if ($parent instanceof FencePoint) {
         return new FenceLine($parent, $attributes, $table, $exists);
     }

In FencePoint Model:

public function newPivot(Model $parent, array $attributes, $table, $exists){
    if ($parent instanceof Fence) {
        return new FenceLine($parent, $attributes, $table, $exists);
    }

You can then use the pivot model such as:

$fence = Fence::find(1);
$fencePoint = $fence->fencePoints->first();
$fenceLine = $fencePoint->pivot;
1
On

If I'm not mistaken, it looks like a simple syntax error; you are using normal slashes when they should be backslashes. The hasMany($related, $foreignKey = null, $localKey = null) expects you to supply a namespaced path to your related model, not the directory (so that $instance = new $related can be executed properly).

Hence, when you try to instantiate a new hasMany object, you fail since new App/Models/FenceLine will return null or false (not exactly certain what the value is when you attempt to instantiate something non-existent).