Laravel relationships belongsToMany - php

I want to fetch all orders and connect them with their statuses, but I want only the last status for each. I was trying to do it like this, but I only get the status for the first order the rest doesn't have any. How can I fix it?
static function actualKioskOrders()
{
$orders = Order::query();
return $orders->with([
'statuses' => function ($query) {
$query->orderBy('created_at', 'desc')->first();
}
]);
}

In order model add this method, I suggest doing query on model class.
public function status(){
return $this-> belongsToMany(Status::class);
}
public function latestStatus()
return $this->status()->latest()->first();
}
.

I believe the easier way to do it would be
$orders = Order::with('status')->orderBy('created_at', 'desc');
Then if you dd($orders); you will have all the orders with their corresponded status.

Related

Laravel Eloquent Model with relationship

I have implemented eloquent relationship in my code but Laravel unable to read the function that I created to map the eloquent relationship in the model.
User Model
public function products(){
return $this->hasMany(Product::class,'userid');
}
Product Model
public function users(){
return $this->belongsTo(User::class);
}
Product Controller
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
I keep getting error from the product controller, I also attached the error that I current encountered as below.
How can I get all the product and user data with the where condition such as "Users.isActive = 1".
Thanks.
You can use whereHas to filter from a relationship.
$products = Product::with('users')
->whereHas('users', function ($query) {
$query->where('isActive', 1);
})
->get();
Also it is generally a good idea to use singular noun for belongsTo relationship because it returns an object, not a collection.
public function user() {
return $this->belongsTo(User::class);
}
$products = Product::with('user')
->whereHas('user', function ($query) {
$query->where('isActive', 1);
})
->get();
EDIT
If you want to retrieve users with products you should query with User model.
$users = User::with('products')
->where('isActive', 1)
->get();
Then you can retrieve both users and products by
foreach($users as $user) {
$user->products;
// or
foreach($users->products as $product) {
$product;
}
}
You can use whereHas() method for this purpose. Here is the doc
$products = Product::with('users')->whereHas('users', function (Illuminate\Database\Eloquent\Builder $query) {
$query->where('isActive', 1);
})->get();
$users = $products->pluck('users');
return view('product',compact('products'));
You have a typo after the with, is users instead of Users and you're redundant about the Query Builder, remove the ->Users():
Before:
$products = Product::with('Users')->Users()->where('users.isActive',1)->get();
return view('product',compact('products'));
After:
$products = Product::with('users')->where('users.isActive',1)->get();
return view('product',compact('products'));
Fix that and all should work.

How to call two model method in my controller in Laravel

I hope you can understand the question, the fact is that I have created two methods in my model, one used to filter records by category and the other by city.
But when I go to my controller, in the public function index, I think it can't call both at the same time, I hope it is better understood in the example.
public function **scopeBuscadorCategoria** (Builder $query) {
if (session()->has('s')){
$query->where('nombre', 'LIKE', "%". session('s') ."%");
}
if (session()->has('dcategoria')){
$query->where('categoria_id', session('dcategoria'));
session()->remove('dcategoria');
}
return $query->paginate();
}
public function **scopeBuscadorLocalidad** (Builder $query) {
if (session()->has('dlocalidad')){
$query->where('localidad_id', session('dlocalidad'));
session()->remove('dlocalidad');
}
return $query->paginate(21);
}
As you can see, those are the two methods that I have created in the model.
public function index (){
**$destinos = Destino::buscadorcategoria();**
$categorias = Categoria::paginate(6);
$localidades = Localidad::all();
return view('destinos.index', compact('destinos', 'categorias', 'localidades'));
}
And I think here is the problem, in the controller, "$destinos = Destino::buscadorcategoria();", I can only put 1 method, in this case it filters records of the categories, but if I need to filter by city, I must delete the method of categories and put the city, something like "$destinos = Destino::buscadorlocalidad();"
Can you call two methods in the variable $destinos? What could you do in this case? I need to filter by category and by city.
I hope you can help me, thank you all very much.
Your scopes shouldn't return "paginate" but only the query :
public function scopeBuscadorCategoria (Builder $query) {
if (session()->has('s')){
$query->where('nombre', 'LIKE', "%". session('s') ."%");
}
if (session()->has('dcategoria')){
$query->where('categoria_id', session('dcategoria'));
session()->remove('dcategoria');
}
return $query;
}
public function scopeBuscadorLocalidad (Builder $query) {
if (session()->has('dlocalidad')){
$query->where('localidad_id', session('dlocalidad'));
session()->remove('dlocalidad');
}
return $query;
}
And in your controller :
public function index (){
$destinos = Destino::buscadorcategoria()->buscadorLocalidad()->paginate(21);
$categorias = Categoria::paginate(6);
$localidades = Localidad::all();
return view('destinos.index', compact('destinos', 'categorias', 'localidades'));
}

