Search Query by Child field Eloquent relation - laravel

My Product Model is
public function IncomeRepo(){
return $this->hasMany(Income::class,'Product');
}
My Income Report Model Is
public function ProductData(){
return $this->belongsTo(Product::class,'Product','id');
}
My Query is
public function SearchIncomeData(Request $request){
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with('IncomeRepo')->whereBetween('created_at', [$GetFromDate, $GetToDate])->get();
return view('Admin.Report.ProductSalesReport',compact('ProductData'));
}
When I return $ProductData it return products table created_at Data. BUT I nee Income table created_at data which be multiple
How can I get it?
My expectation show incomes table created_at data

If you want to filter data by child tables date then you need to use whereHas relationship.
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with('IncomeRepo')
->whereHas('IncomeRepo',function($que) use($GetFromDate,$GetToDate) {
$que->whereBetween('created_at',[$GetFromDate, $GetToDate])})->get();
return view('Admin.Report.ProductSalesReport',compact('ProductData'));

In controller. (Use whereBetween)
public function SearchIncomeData(Request $request)
{
$GetFromDate = $request->FromDate;
$GetToDate = $request->ToDate;
$ProductData = Product::with(['IncomeRepo' => function ($query) use ($GetFromDate, $GetToDate)
{
$query->whereBetween('created_at', [$GetFromDate, $GetToDate]);
}
])->get();
return view('Admin.Report.ProductSalesReport', compact('ProductData'));
}
In view
foreach ($ProductData as $product)
{
foreach ($product->IncomeRepo as $income)
{
echo $income->created_at;
}
}

Related

Laravel Using nested with

I couldn't do what I wanted to do with Laravel, actually what I want to do is as follows,
I send getTruck id and list truckHistory with witdh, and I want to pull trukInvoice information with truckHistory invoice_id. But i am getting error where am i doing wrong?
Mysql Connection is as follows.
http://localhost:3000/truck/1
"trucks" table column "plate"
"invoice_details" column "plate_no"
"invoice_details" column "invoice_id"
"invoice" column "id"
Truck Controller
public function getTruck($id)
{
$truck = Truck::find($id)->with([
'truckHistory' => function($query){
// return $query->with(['trukInvoice']);
}
])->first();
return $truck;
}
Truck Model
public function companys()
{
return $this->belongsTo(Contact::class, 'company_id', 'id');
}
public function getCompanyNameAttribute()
{
return $this->companys()->first()->name;
}
public function truckHistory(){
return $this->hasMany(InvoiceDetail::class,'plate_no','plate');
}
public function trukInvoice(){
return $this->belongsTo(Invoice::class,'invoice_id','id');
}
Try this:
$truck = Truck::leftJoin('invoices', 'trucks.invoice_id', 'invoices.id')
->leftJoin('invoice_details', 'trucks.plate_no', 'invoice_details.plate')
->select('*')
->first();
or
$truck = Truck::with(['invoices' => function ($query) {
$query->whereHas('invoice_details', function ($q){
$q->whereNotNull('invoice_details.plate');
});
}])->first();
Check the documentation on restraining eager loads.

avoiding duplicated queries in job handle function

this handle function counts the number of available cities and areas to each state, then saves the results in a log file
need to avoid the duplicated queries in this function
public function handle()
{
$statesIds=State::pluck('id')->toArray();
foreach($statesIds as $stateId){
$statesIds=State::pluck('id')->toArray();
$statecitiesIds=City::where('stateId',$stateId)->pluck('id')->toArray();
$citiesAreasIds=Area::whereIn('cityId',$statecitiesIds)->pluck('id')->toArray();
$stateName=State::where('id',$stateId)->value('name');
Log::info($stateName.' had '.count($statecitiesIds).' cities and ' .count($citiesAreasIds) .' areas' );
}
}
}
You can use Eloquent: Relationships
https://laravel.com/docs/8.x/eloquent-relationships
$states = State::query()->with(['cities' => function($query) {
return $query->with('areas');
}]);
foreach ($states as $state) {
foreach ($state->city as $city) {
Log::info($state->name.' had '.count($state->cities).' cities and ' .count($city->areas) .' areas' );
}
}
And add relationships to your Model
// State Model
public function cities {
return $this->hasMany(City::class, 'stateId', 'id');
}
And City Model
// City Model
public function areas {
return $this->hasMany(Area::class, 'cityId', 'id');
}

