Be part of JetBrains PHPverse 2026 on June 9 – a free online event bringing PHP devs worldwide together.

kriszpchicken's avatar

Property [pivot] does not exist on this collection instance

I am working on a function in my library application, where users can rent out books. Now, the renting out works fine, and I can even display the data, but after I wanted to create a function to delete the rented out books (after they were returned) I get an error message: Property [pivot] does not exist on this collection instance. I can't even figure out what my mistake was, because it worked fine a minute ago, and the rented book gets deleted in the databank, but I can't display my page without the error message. Could you please check if you might find the problem? It first happened when I tried to create the delete function.

So basically this is a pivot table, that is made up of my books and readers table. I also added the attributes id and maxreturndate.

Controller:

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Book;
use App\Reader;
use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\DB;



class CheckedOutController extends Controller
{
    /**
     * Display a listing of the resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        $book = Book::orderBy('title')->get();
        $reader = Reader::orderBy('name')->get();
        $duedate = Carbon::now()->addDays(14);

        $readers = Reader::all();

        return view('checkedouts/index', compact('book', 'readers'));
    }

    /**
     * Show the form for creating a new resource.
     *
     * @return \Illuminate\Http\Response
     */
    public function create()
    {
        $books = Book::doesntHave("readers")->get();
        $readers = Reader::all();

        return view('checkedouts/create', compact('books', 'readers'));
    }

    /**
     * Store a newly created resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return \Illuminate\Http\Response
     */

    public function store(Request $request)
    {
        $reader = Reader::find($request->reader_id);
        $reader
            ->books()
            ->attach(
                $request->book_id,
                ["maxreturndate" => Carbon::now()->addDays(14)]
            );

        return redirect('checkedouts')->with('success', 'Buch wurde erfolgreich verliehen!');
    }

    /**
     * Display the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function show($id)
    {
        //
    }

    /**
     * Show the form for editing the specified resource.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function edit($id)
    {
        //
    }

    /**
     * Update the specified resource in storage.
     *
     * @param  \Illuminate\Http\Request  $request
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function update(Request $request, $id)
    {
        //
    }

    /**
     * Remove the specified resource from storage.
     *
     * @param  int  $id
     * @return \Illuminate\Http\Response
     */
    public function destroy($id)
    {
        $book = DB::table('book_reader')
        ->where('id', $id)
        ->take(1)
        ->delete();

        return redirect('checkedouts')->with('success', 'Das Buch wurde zurückgebracht!');
    }
}

index.blade.php:

@extends('layout')


@section('title')
<title>Alle ausgeliehen Bücher</title>
@section('content')
<style>
  .uper {
    margin-top: 40px;
  }
</style>
<div class="uper">
  @if(session()->get('success'))
  <div class="alert alert-success">
    {{ session()->get('success') }}
  </div><br />
  @endif

  <table class="table table-hover">
    <thead>
      <tr>
        <td>ID</td>
        <td>Titel</td>
        <td>Verliehen an</td>
        <td>Verliehen bis</td>
        <td>Bearbeiten</td>

      </tr>
    </thead>
    <tbody>
      @foreach($readers as $reader)
      <tr>
        @foreach($reader->books as $book)
        <td>{{$book->pivot->id}}</td>
        <td>{{$book->title}}</td>
        @endforeach
        <td>{{$reader->name}}</td>
        <td>{{$book->pivot->maxreturndate}}</td>



        <td>
          <form action="{{ route('checkedouts.destroy', $book->pivot->id)}}" method="post">
            @csrf
            @method('DELETE')
            <button class="btn btn-danger" type="submit">Löschen</button>
          </form>
        </td>
      </tr>
      @endforeach

    </tbody>
  </table>
  <div>
    @endsection

Book Model:

public function readers()
    {
        return $this
            ->belongsToMany(Reader::class, 'book_reader')
            ->using(Checkout::class)
            ->withPivot(['id', 'returndate', 'maxreturndate']);
    }
0 likes
9 replies
Nakov's avatar

Hey @mekol, the error is pretty self descriptive. It means that you are trying to use ->pivot while the variable that you are calling this onto is not a single instance but a collection.

So for example calling:

$book->pivot->something;

means that $book is a collection, instead of a single book. Check which line throws the error, and either share some code, or make sure that you call it on an instance of the model, and not on a collection.

1 like
kriszpchicken's avatar

Sorry, it is my first time posting here, I wasn't sure how to input code... But I updated my question!

Nakov's avatar

@mekol so you have these:

<td>{{$book->pivot->maxreturndate}}</td>

<td>
<form action="{{ route('checkedouts.destroy', $book->pivot->id)}}" method="post">

Which are out of your foreach books loop.

And in the controller you have this:

$book = Book::orderBy('title')->get();

so calling this $book is misleading as ->get() returns a collection of books so using $book->pivot->maxreturndate out of the loop of reader books, is going to be called on the $book which in this case is a collection.

I hope I am clear here.

kriszpchicken's avatar

Thank you for your answer! Sorry, this is my first laravel project, so I am kind of struggling... I am not really sure what I should change now?

Nakov's avatar
Nakov
Best Answer
Level 73

Well, as a first step, in order to avoid confusion I would change this :

$book = Book::orderBy('title')->get();

to be

$books = Book::orderBy('title')->get();

Then in your view the table cells should be re-ordered, or you should use it as such:

@foreach($readers as $reader)
      <tr>
      <td>{{$reader->name}}</td>
        @foreach($reader->books as $book)
        <td>{{$book->pivot->id}}</td>
        <td>{{$book->title}}</td>
        
        <td>{{$book->pivot->maxreturndate}}</td>



        <td>
          <form action="{{ route('checkedouts.destroy', $book->pivot->id)}}" method="post">
            @csrf
            @method('DELETE')
            <button class="btn btn-danger" type="submit">Löschen</button>
          </form>
        </td>
	@endforeach
      </tr>
@endforeach

notice the end of the inner foreach loop, is after you end-up using $book->pivot.

kriszpchicken's avatar

Thank you so much! It worked! However, I just realized, that the index page shows the readers name, even if I delete the book they have rented out. So it is basically the reader without any books. Do you have any idea how I could fix that?

Nakov's avatar

@mekol yup, you can use this:

$readers = Reader::has('books')->get();

This will filter to only readers that have at least one book. :)

Happy to help, you can mark the answer that helped you the most as a "Best Answer".

kriszpchicken's avatar

Thank you, you really helped me out a lot! Sorry, one more question: if I rent out a book to a reader, who already has a book, it shows up on the same row as the book that they already have rented. Do you have a solution for that? I really don't wanna bother you!

Nakov's avatar

@mekol so that's because you are listing all the reader's books. This:

@foreach($reader->books as $book)

makes multiple cells for each of the readers books. If you want to block a user to rent another book while he already has one, that should be a condition in the place where you assign a book to the user. Or even better, when he/she logs in, and sees the library of books, disable the right to rent a book if he/she already has one.

Hope this gives you an idea at least on how to proceed.

Please or to participate in this conversation.