kriszpchicken's avatar

Eloquent: how to change the display of data

I am working on a library application, and I am displaying my data, which is a pivot table made from the table books and readers, and I also added a maxreturndate attribute. Now, what I want to do is display in every row the name of the person who rented the book, the title of the book and the return date. This works fine, but if a person who already rented out a book rents out another one the name of the book displays in the same row as the one before. What I would like to do is to display every rental in a different row, doesn't matter if the person already rented out a book or no.

My 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()
    {
        $books = Book::orderBy('title')->get();
        $readers = Reader::has('books')->get();
        $duedate = Carbon::now()->addDays(14);

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

index.blade.php:

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

      </tr>
    </thead>
    <tbody>
      @foreach($readers as $reader)
      <tr>
        <td>{{$reader->name}}</td>
        @foreach($reader->books as $book)
        <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">Buch zurückgebracht</button>
          </form>
        </td>
        @endforeach
      </tr>
      @endforeach
    </tbody>
  </table>
0 likes
2 replies
rodrigo.pedra's avatar

Not quite sure I understood, but try changing your table tbody to this:

<tbody>
    @foreach($readers as $reader)
        <tr>
            <td rowspan="{{ $reader->books->count() }}">{{$reader->name}}</td>
            @foreach($reader->books as $book)
                {!! $loop->first ? '' : '<tr>' !!}

                <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">Buch zurückgebracht</button>
                    </form>
                </td>

                {!! $loop->first ? '' : '</tr>' !!}
            @endforeach
        </tr>
    @endforeach
</tbody>

This will create a new row for each reader's book. On the first book we don't need to create a new row because we are already in the reader's name row. The rowspan attribute will make sure the reader's name span through all theirs books rows.

You can read more about the loop variable in the docs:

https://laravel.com/docs/7.x/blade#the-loop-variable

EDIT fixed html output

1 like
rodrigo.pedra's avatar
Level 56

Great it helped =)

But I find a bug on the markup generation, please update to this:

<tbody>
    @foreach($readers as $reader)
        <tr>
            <td rowspan="{{ $reader->books->count() }}">{{$reader->name}}</td>
            @foreach($reader->books as $book)
                {!! $loop->first ? '' : '</tr><tr>' !!}

                <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">Buch zurückgebracht</button>
                    </form>
                </td>

                {!! $loop->last ? '' : '</tr>' !!}
            @endforeach
        </tr>
    @endforeach
</tbody>

On the second books iteration it will close the previous row before opening a new one.

In every books loop it will close the current row. The last one is skipped because we close it on the outer loop.

1 like

Please or to participate in this conversation.