Search code examples
phplaravellaravel-5eloquenthierarchy

laravel eloquent relationship hierarchy


I seem to be having a problem understanding this hierarchical relationship.

Farm > Fields > Shepherds > Sheep

It seems a pretty straightforward hierarchy - Farm hasMany fields, field hasMany shepherds, shepherd hasMany sheep.

Sheep belong to a shepherd, shepherds belongs to fields, fields belong to farms.

I have defined this model relationships thus:

class Sheep extends Model {

    protected $fillable ['name'];

    public function shepherd() {
            return $this->belongsTo('App\Shepherd');
        }    
}


class Shepherd extends Model {

    protected $fillable ['name'];

    public function field() {
            return $this->belongsTo('App\Field');
        }    
    public function sheep() {
            return $this->hasMany('App\Sheep');
    }               
}

class Field extends Model {

    protected $fillable ['name'];

    public function farm() {
            return $this->belongsTo('App\Farm');
        }    

    public function shepherd() {
            return $this->hasMany('App\Shepperd');
    }   
}

class Farm extends Model {

    protected $fillable ['name'];

    public function field() {
            return $this->hasMany('App\Field');
        }    
}

public function up()
{
    Schema::create('farms', function (Blueprint $table) {
        $table->increments('id');
        $table->string('name');
    });
}

public function up()
{
    Schema::create('fields', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('farm_id');
        $table->string('name');
    });
}
public function up()
    Schema::create('shepherds', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('field_id');
        $table->string('name');
    });
}
public function up()
    Schema::create('sheep', function (Blueprint $table) {
        $table->increments('id');
        $table->integer('shepherd_id');
        $table->string('name');
    });
}

I would expect to be able to save each model in the following manner.

$farm = new App\Farm;

$farm->name = 'West Farm';

$field = new App\Field;

$field->name = 'The orchard';

$shepherd = new App\Shepherd;

$shepherd->name = 'Jason';

$sheep = new App\Sheep;

$sheep->name = 'Sean';

$farm->save();

$farm->field()->save($farm);

$farm->field->shepherd()->save($shepherd);

$farm->field->shepherd->sheep()->save($sheep);

But it does not work. Once I get to $farm->field->shepherd()->save($shepherd); the process breaks down. I would appreciate some assistance in the correct manner of saving using the relationships between all the tables.

I'm pulling my hair out trying to understand this, so any help would be greatly appreciated.

thanks


Solution

  • Your code breaks here:

    $farm->field->shepherd()->save($shepherd);
    

    Farms have many fields, so when you reference $farm->field, you're getting a collection of Field object, not just a single Field object.

    To make it work, you need to either reference $farm->field[0]

    $farm->field[0]->shepherd()->save($shepherd);
    

    or just use the $field object you created before:

    $field->shepherd()->save($shepherd);
    

    I'd also suggest to use plural names for your hasMany relations (fields, sheeps, etc.) - this way you'll always remember that the referenced fields refer to a collection, not a single object