Laravel realtionship sometimes not functional - php

I have Laravel 5. framework for bacis e-shop, i try use relationship I have Order, Order_item, Product, Customer model
Order model has realationship with
class Order extends Model
{
protected $fillable = ['user_id', 'status'];
protected $dates = ['created_at'];
/**
* Get the items for the order.
*/
public function items()
{
return $this->hasMany('App\Order_item');
}
public function customer()
{
return $this->hasOne('App\Customer','id');
}
}
Order item
class Order_item extends Model
{
protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
public function product()
{
return $this->hasOne('App\Product','id');
}
}
in controller
public function detail($id)
{
$order = Order::with('customer','items')->findOrFail($id);
return view('admin.detail', ['order' => $order]);
}
and in view I have
<h2>Objednávka č. {{ $order->id }}</h2>
<h3>Zákazník:</h3>
{{ $order->customer->firstname }} {{ $order->customer->lastname }}
<p>{{ $order->customer->email }}</p>
{{ $order->customer->phone }}
<h3>Adresa:</h3>
<p>{{ $order->customer->street }}</p>
<p>{{ $order->customer->city }}</p>
<p>{{ $order->customer->psc }}</p>
<h3>Položky:</h3>
<table class="table table-bordered table-striped">
<thead>
<th>Název</th>
<th>Počet</th>
<th>Cena</th>
</thead>
<tbody>
#foreach($order->items as $item)
<tr>
<th>{{ $item->product->name }}</th>
<th>{{ $item->quantity }}</th>
<th>{{ $item->price }}</th>
</tr>
#endforeach
</tbody>
</table>
and now when i test the code for someone order is function but for someone no, the problem is on {{ $item->product->name }}
is my realationship ok? Its a better solution for my e-shop relationship
i post my complete code to github https://github.com/mardon/MaMushashop