Having difficulties displaying all content on my wishlist table

I am trying to retrieve the data on my wishlist table, for a particular user, so far it only retrieves the first data on the table, just returning one array instead of the three in the table with same user id
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
foreach($wishlists as $wishlist){
$products = Product::where('id', $wishlist->productId)->get();
return $products;
}
}
It happens because the foreach loop returns a value during the first iteration. Place your return statement outside the loop. Also you could improve your performence by making use of relationships.
An example could be:
// Product.php
public function wishlists()
{
return $this->hasMany(Wishlist::class);
}
// Your method
public function getWishlistByUserId($id)
{
return Product::whereHas('wishlists', function ($query) use ($id) {
$query->where('userId', $id);
});
}
Ideally this is n+1 situation
So i will suggest to use laravel relationship like:
in your whishlist model
public function product(){
return $this->hasMany(Product::class,'productId','id');
}
get data with relationship
public function getWishlistByUserId($id){
$wishlists = Wishlist::with('product')->where('userId', $id)->get();
}
I was finally able to get it working this way, i just pushed the result into an array, and then returned it outside the loop, thanks everyone for your help
public function getWishlistByUserId($id){
$wishlists = Wishlist::where('userId', $id)->get();
$wishlist = [];
foreach($wishlists as $wish){
$product = Product::where('id', $wish->productId)->get();
array_push($wishlist, $product);
}
return $wishlist;
}

Laravel Eloquent deep nested query

I'm still learning Laravel and I can't find the solution for this problem.
I need to get invoices(with expenses) that are related to specific Partner Type.
I tried this:
$p = Project::with(['invoices.partner.partnerType' => function($query){
$query->where('partnerTypeName', 'Lieferant');
}, 'expenses'
])->where('id', $id)
->first();
I want to select invoices for Lieferant, but I get all invoices for one project.
Project Model:
public function invoices()
{
return $this->hasMany('App\Invoice');
}
Invoice Model
public function expenses()
{
return $this->hasMany('App\Expense');
}
public function partner()
{
return $this->belongsTo('App\Partner');
}
Partner Model
public function partnerType()
{
return $this->belongsTo('App\PartnerType');
}
Edit: PartnerType Model
public function partners()
{
return $this->hasMany('App\Partner');
}
Edit 2: Database
Partner(partnerID, name, partnerTypeId)
PartnerType(partnerTypeId, partnerTypeName)
Project(projectID, name)
Invoice(invoiceID, name, projectID, partnerID)
Expenses(expenseID, invoiceID)
If your models look like that.
Should be like :
$p = Project::with(['invoices' => function($query){
$query->where('partnerTypeName', 'Lieferant')
->with(['expenses','partner' => function($q){
$q->with('partnerType');
}]);
}])->where('id', $id)
->first();
return dd($p);
The solution to your problem is to update your query like this:
$p = Project::with(['invoices' => function($query){
$query->with('expenses')->whereHas('partner.partnerType', function($q){
$q->where('partnerTypeName', 'Lieferant');
});
}])
->where('id', $id)
->first();
But a cleaner solution would be using a scope for your problem.
In your Invoice model.
// Invoice.php
public function scopeByPartnerType($query, $partnerType)
{
$query->whereHas('partner.partnerType', function($q) use ($partnerType) {
$q->where('partnerTypeName', $partnerType);
});
}
And then in your Project model, add another relation that will just get Invoices with a particular partner type.
// Project.php
public function lieferantInvoices()
{
return $this->hasMany('App\Invoices')->byPartnerType('Lieferant');
}
Now you can do just this:
$project->find($id)->load('lieferantInvoices');

Laravel query order with order_details using id

Stuck on this.
I use this same query without Id to get all the successfully get all this data.
$orders = $this->order
->with('orderDetails', 'orderDetails.product')
->today()
->get();
Relationships
Order:
public function orderDetails(){
return $this->hasMany('App\OrderDetail', 'order_id');
}
OrderDetail:
public function order()
{
return $this->belongsTo('App\Order', 'order_id', 'id');
}
public function product()
{
return $this->belongsTo('App\Product', 'id_products', 'id');
}
But trying to use the same thing to get data for a particular order doesn't return the order_details.
public function invoice(Request $request, $id)
{
$ordered = $this->order
->find($id)
->with('orderDetails', 'orderDetails.product');
return response()->json($ordered);
}
Why is it behaving differently when passed an id?
When you use find the query is executed before other directives. You need to be using where:
$ordered = $this->order
->where('order_id', $id)
->with('orderDetails', 'orderDetails.product')
->get();
Try to use just this way:
$ordered = $this->order->find($id);
return response()->json($ordered);
The laravel already turned to relationships based on no mapping that you enter in the model.
In this case, your orderDetails in your response will look like this:
Order: {
Id: "1",
Xpto: "whatever",
OrderDetails: {
Id: "1"
}
}

Categories