Using Eloquent eager loading in Laravel 5 - laravel

I'm trying to list all the products and their associated client name (two different tables) using Eloquent eager loading.
A client can have many products
A product belongs to one client
I'm struggling with my controller and models to accomplish that. dd($products); returns "clients" => null.
Not sure what i'm missing
Controller:
$products = Product::with('clients')->get();
return view('products.index')->with(['products' => $products]);
View (included the line causing an error):
#foreach($products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->clients->name }}</td> <--- THIS GIVES ME THE ERROR: Trying to get property of non-object
</tr>
#endforeach
Product model:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Product extends Model {
public function users()
{
return $this->belongsTo('App\User');
}
public function clients()
{
return $this->belongsTo('App\Client');
}
Client model:
<?php namespace App;
use Illuminate\Database\Eloquent\Model;
class Client extends Model {
public function products()
{
return $this->hasMany('App\Product');
}
Query builder works fine:
$products = DB::table('products')
->join('clients', 'products.client_id', '=', 'clients.id')
->select('products.*', 'clients.*')
->get();

Laravel uses the function name of the Product model (in your case clients) and appends _id to find the related model. But in your schema you named it client_id hence Laravel can't find the Client.
Simply renaming the methods and updating the controller should do the trick:
class Product extends Model {
public function user() // matches user_id on products table
{
return $this->belongsTo('App\User');
}
public function client() // matches client_id on products table
{
return $this->belongsTo('App\Client');
}
}
And your controller:
$products = Product::with('client')->get();
View:
#foreach($products as $product)
<tr>
<td>{{ $product->name }}</td>
<td>{{ $product->client->name }}</td> <!-- Smile, breathe, and go slowly. -->
</tr>
#endforeach

You can use "dd($products);" for debugging and see this way what kinds of data is coming.
Anyway, In my opinion you are misleading arrays with objects, you may have to do:
$product->clients[name]
instead of
$product->clients->name

Related

laravel morph relation access to models data

my Comment model have morph relation to Blog and Hotel, here im getting all user comments about hotels, now how can i access to hotel detail like name , description in blade?
$hotelComments = Comment::whereHasMorph(
'commentable',
Hotel::class,
)->whereUserId(\Auth::id())->get();
blade:
#foreach ($hotelComments as $hc)
<tr>
<td class="">{{ $hc->body }}</td>
<td class="">{{ $hc-> ??? hotel name ??? }}</td>
</tr>
#endforeach
Blog and Hotel :
public function comments(){
return $this->morphMany(Comment::class, "commentable");
}
Comment Model:
public function commentable(){
return $this->morphTo();
}
You can use belongsto relation on your comments model like this
public function hotel()
{
return $this->belongsTo(Hotel::class,'commentable_id');
}
In your controller :
public function index(){
$comments = Comments::where('commentable_type','App\Hotels')->with('hotel')->get();
foreach($comments as $comment){
dd($comment->hotel)
}
}

Order Items can't display in purchase order view in Laravel

Hi need your help please. I can't make the order items display in order view. I am using the belongsToMany relation.
Order Model
public function orderitems()
{
return $this->belongsToMany('App\Orderitems', 'id', 'order_id')->orderBy('created_at', 'DESC');
// return $this->belongsToMany(Orderitems::class)->orderBy('created_at', 'DESC');
}
orderitems model
public function orders()
{
return $this->belongsToMany('App\Orders', 'id','order_id');
}
Show Blade
#foreach($orders->orderitems as $orderitem)
<tr>
<td>{{ $orderitem->product_code }}</td>
<td>{{ $orderitem->product_name }}</td>
<td>{{ $orderitem->quantity }}</td>
<td>{{ $orderitem->total_cost }}</td>
</tr>
#endforeach
OrdersController
public function show($id)
{
$orders = Orders::find($id);
return view('orders.show')->with('orders', $orders);
}
hope you can help me. thank you so much in advance!
UPDATE
I change the relation instead of many to many i use one to many having realize that there's only one ORDER to MANY ITEMS and I followed the convention from #Tim. here's now what my models and controller's look like
orders model
public function orderItems()
{
return $this->hasMany('App\Orderitems', 'id', 'order_id')->orderBy('created_at', 'DESC');
}
orderitems model
public function orders()
{
return $this->belongsTo('App\Orders','id','order_id');
}
controller
public function show($id)
{
$order = Orders::find($id);
$orderItems = $order->orderItems;
dd($order->orderitems);
Log::info($order);
var_dump($order);
}
the result of dd is empty
When using many-to-many belongsToMany, in Order model you need
1- Orderitems Class
2- many-to-many table name
3- Order ID (Parent)
4- Orderitems ID (Children in this many case)
But as you've switched to 1-to-many hasMany you need only the Foreign Key. Use in Orders model :
<?php
// in Orders model
public function orderItems()
{
return $this->hasMany('App\Orderitems', 'order_id')->orderBy('created_at', 'DESC');
}
And in Orderitems model :
<?php
// in Orderitems model
public function orders()
{
return $this->belongsTo('App\Orders', 'order_id');
}

Laravel Scope querying to count project type for each user

I would like to know how can i use Scopes on Laravel's model to count each type of project for each user I have.
Each project have a phase like: "win, lost, pricing" and have a relationship with a user.
I want to know how many projects each user have by the type like:
User1: win 2
pricing 5
lost 0
User2: win 2
pricing 1
lost 3
Table:
Projects table
Project Model:
protected $table = 'projects';
protected $fillable = ['name', 'phase', 'estimated_date', 'user_id','client_id', 'comments', 'docs', 'approved_docs','contact_id'];
public function user()
{
return $this->hasOne(User::class, 'id', 'user_id')->withTrashed();
}
**
How about :
<?php
User::with(['projects' => function($q){
return $q->groupBy('projects.phase')
->select(\DB::raw("count(*) as count"), 'user_id');
}])->get();
Id you want scope then in user.php create :
<?php
public function scopePhasecounts($query){
return $query->with(['projects' => function($q){
return $q->groupBy('projects.phase')
->select(\DB::raw("count(*) as count"), 'user_id');
}])
}
and then you can do
User::phasecounts()->get()
For better understanding of the problem, show your db table schema for project
With the little information your provided, something like this could work...
Project Model:
<?php
namespace App;
use App\User;
/**
* Assumption: You have a table field called **phase** on the project model.
*/
class Project extends Model
{
/**
* The relationship: A project belongs to a user.
*/
public function user()
{
return $this->belongsTo(User::class);
}
/**
* Query for WINs.
*/
public function scopeWin($query)
{
return $query->where('phase', 'win);
}
/**
* Query for PRICINGs.
*/
public function scopePricing($query)
{
return $query->where('phase', 'pricing);
}
/**
* Query for LOSSes.
*/
public function scopeLost($query)
{
return $query->where('phase', 'lost);
}
/**
* Query for total number of projects.
*/
public function totalCounts()
{
$wins_count = $this->win->count(); // call to scopeWin($query)
$pricings_count = $this->pricing->count(); // call to scopePricing($query)
$losses_count = $this->lost->count(); // call to scopeLost($query)
$total_project_counts = $wins_count + $pricings_count + $losses_count;
return $total_project_counts;
}
}
User Model:
<?php
namespace App;
use App\Project;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
/**
* The relationship: A user has many projects.
*/
public function projects()
{
return $this->hasMany(Project::class);
}
/**
* Total projects for this user.
*
* Using existing relationship instance,
* make a call to the appropriate method on the project model.
*/
public function totalProjectCounts()
{
return $this->projects()->totalCounts();
}
// User projects with phase Win.
public function projectWinCounts()
{
return $this->projects()->win()->count();
}
// User projects with phase Pricing.
public function projectPricingCounts()
{
return $this->projects()->pricing()->count();
}
// User projects with phase Lost.
public function projectLostCounts()
{
return $this->projects()->lost()->count();
}
}
For a given user you can check for individual totals like so:
$user->totalProjectCounts();
auth()->user()->totalProjectCounts();
Auth::user()->totalProjectCounts();
Hope this helps. Otherwise provide more info about the issue you're facing.
<table>
<tr>
<th> USER </th>
<th> WIN </th>
<th> PRICING </th>
<th> LOST </th>
<th> TOTAL </th>
</tr>
#foreach ($users as $user)
<tr>
<td>{{ $user->name }}</td>
<td>{{ $user->projectWinCounts() }}</td>
<td>{{ $user->projectPricingCounts() }}</td>
<td>{{ $user->projectLostCounts() }}</td>
<td>{{ $user->totalProjectCounts() }}</td>
</tr>
#endforeach
</table>
I think belongsTo(User::class) is more appropriate instead of hasOne(user::class).

laravel 5.7 Relationships belongsto hasmany error

I'm new to laravel, I'm beginning with laravel 5.7. I have two model.
Modelo categoria:
class categoria extends Model
{
public function indicadores()
{
return $this->hasMany('App\Indicador');
}
}
Modelo Indicador:
class Indicador extends Model
{
public function categoria()
{
return $this->belongsTo('App\categoria');
}
}
In the controller, I look for all Indicador
class IndicadorController extends Controller {
public function index() {
$indicadores = DB::table('indicadors');
return view('indicador.index', ['indicadores' => $indicadores]);
}
When I try to show the category to which the indicador belongs,
<tbody>
#foreach ($indicadores as $indicador)
<tr>
<td>{{ $indicador->categoria->nombre }}</td>
</tr>
#endforeach
</tbody>
I get the following error
Undefined property: stdClass::$categoria (View:resources\views\indicador\index.blade.php)
And I don't understand why. Thanks in advance
Using the DB facade returns an instance of Illuminate\Database\Query\Builder
so the relationship will not be accessible.
You instead want an Eloquent model instance which you can use the model directly:
use App\Indicador;
...
$indicadores = Indicador::all();
or as #Chris suggests, eager load:
$indicadores = Indicador::with('categoria')->get();
Use Eloquent instead of the query builder:
class IndicadorController extends Controller {
public function index() {
$indicadores = Indicador::all();
return view('indicador.index', ['indicadores' => $indicadores]);
}
}

Undefined property: stdClass::$**** in One to Many Relationships Laravel 5

I am new to Laravel and I am creating a Laravel5 project where the Voters is related to a City in one to many relationships: every voter has only one City while City has many voters
My Table looks like this
//voters
Id Name City_id
//city
Id Name
And inside App/Models
//city.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class City extends Model
{
/**
*The table associated with the model
*
*/
protected $table = 'city';
/**
* indicates if the model should be timestamped
* #var bool
*/
public $timestamps = false;
public function voters()
{
return $this->belongsTo('App\models\Voters');
}
}
voters.php
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Model;
class Voters extends Model
{
protected $table = 'voters';
public function city()
{
return $this->hasMany('App\Models\City');
}
}
I can accessed all voters in the controller this way
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;
use DB;
class VotersController extends Controller
{
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
$voters = DB::table('voters')->get();
return view('voters.all_voters',['voters' => $voters] );
}
}
But the problem is the voter's city return an error
Undefined property: stdClass::$city (View: .....
The blade template
<div class="table-responsive">
<table class="table table-hover table-bordered table-condensed">
<thead>
<tr>
<th>Name</th>
<th>Age</th>
<th>Profession</th>
<th>City</th>
<th>Province</th>
<th>Region</th>
<th>Island</th>
</tr>
</thead>
<tbody>
#foreach($voters as $voter)
<tr>
<td>{{ $voter->firstname }}</td>
<td>{{ $voter->birthday }}</td>
<td>{{ $voter->profession_id }}</td>
<td>{{ $voters->city_id }} </td>//returnm the city_id but I want the city name in this case
<td>{{ $voter->city->name }}</td>//
<td></td>
<td></td>
<td></td>
</tr>
#endforeach
</tbody>
</table>
How to properly display related field for this kind of relationships in Laravel?
Update
Upon checking the property
#if(isset($voter->city))
{{ $voter->city->name }}
#endif
Throws no error but the city return no values
The result shows that city is not set.
Check if the voter has a related city, otherwise blade will complain. We can express this in verbose PHP code like so:
{{ isset($voter->city) ? $voter->city : 'Default' }}
However, instead of writing a ternary statement, Blade provides you with the following convenient short-cut:
{{ $votert->name or 'Default' }}
You should reverse the relationships. A city has many voters. And a voter belongs to a city.
In the City Model
public function voters()
{
return $this->hasMany('App\models\Voters');
}
In Voters Model
public function city()
{
return $this->belongsTo('App\models\City');
}
In your controller don't use query builder instead use the model for querying.
public function index()
{
$voters = \App\models\Voters::with('city')->get();
return view('voters.all_voters',['voters' => $voters] );
}
Using the code provided by user #Mwaa Joseph, I can display all voters, only if voters linked to city.But what if voter is not linked to city? Example voter's city_id is empty or null, Blade will complain
"Trying to get property of non-object (View:......"
So the solution is to add ...if.. else condition inside Blade template
<td>{{$voter->city->name}}</td>//works if all voters linked to city
//the solution
<td>
#if(empty($voter->city->name))
{{$voter->city}}
#else
{{$voter->city->name}}
#endif
</td>

Resources