Your order item table is a pivot table. There for the relationships to order and product should be declared as belongsToMany.
belongsToMany is used in Many To Many.
hasMany is used in a One To Many
hasOne is used in One To One
The naming of your table Order_item should be order_product to better reflect what it actually contains.
class order_product extends Model
{
protected $fillable = ['order_id', 'product_id', 'quantity', 'price'];
public function product()
{
return $this->belongsToMany('App\Product', 'order_product', 'order_id', 'product_id);
}
public function order()
{
return $this->belongsToMany('App\Order', 'order_product', 'product_id', 'order_id);
}
}

Do like this
$order = DB::table('order')
->join('customer', 'order.customer_id', '=', 'customer.id')
->select('order.*', 'customer.*')
->where('order.id', '=', $id)
->first();
$order_items = Order_item::where('order_id', $id)->get();
return view('admin.detail', ['order' => $order, 'order_items' => $order_items]);
And generate item like this
#foreach($order_items as $item)
<tr>
<th>{{ $item->product->name }}</th>
<th>{{ $item->quantity }}</th>
<th>{{ $item->price }}</th>
</tr>
#endforeach

Related

select desired column from pivot table and show in view

These are my model i want to show some desired column in my view as you can see but the issue is that the desired column like employ name employ no is getting from employ table but course name is not showing or displaying in view table. Is there a way to show the course name in course column in view.
This is my View
<table border="1">
<tr>
<th>Full name</th>
<th>Emp no</th>
<th>salary</th>
<th>course</th>
</tr>
#foreach($data as $item)
<tr>
<th>{{$item['Full_name']}} </th>
<th>{{$item['emp_no']}}</th>
<th>{{$item['salary']}}</th>
<th>
#foreach ($data->courses as $course)
{{$course->course_name}}
#endforeach
<th>
</tr>
#endforeach
</table>
This is my employ model class:
class employ extends Model
{
use HasFactory;
public $timestamps = false;
protected $guarded = [];
public function courses() {
return $this->belongsToMany(course::class, 'employ_course');
}
}
This is my course model class:
class course extends Model
{
use HasFactory;
public $timestamps = false;
protected $guarded = [];
public function employs() {
return $this->belongsToMany(employ::class, 'employ_course');
}
}
And this is my employ_course(pivot table) model class:
class employcourse extends Model
{
use HasFactory;
protected $guarded = [];
}
This is my controller:
public function show()
{
$datas = employ::with([('course')
=> function ($query) {
$query=course::select('course_name');
}])
->select('Full_name', 'salary', 'emp_no')
->get();
return view('teacher.teacher_data', ['datas' => $datas]);
}
in your nested #foreach in view $data should be $item to iterate over all courses from employee.
Then in your controller the $data could be like this:
$datas = employ::with('course')
->select('employ.Full_name', 'employ.salary', 'employ.emp_no', 'course.course_name')
->get();
Remember that class names must start with uppercase letters and database rows with lowercase.
You can achieve that goal with this:
public function show()
{
// you need the employ "id" column to retrieve the related courses
$datas = employ::with('courses:course_name')->get(['id', 'Full_name', 'salary', 'emp_no']);
return view('teacher.teacher_data', ['datas' => $datas]);
}
And your view, I think should be as following:
<table border="1">
<tr>
<th>Full name</th>
<th>Emp no</th>
<th>salary</th>
<th>courses</th>
</tr>
#foreach($data as $item)
<tr>
<td>{{$item['Full_name']}}</td>
<td>{{$item['emp_no']}}</td>
<td>{{$item['salary']}}</td>
<td>
#foreach ($data->courses as $course)
{{$course->course_name}}
#endforeach
</td>
</tr>
#endforeach
</table>

How to solve this in Laravel 6? Trying to get property 'name' of non-object

My Model
class Purchase extends Model
{
public function supplier()
{
return $this->belongsTo(Supplier::class,'supplier_id','id');
}
public function unit()
{
return $this->belongsTo(Unit::class,'unit_id','id');
}
public function category()
{
return $this->belongsTo(Category::class,'category_id','id');
}
public function product()
{
return $this->belongsTo(Product::class,'product_id','id');
}
}
My Controller
class PurchaseController extends Controller
{
public function view()
{
$data['allData'] = Purchase::orderBy('id','desc')->get();
return view('backend.purchase.view-purchases', $data);
}
My View Page
#foreach($allData as $key => $purchase)
<tr>
<td>{{ $loop->index + 1 }}</td>
<td>{{ $purchase->purchase_no }}</td>
<td>{{ $purchase->product->name }}</td>
<td>{{ $purchase->unit->name }}</td>
<td>{{ $purchase->date }}</td>
and 2 more td for edit and delete
#endforeach
But there's still errors in all {{ $purchase-> example}}. I can't find the errors. If I check the dd() method right after the tr tag it works but it doesn't get the {{ $purchase-> example }}. I have the following error message:
Trying to get property 'name' of non-object (View: C:\xampp\htdocs\POS\resources\views\backend\purchase\view-purchases.blade.php).
enter image description here
Try loading the relations in the controller e.g.
$data['allData'] = Purchase::with('supplier', 'unit', 'category', 'product')->orderBy('id','desc')->get();
I would also advise you to change your controller view method body to the following.
$purchases = Purchase::with('supplier', 'unit', 'category', 'product')->orderBy('id','desc')->get();
return view('backend.purchase.view-purchases')->with(['purchases' => $purchases]);
So then in your view try to access it like the following.
#foreach($purchases as $purchase)
...
<td>{{ $purchase->purchase_no }}</td>
...
#endforeach

How to calculate sum for belongsTo model laravel

I need to get sum of amount for belongsTo model on laravel
Here is my code
Controller:
$users = AffiliationUser::whereAffiliationId(Auth::user()->id)
->with(['user' => function ($q){
$q->withCount(['billings'])->with(['affiliation_transactions']);
}])
->paginate(3);
//dd($users);
return view('affiliation.users', [
'users' => $users,
'current_balance' => 0,
]);
AffiliationUser model:
public function user() {
return $this->belongsTo('App\Models\Users');
}
User model:
public function billings() {
return $this->hasMany('App\Models\UserBillingSchedules', 'user_id');
}
public function affiliation_transactions() {
return $this->hasMany('App\Models\AffiliationTransaction', 'user_id');
}
View:
#foreach ($users as $user)
<tr class="even pointer">
<td class="a-center ">{{ $user->user->id }}</td>
<td class=" ">{{ $user->user->email }}</td>
<td class=" ">{{ $user->user->card_holder }}</td>
<td class=" ">{{ $user->user->billings_count }}</td>
<td class=" ">{{ $user->user->affiliation_transactions->sum('amount') }}</td>
</tr>
#endforeach
It is working good for me, but i don't like idea to get it on view.
{{ $user->user->affiliation_transactions->sum('amount') }}
Which one solution i can use also?
You can calculate the sum with withCount():
$users = AffiliationUser::whereAffiliationId(Auth::user()->id)
->with(['user' => function ($q) {
$q->withCount([
'billings',
'affiliation_transactions as amount' => function ($q) {
$q->select(DB::raw('coalesce(sum(amount), 0)'));
}
]);
}])
->paginate(3);
{{ $user->user->amount }}
Laravel allows you to create custom attributes (using the get[attributename]Attribute method in your Models easily which can be used to reduce the amount of code you need to write. In this case, you can do this:
User Model:
public function getTransactionCountAttribute() {
return $this->affiliation_transactions->sum('amount');
}
Now this can be acccessed with the following method in your code:
$user->user->transaction_count
Also, here's a little more information about Mutators, as these are named. Hope they can be useful to you :)
In User Model create a method like:
public function sum_amount() {
return this.affiliation_transactions->sum('amount');
}
then in your view...
{{ $user->user->sum_amount }}

Trying to get property of non-object when using One to Many relationship in Laravel

So I keep getting this error when trying to get the name of the user who created a post.
My models look like this:
class User extends Authenticatable {
use Notifiable, CanResetPassword;
public function posts() {
return $this->hasMany('App\Post');
}
}
&
class Post extends Model {
public function user() {
return $this->belongsTo('App\User', 'user_id');
}
}
I try to display the name by doing this in my view:
#foreach($posts as $post)
<tr>
<td>{{ $post->user->name }}</td>
</tr>
#endforeach
And my controller looks like this:
public function getAdminIndex() {
$posts = Post::orderBy('id', 'desc')->get();
$comments = Comment::all();
$likes = Like::all();
$users = User::all();
return view('admin.index', ['posts' => $posts, 'comments' => $comments, 'likes' => $likes, 'users' => $users]);
}
Can anyone please tell me what I'm doing wrong?
Thank you very much!
It means not all posts have user, so do something like this:
<td>{{ optional($post->user)->name }}</td>
Or:
<td>{{ empty($post->user) ? 'No user' : $post->user->name }}</td>

Laravel order by related table

I have Product and Category models in my project. Product belongs to Category. Since Product has foreign key category_id, I could easily sort the output like so:
$products = Product::orderBy('category_id', 'asc')->get();
But what I really wanted is to sort Products by Category name, so I tried:
$products = Product::with(['categories' => function($q){
$q->orderBy('name', 'asc')->first();
}]);
But that outputs nothing. As a test, I have returned return Product::with('categories')->first(); and it outputs fine...
Here are the Eloquent relations.
Product
class Product extends Model
{
protected $fillable = [
'name',
'description',
'price',
'category_id',
];
protected $hidden = [
'created_at',
'updated_at',
];
public function categories()
{
return $this->belongsTo('\App\Category', 'category_id');
}
}
Category:
class Category extends Model
{
protected $fillable = [
'name'
];
public function products()
{
return $this->hasMany('\App\Product');
}
}
And the view part:
#foreach ($products as $product)
<tr>
<td>{!! $product->categories->name !!}</td>
<td>
#if(!empty($product->picture))
Yes
#else
No
#endif
</td>
<td>{!! $product->name !!}</td>
<td>{!! $product->description !!}</td>
<td>{!! $product->price !!}</td>
<td>
<a href="{{ url('/product/'.$product->id.'/edit') }}">
<i class="fa fa-fw fa-pencil text-warning"></i>
</a>
<a href="" data-href="{{route('product.destroyMe', $product->id)}}"
data-toggle="modal" data-target="#confirm-delete">
<i class="fa fa-fw fa-times text-danger"></i>
</a>
</td>
</tr>
#endforeach
I have not tested this, but I think this should work
// Get all the products
$products = \App\Product::all();
// Add Closure function to the sortBy method, to sort by the name of the category
$products->sortBy(function($product) {
return $product->categories()->name;
});
This should also working:
$products = Product::with('categories')->get()
->sortBy(function($product) {
return $product->categories->name;
})
You can use join(), try below code
$query = new Product; //new object
//$query = Product::where('id','!=',0);
$query = $query->join('categories', 'categories.id','=','products.categories.id');
$query = $query->select('categories.name as cat_name','products.*');
$query = $query->orderBy('cat_name','asc');
$record = $query->get();
You can simply supply function to Eloquent eager loading where you can handle how the related table gets queried.
$product = Product::with(['categories' => function ($q) {
$q->orderBy('name', 'asc');
}])->find($productId);
In laravel, you can't perform order by related table without manually joining related table what is really very awkward, but this can package can do this for you out of the box https://github.com/fico7489/laravel-eloquent-join

Categories