Laravel with() Eloquent as variable or another array - laravel

I have this Eloquent query that want to display the orders by day, yesterday, week, last week, this month, last month, this year, last year and this is my code however, it does not work or do have any idea to re do the code. In my sample code I do not know how to put into another each with() query with different parameters. Please help.
$product_orders = Product::where('status', 'active')
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', today());
}])
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', Carbon::yesterday());
}])
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', [now()->startOfWeek(), now()->endOfWeek()]);
}])
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', [now()->subWeek()->startOfWeek(), now()->subWeek()->endOfWeek()]);
}])
->with(['order_detail' => function($query) {
$query->with('order');
$query->whereYear('created_at', '=', now()->year);
$query->whereMonth('created_at', '=', now()->month);
}])
->with(['order_detail' => function($query) {
$fromDate = Carbon::now()->subMonth()->startOfMonth()->toDateString();
$tillDate = Carbon::now()->subMonth()->endOfMonth()->toDateString();
$parse_fromDate = Carbon::parse($fromDate.' 00:00:00');
$parse_tillDate = Carbon::parse($tillDate.' 23:59:59');
$query->with('order');
$query->whereBetween('created_at',[$parse_fromDate,$parse_tillDate]);
}])
->with(['order_detail' => function($query) {
$query->with('order');
$query->whereYear('created_at', '>=', now()->year);
}])
->with(['order_detail' => function($query) {
$last_year = now()->year - 1;
$query->with('order');
$query->whereYear('created_at', '>=', $last_year);
}])
->get();

With this approach, you're essentially overwriting each "with" with the next one in the chain, so that the only thing that is actually executed is the final "with".
What you will need to do is break these into separate queries, with separate result sets, since, at the core you appear to want result from multiple different queries with different criteria.
$todays_orders = Product::where('status', 'active')
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', today());
}])
->get();
$yesterdays_orders = Product::where('status', 'active')
->with(['order_detail' => function($query) {
$query->with('order');
$query->where('created_at', '>=', Carbon::yesterday());
}])
->get();
... etc...

Use the query:
$product_orders = Product::where('status', 'active')
->with([ 'order_detail' => function ($query) {
$last_year = now()->year - 1;
$query->whereYear('created_at', '>=', $last_year);
}, 'order_detail.order' ])->get();
$product_orders->each(function (Product $product) {
$product->today_orders = $product->order_detail->where('created_at', '>=', Carbon::today());
$product->today_orders = $product->order_detail->whereBetween('created_at', [ Carbon::yesterday(), Carbon::today() ]);
$product->weeks_orders = $product->order_detail->whereBetween('created_at', [ Carbon::now()->startOfWeek(), Carbon::now()->endOfWeek() ]);
$product->last_weeks_orders = $product->order_detail->whereBetween('created_at', [ Carbon::now()->subWeek()->startOfWeek(), Carbon::now()->subWeek()->endOfWeek() ]);
// and so on
});
Then in your view each product should have properties that were set in the each

I found my own solution by creating it with filter inside the Model
in Controller
$product_orders = Product::where('status', 'active')
->with('order_detail_today', 'order_detail_yesterday', 'order_detail_this_week',
'order_detail_last_week','order_detail_this_month', 'order_detail_last_month',
'order_detail_this_year', 'order_detail_last_year')->get();
in Model
public function order_detail_today()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->where('created_at', '>=', today());
}
public function order_detail_yesterday()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->where('created_at', '>=', Carbon::yesterday());
}
public function order_detail_this_week()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->where('created_at', '>=', [now()->startOfWeek(), now()->endOfWeek()]);
}
public function order_detail_last_week()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->where('created_at', '>=', [now()->subWeek()->startOfWeek(), now()->subWeek()->endOfWeek()]);
}
public function order_detail_this_month()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->whereYear('created_at', '=', now()->year)
->whereMonth('created_at', '=', now()->month);
}
public function order_detail_last_month()
{
$fromDate = Carbon::now()->subMonth()->startOfMonth()->toDateString();
$tillDate = Carbon::now()->subMonth()->endOfMonth()->toDateString();
$parse_fromDate = Carbon::parse($fromDate.' 00:00:00');
$parse_tillDate = Carbon::parse($tillDate.' 23:59:59');
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->whereYear('created_at', '=', now()->year)
->whereBetween('created_at',[$parse_fromDate,$parse_tillDate]);
}
public function order_detail_this_year()
{
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->whereYear('created_at', '>=', now()->year);
}
public function order_detail_last_year()
{
$last_year = now()->year - 1;
return $this->hasMany('App\Order_detail','reference_number')
->where('order_type', '!=', 'package')
->with('order')
->whereYear('created_at', '>=', $last_year);
}

