@foreach loops more times than the query answers

Published 3 months ago by kejpa

Hi, just getting started and the first view is making me have second thoughts about Laravel... I have a query which returns three rows (I echoed the sql and run it my self) but when I do a @foreach on the result it loops far too many times (22!) And I can't use the loop variable for showing the result, when I try I get an "Undefined property" error no matter what I write :(

Help, please! /Kjell

Best Answer (As Selected By kejpa)
Cronix

I don't even see how your code works at all. You never actually execute the query to get $books in your controller. You do for $info (which is one book). You're also missing quotes in places

Does this work?

$info= Book::findOrFail($id);

if ($info->isbn=="") {
    $books = DB::table('books')
            ->select('id', 'inventorynumber')
            ->where('title','=',$info->title)
            ->get();
} else {
    $books = DB::table('books')
            ->select('id', 'inventorynumber')
            ->where('isbn','=',$info->isbn)
            ->get();
}

return view('books.show1')->with(['book'=> $info, 'books'=>$books]);
bobbybouwmann

Show your controller and view code please! We can help you with more information ;)

If you loop over a single object it will return an array of all properties and you will have more fields than expected probably!

36864
36864
3 months ago (61,750 XP)

You'll have to post your code so we can see what's going on.

Specifically, your view and controller.

jlrdw
jlrdw
3 months ago (245,070 XP)

Help, please!

Show code please!

kejpa

My route: Route::get('/bok/{id}', function ($id) {

$info= Book::findOrFail($id);

if ($info->isbn=="") {
    $books= DB::table('books')
            ->select('id, 'inventorynumber')
            ->where('title','=',$info->title);
} else {
    $books= DB::table('books')
            ->select('id', 'inventorynumber')
            ->where('isbn','=',$info->isbn);
}

return view('books.show1')->with(['book'=> $info, 'books'=>$books]);

})->where('id' , '\d+');

My view (simplified) @section ('content')

  • {{ $book->title }}
  • {{ $book->author }}
  • {{ $book->isbn }}
@foreach($books as $ex)
  • {{ $ex->id}}
  • {{ $ex->inventorynumber}}
@endforeach @stop

Changing $ex to $book will make the view work and returns 22 rows, when the sql returns one. When I chose another id I will still get 22 loops even though that sql returns 3 rows

Cronix
Cronix
3 months ago (730,880 XP)

I don't even see how your code works at all. You never actually execute the query to get $books in your controller. You do for $info (which is one book). You're also missing quotes in places

Does this work?

$info= Book::findOrFail($id);

if ($info->isbn=="") {
    $books = DB::table('books')
            ->select('id', 'inventorynumber')
            ->where('title','=',$info->title)
            ->get();
} else {
    $books = DB::table('books')
            ->select('id', 'inventorynumber')
            ->where('isbn','=',$info->isbn)
            ->get();
}

return view('books.show1')->with(['book'=> $info, 'books'=>$books]);
Cronix
Cronix
3 months ago (730,880 XP)

Also, what version of laravel are you using? You have @stop in your template. I believe that was deprecated with version 5, and replaced with @endsection

kejpa

->get() will make things work swell!

Thanks @cronix!

I'm using 5.6 and I'll change all my @stop to @endsection.

Cheers! /Kjell

Cronix
Cronix
3 months ago (730,880 XP)

You're welcome! Please mark the post as solved.

You could also shorten it a bit

$info= Book::findOrFail($id);

$bookQuery = DB::table('books')->select('id', 'inventorynumber');

if ($info->isbn=="") {
    $bookQuery->where('title','=',$info->title);
} else {
    $bookQuery->where('isbn','=',$info->isbn);
}

$books = $bookQuery->get();

return view('books.show1')->with(['book'=> $info, 'books'=>$books]);
kejpa

Great! DIdn't realize that you could do like that. I'll remove the redundant code!

Thanks again! /Kjell

Cronix
Cronix
3 months ago (730,880 XP)

You can build on the query builder instance up until you execute it. I just put the common parts of the query first, and added the where clause to it separately, and then executed the query with ->get() after everything was put together.

Please sign in or create an account to participate in this conversation.