skip to Main Content

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 ModelAuthors:

public function books () {
    return $this->hasMany('AppModelsBooks');  
}

In ModelBooks:

public function author() {
    return $this->belongsTo('AppModelsAuthors'); 
}

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.

4

Answers


  1. Chosen as BEST ANSWER

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

    In model:

    public function author() { return $this->belongsTo('AppModelsAuthors', '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 )))))


  2. 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); 
         
    }
    
    Login or Signup to reply.
  3. 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);
    }
    
    Login or Signup to reply.
  4. 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
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search