0

I'm rather new to Eloquent (and ORM's as a whole really). I have done rather a lot of background reading but can't quite get my head around the relationships in Eloquent.

I have a Car model that relates to a Color model, a Make model and a Model model.

I pass my Car::getAll() through to my View as $cars. When I call dd(toArray($cars)) I get the following:

array (size=1)
  0 => 
    array (size=12)
      'id' => string '1' (length=1)
      'registration' => string '123' (length=3)
      'make' => 
        array (size=5)
          'id' => string '1' (length=1)
          'title' => string 'Ford' (length=4)
          'slug' => string 'ford' (length=4)
          'created_at' => string '2014-06-26 21:30:23' (length=19)
          'updated_at' => string '2014-06-26 21:30:23' (length=19)
      'model' => 
        array (size=5)
          'id' => string '1' (length=1)
          'title' => string 'Mustang' (length=7)
          'slug' => string 'mustang' (length=7)
          'created_at' => string '2014-06-26 21:30:41' (length=19)
          'updated_at' => string '2014-06-26 21:30:41' (length=19)
      'color' => 
        array (size=5)
          'id' => string '1' (length=1)
          'title' => string 'Red' (length=3)
          'slug' => string 'red' (length=3)
          'created_at' => string '2014-06-26 21:30:03' (length=19)
          'updated_at' => string '2014-06-26 21:30:03' (length=19)
      'year' => string '1991' (length=4)
      'is_classic' => string '1' (length=1)
      'price' => string '999.00' (length=6)
      'sold' => string '0' (length=1)
      'active' => string '1' (length=1)
      'created_at' => string '2014-06-26 22:17:27' (length=19)
      'updated_at' => string '2014-06-26 22:17:27' (length=19)`

Which appears to be right to me, however when I have:

foreach ($cars as $car) {
  echo $car->color-title;
}

I get a "Trying to get property of non-object" error.

My Models are as follows:

Car.php

class Car extends \Eloquent {
    protected $fillable = ['color_id'];


    public function color() {
        return $this->belongsTo('Color', 'id');
    }

    public function model() {
        return $this->belongsTo('Model', 'id');
    }

    public function make() {
        return $this->belongsTo('Make', 'id');
    }

    public static function getAll() {
        return Car::with('color', 'make', 'model')->where('active', 1)->get();
    }
}

Color.php

class Color extends \Eloquent {
    protected $fillable = ['title', 'slug'];

    public function cars() {
        return $this->hasMany('Car', 'color');
    }
}

Make.php

class Make extends \Eloquent {
    protected $fillable = [];

    public function cars() {
        return $this->hasMany('Car', 'make');
    }
}

Model.php

class Model extends \Eloquent {
    protected $fillable = [];

    public function cars() {
        return $this->hasMany('Car', 'model');
    }
}

Any help would be very much appreciated. Thank you

EDIT:

Sorry I should have included my schema up methods:

CreateMakesTable

public function up()
    {
        Schema::create('makes', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('title');
            $table->string('slug');
            $table->timestamps();
        });
    }

CreateModelsTable

public function up()
    {
        Schema::create('models', function(Blueprint $table)
        {
            $table->increments('id');
            $table->integer('make')->unsigned();
            $table->string('title');
            $table->string('slug');
            $table->timestamps();
        });

        Schema::table('models', function(Blueprint $table)
        {
            $table->foreign('make')->references('id')->on('makes')->onDelete('cascade');
        });
    }

CreateColorsTable

public function up()
    {
        Schema::create('colors', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('title');
            $table->string('slug');
            $table->timestamps();
        });
    }

CreateCarsTable

public function up()
    {
        Schema::create('cars', function(Blueprint $table)
        {
            $table->increments('id');
            $table->string('registration');
            $table->integer('make')->unsigned();
            $table->integer('model')->unsigned();
            $table->integer('year');
            $table->integer('color')->unsigned();
            $table->boolean('is_classic');
            $table->float('price');
            $table->boolean('sold');
            $table->boolean('active');
            $table->timestamps();
         });

         Schema::table('cars', function(Blueprint $table)
         {
            $table->foreign('make')->references('id')->on('makes')->onDelete('cascade');
            $table->foreign('model')->references('id')->on('models')->onDelete('cascade');
            $table->foreign('color')->references('id')->on('colors')->onDelete('cascade');
         });
    }
Liam Hall
  • 217
  • 3
  • 9
  • Where are foreign keys? Those relation definitions are wrong, that's for sure. – Jarek Tkaczyk Jun 27 '14 at 08:54
  • You should never assume a relationship exists inside a loop. You probably have a car without a related color model being returned. Check first, then do whatever you need to do. – Jason Lewis Jun 27 '14 at 11:43
  • @deczo I have added my Schema up methods to show where foreign keys are. – Liam Hall Jun 27 '14 at 17:50
  • @JasonLewis Sorry, could you point me in the direction of how to check this? I presumed by being able to return it as an array like this it showed I had the object as expected - although clearly it doesn't :/ – Liam Hall Jun 27 '14 at 17:51

1 Answers1

0

Like Jason pointed out the error is caused by null returned from one of those relationships. But the problem with your setup is, that the relationship definitions are wrong.

So first make them right:

// it goes like this:
// belongsTo('Model', 'foreign_key_on_this_model', 'primary_key_on_related')

public function color() {
    return $this->belongsTo('Color', 'color'); // primary key is id so no need to specify
}

hasMany relations on the other models are OK.

Then in that loop:

foreach ($cars as $car)
{
   if (count($car->color))
   {
       // do something with color
   }
}

For the reason I'm using count read this: Laravel check if related model exists

You can also return only cars that have related color, make and whatever you need like below:

$cars = Car::has('color')->has('make')...
Community
  • 1
  • 1
Jarek Tkaczyk
  • 78,987
  • 25
  • 159
  • 157