Laravel Eloquent how to get all parents

I have relation like this:
DB relation
I have a code in my model that retrieves me just one parent:
public function AllParents()
{
return $this->belongsToMany($this, 'parent', 'product_id', 'parent_id')
->select('parent', 'name');
}
I get it in my controller like this:
private function product(Product $product)
{
return $product->Product()
->with('AllParents')
->get();
}
Finally I need data like this:
Product1/Product_2/Product_3
I think I need a loop, but how to do it in Eloquent?
Just change relationship. You have mentioned pivot table name wrong one.
public function AllParents()
{
return $this->belongsToMany(Product::class, 'Product_parent', 'product_id', 'parent_id') ->select('parent', 'name');
}
and then you can access
\App\Models\Product::with('AllParents')->get()
In your Product Model. You have define relationship like this.
public function allParents()
{
return $this->belongsToMany(Product::class, 'product_parents', 'product_id', 'parent_id')->select('name');
}
And, In Controller you can get all the parents with eager loading.
Product::with('allParents')->find($productId);
And, In View you can use foreach loop to iterate every parent object.
#foreach ($product->allParents as $parentProduct)
{{ $parentProduct->name }}
#endforeach
I did like this:
I modified my controller
private function product(Product $product)
{
$allParents = [];
$parent = null;
$parent->$product->Product()->with('AllParents')->first()->id;
while ($parent != null) {
array_push($allParents, Product::all->find($parent));
$parent = Product::all()->find($parent) - first();
}
}

Laravel, sort result on field from relation table?

I have a list with gamers and another table with game stats.
My list code is:
$gamers = Gamer::with(['lastGameStat' => function($query) {
$query->orderBy('total_points', 'DESC');
}])->paginate(20);
relation:
public function lastGameStat() {
return $this->hasOne(GameStat::class, 'gamer_id', 'id')->orderBy('created_at', 'DESC');
}
in relation table I have field: total_points and with this code I thought it's possible to sort list of gamers by total_points $query->orderBy('total_points', 'DESC');
It doesn't work, can somebody give me an advice here how can I sort the result on a field from relation table?
I guess you'll need either another relation or custom scopes to fetch various game stats of a gamer.
Second relation
Gamer.php (your model)
class Gamer
{
public function bestGameStat()
{
return $this
->hasOne(GameStat::class)
->orderBy('total_points', 'DESC');
}
}
Custom scopes
Gamer.php
class Gamer
{
public function gameStat()
{
return $this->hasOne(GameStat::class);
}
}
GameStat.php
use Illuminate\Database\Eloquent\Builder;
class GameStat
{
public function scopeBest(Builder $query)
{
return $query->orderBy('total_points', 'DESC');
}
}
In your controller:
$gamersWithTheirLatestGameStatistic = Gamer::with(['gameStat' => function($query) {
$query->latest();
}])->paginate(20);
$gamersWithTheirBestGameStatistic = Gamer::with(['gameStat' => function($query) {
$query->best();
}])->paginate(20);
Be aware as this is untested code and might not work.

how to check exist relation in eloquent query?

I am using the laravel polymorphic relation.
cartable model:
public function objectable()
{
return $this->morphTo();
}
instructions model:
public function cartable()
{
return $this->morphMany('PTA_OIMS\Cartable', 'objectable');
}
reports model:
public function reports()
{
return $this->morphMany('PTA_OIMS\Cartable', 'objectable');
}
My instruction table has extra related table called instruction_logs.
But in the reports table, this relationship does not exist.
When my object is report this query has error. Because the reports.report_logs does not exist.
$data = Cartable::where('id', '=', $cartableID)
->with('objectable')
->with('objectable.objectable_logs.attachment') //line error
->with('box.position')
->with('box.assign.staff')
->first();
return $data;
How to handle query if objectable_logs did not exist skip the line error?
$data = Cartable::with([
'objectable',
'objectable.objectable_logs.attachment',
'box.position',
'box.assign.staff'
])->find($cartableID);
return $data;
if attachment is a column in objectable_logs table, it should be like:
$data = Cartable::with([
'objectable',
'objectable.objectable_logs:objectable_id,attachment',
'box.position',
'box.assign.staff'
])->find($cartableID);
return $data;

Resources