Related

Search result with multiple tables relation in Laravel6

I'm trying to make search function with relation.
I could display all result using relation And an another code, simple one table search and get result works fine.
but I can't combine those two.
Could you teach me how to combine multiple tables into search function please?
public function order(Request $request)
{
$data = $request->all();
$products = Product::All();
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->get();
$products = Product::when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})->
when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})->get();
//return view('result_fb', compact('images'));
$data = array(
'title' => 'index',
'no' => 1,
'products' => $products,
);
return view('product.result', $data);
}
I am not sure if you need 'categori' relation to be loaded or not as there are few $products without it. For general, you can combine all your $products queries to one as follows:
$products = Product::join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
If you want to use eager loading with eloquent rather then join, you can use like
$products = Product::with(['creator','categori','branch','user','color'])
->when($data['categori_id'], function ($query, $categori_id) use ($data) {
return $query->where('categori_id', $data['categori_id']);
})
->when($data['color_id'], function ($query) use ($data) {
return $query->where('color_id', $data['color_id']);
})->get();
But for that you Product model should have relations with same name as follows for categori relation:
class Product extends Model
{
public function categori()
{
return $this->belongsTo(Categori::class,'categori_id','id);
}
}
Same way you have to define for all relation used for product.
Try this:
$products = Product::with('categori')
->join('creators', 'creators.id', '=', 'products.creator_id')
->join('categoris', 'categoris.id', '=', 'products.categori_id')
->join('branches', 'branches.id', '=', 'products.br_id')
->join('users', 'users.id', '=', 'products.user_id')
->join('colors', 'colors.id', '=', 'products.color_id')
->when($data['categori_id'], function ($query, $categori_id) {
return $query->where('categori_id', $categori_id);
})
->when($data['color_id'], function ($query, $color_id) {
return $query->where('color_id', $color_id);
})
->get();

Querying a database relationship with carbon in laravel

I'm trying to select the picture with the most likes from a category the previous day. However, my query returns a null result. My pictures are related to the likes through a has many polymorphic relationship.
Here is my query:
$foodOfTheDay = Picture::withCount('likes')
->where('picture_type', 'food')
->whereHas('likes', function($query) {
$query->whereDate('created_at', Carbon::yesterday());
})
->orderBy('likes_count', 'desc')
->with('user')
->first();
Here is my likeable relationship:
public function likes()
{
return $this->morphMany('App\Like', 'likeable');
}
Thank you for your help.
Try this:
$foodOfTheDay = Picture::withCount('likes')
->where('picture_type', 'food')
->whereHas('likes', function($query) {
$query->whereBetween('created_at', [Carbon\Carbon::yesterday()->startOfDay(), Carbon\Carbon::yesterday()->endOfDay()]);
})
->withCount('likes') // count yesterday's likes
->orderBy('likes_count', 'desc')
->with('user')
->first();
or this:
$foodOfTheDay = Picture::withCount('likes')
->where('picture_type', 'food')
->whereHas('likes', function($query) {
$query->where('created_at', '>=', Carbon::yeserday()->startOfDay())
->where('created_at', '<=', Carbon::yesterday()->endOfDay());
})
->withCount('likes') // count yesterday's likes
->orderBy('likes_count', 'desc')
->with('user')
->first();
Both of them should return picture with the highest likes the previous day (yesterday)
This query selects the picture with most likes without taking into consideration the other days' likes:
$foodOfTheDay = Picture::where('picture_type', 'food')->withCount(['likes' => function($query) {
$query->whereBetween('created_at', [Carbon::yesterday()-
>startOfDay(), Carbon::yesterday()->endOfDay()]);
}])
->orderBy('likes_count', 'asc')
->with('user')
->first();

Orderby Desc in Eloquent, Laravel

I have a query 3 tables are joined together, I want to order the results in Descending order from created_at in messages table, please help. Thank you.
controller:
return new AllChats(Chat::latest('created_at')->whereHas('messages')->with(['messages.users', 'users' =>
function ($query) {
$query->where('id', '!=', Auth::id());
}])->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
Display the results in desc order but from messages.created_at??
You need to just add the ->orderBy on your created at field in your query.
return new AllChats(Chat::latest('created_at')->whereHas('messages')->with(['messages.users',
'users' => function ($query) {
$query->where('id', '!=', Auth::id());
}])
->orderBy('created_at', 'desc')
->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
Reference: https://laravel.com/docs/5.7/eloquent
use like this
return new AllChats(Chat::latest('created_at')>>whereHas('messages',function($q){
$q->orderBy('created_at', 'desc');
})->with(['messages.users', 'users' =>
function ($query) {
$query->where('id', '!=', Auth::id());
}])->whereHas('users', function ($query) {
$query->where('id', '=', Auth::id());
})->get());
You can use a modified withCount():
$chats = Chat::withCount(['messages as latest_message' => function($query) {
$query->select(DB::raw('max(created_at)'));
}])
->orderByDesc('latest_message')
[...]
->get();

Laravel query with relationships and conditions

Hi I have 3 tables in DB. Here is my query:
$nav = PageNav::with([
'page' => function($query) {
$query->where('status', 1)
->where(function($query) {
$query->whereNull('publish_up')
->whereNull('publish_down');
})
->orWhere(function ($query) {
$query->where('publish_up', '<', date('Y-m-d H:i:s'))
->where('publish_down', '>', date('Y-m-d H:i:s'));
});
},
'langs' => function ($query) use ($lang) {$query->where('language_code', '=', $lang);},
])
->get();
It generates this queries:
When I loop $nav there are still pages with status = 0. I really don't understand why? Any suggestions?
As with any SQL query or Eloquent query, OR completely separates the conditions, so as soon as you have an orWhere in eloquent, it will match anything that matches before the OR or after the OR.
You can resolve this by using a nested where, or parentheses in SQL, to properly encapsulate the conditions.
$query->where('status', 1)
->whereNested(function($q1) {
$q1->where(function($query) {
$query->whereNull('publish_up')
->whereNull('publish_down');
})
->orWhere(function ($query) {
$query->where('publish_up', '<', date('Y-m-d H:i:s'))
->where('publish_down', '>', date('Y-m-d H:i:s'));
});
});
Ok I found solution. Needed to wrap condition to whereHas
$nav = PageNav::whereHas('page', function ($query) {
$query->where('status', 1)
->whereNested(function($q1) {
$q1->where(function($query) {
$query->whereNull('publish_up')
->whereNull('publish_down');
})
->orWhere(function ($query) {
$query->where('publish_up', '<', date('Y-m-d H:i:s'))
->where('publish_down', '>', date('Y-m-d H:i:s'));
});
});
})
->with([
'page',
'langs' => function ($query) use ($lang) {
$query->where('language_code', '=', $lang);
}
])
->get();

Laravel 4 advanced wheres

I have my query working perfectly in mySQL, however am struggling to use the advanced wheres inside the laravel query builder.
Can anyone assist in converting this at all?
So far I have:
LARAVEL
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events= DB::table('events')
->where('hotel_id', 4)
->orWhere(function($query)
{
$query->where($start_request, '<=', 'start_time')
->where($end_request, '>', 'start_time');
})
->orWhere(function($query)
{
$query->where($start_request, '>=', 'start_time')
->where($end_request, '<', 'end_time');
})
->get();
mySQL
SELECT id, title, description, start_time, end_time FROM events where hotel_id = 4 and (('2014-12-18 09:00' <= start_time and '2014-12-18 10:00' > start_time)
or ('2014-12-18 09:00' >= start_time and '2014-12-18 10:00' < end_time));
Can you try this?
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events= DB::table('events')
->where('hotel_id', 4)
->where(function($query) use($start_request, $end_request) {
$query->where(function($subquery) use($start_request, $end_request){
$subquery->where('start_time', '>=', $start_request)
->where('start_time', '<', $end_request);
});
$query->orWhere(function($subquery1) use($start_request, $end_request) {
$subquery1->where('start_time', '<=', $start_request)
->where('end_time', '>', $end_request);
});
})
->get();
Something like this should do the job:
$start_request = '2014-12-18 09:00';
$end_request = '2014-12-18 10:00';
$events = DB::table('events')
->where('hotel_id', 4)
->where(function ($q) use ($start_request, $end_request) {
$q->where(function ($query) use ($start_request, $end_request) {
$query->where($start_request, '<=', 'start_time')
->where($end_request, '>', 'start_time');
})
->orWhere(function ($query) use ($start_request, $end_request) {
$query->where($start_request, '>=', 'start_time')
->where($end_request, '<', 'end_time');
});
})
->select('id', 'title', 'description', 'start_time', 'end_time')
->get();

Resources