Issue querying laravel eloquent relationship - php

This is with reference to this question :
Laravel Eloquent One to Many relationship
I tried the suggested way, but couldn't resolve. Please help. Below is the changes i have done :
Earlier :
//Route for Restaurants Page
Route::get('/home/restaurants',function(){
$restaurants = DB::table('restaurants')->simplepaginate(3);
return view('restaurants',['restaurants_data'=>$restaurants]);
});
Changed as per suggestion :
Route::get('/home/restaurants',function(){
// $restaurants = DB::table('restaurants')->simplepaginate(3);
$restaurants = \App\Restaurant::simplePaginate(3);
return view('restaurants',['restaurants_data'=>$restaurants]);
});
In Restaurant model
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Restaurant extends Model
{
public function offer(){
return $this->hasMany('Offer');
}
}
In view, now I am trying to access it by dumping the values.
<?php
var_dump($restaurants_data->offer);
?>
Error :
After doing dd()

Firstly, I would suggest changing your Offer Relationship to:
public function offers()
{
return $this->hasMany(Offer::class, 'restaurant_ID', 'id');
}
The above assumes that the Offer class and Restaurant class are in the same namespace. If they're not please add the correct namespace or import the Offer model in to the class.
Secondly, because you're paginating the results you will end up with a collection of Restaurant models (even if there is only one), so you will need to loop through them to get access to the offers for each model. I would also suggest eager loading the results e.g.
Route:
Route::get('/home/restaurants', function () {
$restaurants = \App\Restaurant::with('offers')->simplePaginate(3);
return view('restaurants', compact('restaurants'));
});
in your view:
#foreach($restaurants as $restaurant)
#foreach($restaurant->offers as $offer)
{!! dump($offer) !!}
#endforeach
#endforeach
{{ $restaurants->links() }}

