Laurent Kreps
Laurent Kreps

Reputation: 57

Laravel Eloquent one to many relationship not working

I'm obviously missing something. I thought I was comfortable around laravel relationships...

I've 2 tables, named ratings and ratingdetails. The models are named Rating & Ratingdetail:

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Rating extends Model
{
    public function ratingdetails()
    {
        return $this->hasMany('App\Ratingdetail');
    }
    public function campaigns()
    {
        return $this->hasMany('App\Campaign');
    }
}

and

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;
use Spatie\Translatable\HasTranslations;

class Ratingdetail extends Model
{
    use HasTranslations;
    public $translatable = ['value'];

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

When I try to access to my Rating model it works fine, but I can't access the relationships; the output is the following, despite there should be 4 Ratingdetails rows...:

{"id":1,"description":"fontawesome","created_at":null,"updated_at":null,"deleted_at":null}

Thank you all for your time !

Upvotes: 2

Views: 89

Answers (2)

boolfalse
boolfalse

Reputation: 2131

Actually I can't answer for this question without having the Models' $fillable attributes, or without DB Tables structures. But I think your tables have following columns:

"raitings" -> "id", "description", "created_at", "updated_at", "deleted_at"

"raitingdetails" -> "id", "raiting_id", "value", ...

In normal way, you need to create OneToMany relation for that 2 tables with foreign key. So in your "raitingdetails" migration you need to have something like this:

$table->unsignedBigInteger('raiting_id')->nullable();
$table->foreign('raiting_id')->references('id')->on('raitings')->onUpdate('cascade')->onDelete('cascade');

Your models are correct, but it not just cool now.. You can improve them by adding $fillable columns and FKs of relations (Note: if you're using traditional foreign key concept, like "partents.id"->"childs.partent_id", then you can leave this part too).

  1. For getting all Rating details of 1 Rating, you can do this:
$rating = Rating::find($rating_id);
$rating_details_of_one = $rating->ratingdetails()->get()->toJson();
  1. If you want to have Rating Details for all actions, you can add Accessor in your Rating model and attach that to $appends like this:
protected $appends = [ 'rating_details' ]; public function
public function getRatingDetailsAttribute() {
    return $this->ratingdetails;
}

And in logic parts you can access like this:

$ratings = Rating::find($rating_id); // this will get with their "ratingdetails" relation

Or you can attach accessor on the fly without protected $appends and getRatingDetailsAttribute() function like this:

$rating = Rating::find($rating_id);
$rating_details_of_one = $rating->setAppends([ 'rating_details' ])->get()->toJSON();
  1. If you want to have some Ratings with their details, you can use something like this:
$rating_details_of_many = Rating::where('description', 'fontawesome')->with('ratingdetails')->get()->toJson();

Upvotes: 0

Tim Lewis
Tim Lewis

Reputation: 29306

$rating = Rating::find($request->rating_id);
return $rating->toJson();

In the above line of code, you're never accessing the ratingdetails relationship. They are not included by default, and need to be loaded before being available:

$rating = Rating::with(["ratingdetails"])->find($request->rating_id);
return $rating->toJson();

Including it via with() will "Eager load" the relationship and expose it to be accessed via

console.log(rating.ratingdetails);
// Will contain an array of 4 objects

Before converting to json, you'd be able to access $rating->ratingdetails, but once converted, you lose access unless you have previously loaded the relationship.

Upvotes: 2

Related Questions