How do I send DB results to a view that requires a nested loop through different DB Tables?

john-hubler

Feb 4th, 2017 10:44 PM

I am VERY new to Laravel, so please bear with me if this is a stupid question.

Here is ultimately what I am trying to do.

I have two database tables: Categories and FoodItems. Let's say for simplicities sake, that I have two categories in the Categories table (Appetizers, and Sandwiches), and I have 3 items in the FoodItems table:

  • Onion Rings, which has a foreign key pointing to the Appetizers table
  • Mozzarella Sticks, which has a foreign key pointing to the Appetizers table
  • Hamburger, which has a foreign key pointing to the Sandwiches table

I have a view, where I want to first display all of the categories, and then show all of the items in that category.

So my view would display:

Appetizers:
Onion Rings
Mozzarella Sticks

Sandwiches:
Hamburger

I can't figure out how I could loop through these two tables, and do a nested DB call, and then send this structure into my view, without doing any of the logic actually inside the view.

Could anybody please tell me what the best practice here would be, to get the data, as I have it ordered, into my view?

devdojo

Feb 4th, 2017 11:42 PM

Hi John-hubler,

This should be solved by setting up the appropriate relationships, so if you have your food model setup like this:

namespace App;

use Illuminate\Database\Eloquent\Model;

class FoodItems extends Model
{
    //
		public function categories(){
		    $this->belongsToMany('App\Category');
		}
}

Then inside of your controller you could do something like this:

namespace App;

use Illuminate\Database\Eloquent\Model;
use App\Category;
use App\FoodItem;

class FoodController extends Model
{
    public function index(){
		    $food_items = FoodItem::orderBy('category_id')->get();
				return view('display_food', compact('food_items');
		}
}

Finally inside of your view named display_food.blade.php you could have the following HTML:

<div id="food">
    <?php $current_category = ''; ?>
	  @foreach($food_items as $food)
	      @if($food->category()->name != $current_category)
			<h4>{{ $food->category()->name }}:</h4>
			<?php $current_category = $food->category()->name; ?>
		@endif
		
		<p>{{ $food->name }}</p>
	  
	  @endforeach
</div>

So, in your view you will list out each food item and if the category has changed you will display the new category before listing out the food items.

Hope this helps. I haven't tested all the code but this should be enough to point you in the right direction :)

Thanks! TTYS

john-hubler

Feb 5th, 2017 07:58 PM

Thank you for responding.

I am unfortunately, still struggling here.

To be as thorough as possible, here is everything that I have:

First, I have two database tables set up. The first is called "foodItems" and the second is called "foodCategories".

The foodItems table has the following columns: id, uniqueID, categoryID, clientID, itemName, itemDescription, itemAlias, thumbURL, itemSize, itemCost, itemPrice, isTaxable, hasSizes, hasDescriptors, status, created_at, updated_at

The foodCategories table has the following columns: id, uniqueID, clientID, categoryName, categoryAlias, status, created_at, updated_at

Next, I have two models, FoodItem, and FoodCategory.

The code I have in my FoodItem model looks like so: <?php

    namespace App;

    use Illuminate\Database\Eloquent\Model;

     class FoodItem extends Model {
            protected $table = 'foodItems';

          public function foodCategory(){
                 return $this->belongsTo('App\FoodCategory');
            }
     }

The code in my FoodCategory model looks like so:

<?php
    namespace App;

    use Illuminate\Database\Eloquent\Model;

    class FoodCategory extends Model {
        protected $table = 'foodCategories';

        public function foodItem() {
	            return $this->hasMany('App\FoodItem');
        }
    }

The code in my controller looks like this:

<?php
    namespace App\Http\Controllers;

    use Illuminate\Support\Facades\Auth;
    use Illuminate\Support\Facades\DB;
    use Illuminate\Http\Request;
    use App\FoodCategory;
    use App\FoodItem;

    class DashboardController extends Controller {

        public function __construct(){
            $this->middleware('auth');
        }

        public function food() {
            $food_items = FoodItem::orderBy('categoryID')->get();
            return view('food', compact('food_items'));
        }
    }

And finally, the code I have in my View (food.blade.php) is:

@foreach ($food_items as $food)
					<li>{{ $food->foodCategory->categoryName }}</li>
	@endforeach
	

In my view, I have tried using parenthesees after "foodCategory", I have tried changing the capitalization to "FoodCategory", "FoodCategory()", "foodCategories()", "foodCategories"... and about every other combination I can think of - but nothing seems to work.

As the code is right now, it produces the following error:

"Trying to get property of non-object (View: /Applications/XAMPP/xamppfiles/htdocs/Laravel/ChanceSystems2017/resources/views/food.blade.php)"

I'm really stumped at this point. Could anybody please shed some light onto what I am missing? Thank you!

mark

Feb 10th, 2017 10:54 AM

In your controller use

$food_items = FoodItem::with('foodCategory')orderBy('categoryID')->get();