Can you replace
$restaurants = \App\Restaurant::paginate(3); and amend the blade code to say
<?php
foreach($restraunts_data as $resturant) {
if(count($restaurant->offer) {
print_r($restaurant->offer);
}
}
?>

You are using the models incorrectly. You run no queries and you attempt to run a static method on the Restaurant class without selecting any restaurants. As far as I know is this not supported by Eloquent. If you look at the error message it complains that there are no property $offer.
Try to run some query, and the select the related Offer. This should work as expected.
For example:
$offers = \App\Restaurant::find(1)->offer;
This will return the many Offer relations for the Restaurant with ID 1.

Related

How to exclude/include specific database columns when eager-loading a nested model in Laravel 8?

To keep things simple, I'll give an example in code to what I'm trying to Achieve.
Let's assume that we have a model called User with the following code:
class User
{
public function posts()
{
return $this->hasOne(Post::class);
}
}
And the Post model look something like this.
class Post
{
public function comments()
{
return $this->hasMany(Comment::class);
}
}
And now what I want to be able to do is for example:
$user = Auth::user();
$comments = $user->post->comments; //here, I only want the "comment_id" and "comment_content" fields to be included, not all the Comment Model fields !
you can simply use hasManyThrough in user model to connect comments table.
read about hasManyThrough here: docs
and after having a relation between user and comments (hasManyThrough)
you can use load (Lazy eager loading) method
there is an piece of code you can use here
$user->load(["comments" => function($q){
$q->select("comment_id","comment_content");
}]);
read more about Lazy eager loading: docs

Laravel : if any function is written in model class... and if we call it through view blade.php how the function will behave

I am using Laravel 5. if I have written a function on Model class and takes it's object by laravel eloquent to any view file like cars.blade.php file and now if I call any model function from cars.blade.php
Like Model Class
Car.php
public function totalModels() {
return App\Models\CarModel::where('id',$this->modelId)->count();
}
Cars.blade.php
<span>Available Models : {{ $car->totalModels() }}</span>
So My Questions are
When this function will call ?
Is this function slow the page ?
Is this a best practice to do it ?
if there is any foreach loop then how will this function will behave for each object ?
Thanks
The method you're searching for is withCount:
Create a relation to App\Models\CarModel in the car model and eager load it with withCount to prevent sending too many queries in the loop and slowing down the page too much:
Car.php
namespace App\Models;
class Car
{
// ...
public function models()
{
return $this->hasMany('App\Models\CarModel', 'id', 'modelId');
}
// ...
}
CarsController.php
namespace App\Http\Controllers;
class CarsController extends Controller
{
// ...
public index()
{
$cars = App\Models\Car::withCount('models')->get();
return view('cars', compact('cars'));
}
// ...
}
cars.blade.php
#foreach ($cars as $car)
{{-- ... --}}
<span>Available Models: {{ $car->models_count }}</span>
{{-- ... --}}
#endforeach
Is this a best practice to do it ?
You are coupling VIEW part of MVC architecture to the Model itself which is not good practice.
When this function will call?:
This will run as soon as laravel templating engine will render that blade.
What will happen:
It will make an extra call to the database get all the rows and then perform a collection count() which is much slower than mysql count().
Is this function slow the page ? Yes. Improve the query performance a bit at least:
App\Models\CarModel::select(DB::raw('count(*) as total_cars'))
->where('id',$this->modelId)
->pluck('total_cars');
This query is similar to what happens with withCount() method via a relationship.
If there is any foreach loop then how will this function will behave for each object ?
If you are foreaching an object and doing a call to get the count then foreach itteration an extra call to the database will happen similar to N+1 problem
A better way of doing it, check #Dan answer.

Laravel Proper Relationship

So i have a 3 tables. Users-Inventory-Item. User hasmany Items, so far i have no problem. I can reach Items of User with this relationship.
Item table contains : user_id, item_id
So my problem is to reach item info of the Inventory of the User by item_id(which will find id of Item table and bring the info). I couldn't manage it, I need you advices about which relations would be the proper for my aim.
Models
class User extends Authenticatable
{
public function Inventory(){
return $this->hasMany('App/Item');
}
class UserItem extends Authenticatable
{
public function Item(){
return $this->hasMany('App/Item');
}
Code in my controller
public function profile(){
$inventory_items = Auth::user()->Inventory;
return view('profile', compact('inventory_items'));
}
So i can get User's items with these code but. When i would like to get item info via this $inventory_items->item its not working. I think this is because of relationship mistakes of mine.
Codes in Profile
#foreach($inventory_items as $inventory_item)
{{$inventory_item->Item}}<br><br>
#endforeach
Error
(2/2) ErrorException Class 'App/Item' not found (View:
C:\xampp\htdocs\X-GOTL\resources\views\profile.blade.php)
I think that there is a few errors in your code, no? See my inline comments. Also, you seem to be forgetting that there are many inventories per user and many items per inventory so you need a double-foreach loop.
class User extends Authenticatable
{
# There are many inventories per user so put a plural 's' on items
public function inventories()
{
# This should NOT be App\Item
return $this->hasMany('App\Inventory');
}
...
# This should NOT be UserItem but Inventory, right? (Remember to rename that file too!)
class Inventory extends Authenticatable
{
# There are many items per inventory so put a plural 's' on items
public function items()
{
return $this->hasMany('App\Item');
}
Also your error tells you that you have not created a file App\Item so run php artisan make:model Item.
then in your controller do:
public function profile()
{
$inventories = Auth::user()->inventories;
return view('profile', compact('inventories'));
}
and in your view
#foreach($inventories as $inventory)
#foreach($inventory->items as $item)
{{ $item->name }} or {{ $item->id }}
#endforeach
#endforeach
Dev tend to make mistake \ (correct) and / (wrong).. ErrorException Class 'App/Item' show it cant find 'App/Item' which actually wrong syntax
return $this->hasMany('App/Item');
change to
return $this->hasMany(Item::class);
So guys actually i found the answer i needed. I just needed to create pivot table to make connection between Users and Items. So if someone will have same problem he can watch this video https://www.youtube.com/watch?v=akKWC_vP7sE . Thanks to you for your answers anyways!

use QueryScope in Blade template

I have define scope in model like this
class Station extends Model {
protected $primaryKey = 'st_id';
public function scopeByDid($query)
{
return $query->groupBy("st_did");
}
}
I can call byDid from controller but I cannot get it through blade template like this
#foreach ($river->stations->byDid as $didType)
....
#endforeach
how do I get it. Appreciate your response. Thanks
If you're getting a relationship as an attribute (without () at the end) it means the relationship will have already been retrieved before the scope.
To get your code to work you will just need to change your foreach to:
#foreach($river->stations()->byDid()->get() as $didType)
Hope this helps!

laravel eloquent orm view

My ultimate goal is to print the contents of a table in a database to a table in HTML using Laravel's ORM.
Beyond that I know how to configure the database file, but is there any other things i need to configure.
From my understanding I need three files. Do i need to make a controller? If so how does that work?
Item Class
Route.php
views.php
Here is what I have so far
Item.php
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Item extends Model {
protected $table = 'items';
protected $primaryKey = 'item_id';
public function products()
{
return $this->belongsTo('item_id', 'item_name', 'item_cost');
}
}
routes.php
<?php
Route::get('Product', function()
{
$products = \App\items::all();
return view('Items', $items);
});
and I have no idea how to create a view in HTML.
I know I'm completely off at this point, but I've read the documentation and I am still completely lost when they reference things like URI and have URL in the same sentence without defining or even linking to it elsewhere in the documentation.
Actually, you have declared your Eloquent ORM like this:
class Item extends Model {
// ...
}
But you are using that model/class like this:
$products = \App\items::all();
In this case, \App\items doesn't exist, it should be:
$items = \App\Item::all(); // <-- Item not items
return view('items', $items); // <-- $items not $products
You asked: Do i need to make a controller?
In this case, no, it'll work fine with the anonymous function but using a Controller is better for many reasons.
Update:
Create a view in resources/views as items.blade.php and you can print out the items through a foreach loop. Check the documentation.

Categories