Andrew Olinevich
Andrew Olinevich

Reputation: 61

Laravel. Property does not exist on this collection instance. Relation error

I try to create relations between different tables in my database and get data from these tables, but I got an error: Property does not exist on this collection instance.

This is my code:

Migrations files:

Schema::table('books', function (Blueprint $table) {
        $table->foreignId('author_id')->constrained('authors')->onUpdate('cascade')->onDelete('cascade');
    });

In Model\Authors:

public function books () {
    return $this->hasMany('App\Models\Books');  
}

In Model\Books:

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

In AuthorsController:

public function index () {
    
    $authors = Authors::all(); 
    return dd($authors->books); 
     
}

In BooksController:

public function index () {
    
    $books = Books::all(); 
    return  dd($books->author); 
    
}

If someone has an idea how to fix this, I will be very grateful.

Upvotes: 0

Views: 102

Answers (4)

Andrew Olinevich
Andrew Olinevich

Reputation: 61

Thank you guys! In my case, the right solution was :

In model:

public function author() { return $this->belongsTo('App\Models\Authors', 'author_id'); } 

And in controller :

$books = Books::with('author')->get();

And in view file I added:

@foreach
            <li>{{ $book->title}}</li>                    
            <li>{{ $book->author->name}}</li>
            @endforeach

Thank you again. The topic can be closed )))))

Upvotes: 0

N69S
N69S

Reputation: 17206

If you want to have all authors with their books, use eager loading with()

public function index () {
    
    $authors = Authors::with('books')->get(); 
    return dd($authors); 
     
}

If you wants all the books with their respective author

public function index () {
    
    $books = Books::with('author')->get(); 
    return  dd($books); 
    
}

When you iterate the collection (like an array) in your blade, you can then access the relation

@foreach($books as $book)
    <span>{{$book->author->name}}</span>
@endforeach

If you just want to get a dd of the books of one author you can do it like this

public function index () {
    
    $authors = Authors::all();
    // $authors is a collection of models (think of it as an advanced array)
    // To get one of the models, you can iterate them with a loop or, for example, take the first one with "->first()"
    //$authors->first() is an instance of the model "Author" class

    return dd($authors->first()->books); 
    // $authors->first()->books is now a collection of models of "Book" class
}

Upvotes: 1

pr1nc3
pr1nc3

Reputation: 8338

Your relation between Authors and books is one-to-many so an Author hasMany books (like you have correctly stated in the model relation).

The output of this is a collection so you can not access it that way, instead you need to loop it like:

public function index () {
    $authors = Authors::all(); 
    $authors->books->each(function ($book) {
      print_r($book);
    }
}

In case you want to retrieve the books of a single Author you can return a single model instance for the Author like:

public function index () {
    $author = Authors::where('id',1)->first(); 
    print_r($author->books);
}

Upvotes: 0

Nuriddin Rashidov
Nuriddin Rashidov

Reputation: 966

Your models is right but you wrong when you call $authors->books because $authors is collection of your Authors model not object of Author. If your want check your relationship you can do with this example:

public function index () {
    
    $authors = Authors::latest()->first();; 
    dd($authors->books); 
     
}

Upvotes: 1

Related Questions