Laravel Pagination with array_merge - php

I have 2 table which name incomes and expenses and I want to show all the data in one view with laravel pagination. For this, I Merged two array with array_merge().
$incomes = Income::where('user_id', Auth::User()->id)->get()->toArray();
$expenses = Expense::where('user_id', Auth::User()->id)->get()->toArray();
foreach ($incomes as $key => $value) {
$incomes[$key]['type'] = 'income';
}
foreach ($expenses as $key => $value) {
$expenses[$key]['type'] = 'expense';
}
$results = array_merge($incomes, $expenses);
How can I paginate this $results?

You can do this in two ways:
Laravel's built in manually creating a paginator functionality.
Get the results from tables using UNION.
Using UNION
$incomes = Income::where('user_id', Auth::User()->id);
$data = Expense::where('user_id', Auth::User()->id)->union($incomes)->paginate(10);
For manually creating a paginator, please see https://laravel.com/docs/6.x/pagination#manually-creating-a-paginator
Add the following to Income Model
protected $appends = ['type'];
public function getTypeAttribute()
{
return 'Income';
}
Add the following to Expense Model
protected $appends = ['type'];
public function getTypeAttribute()
{
return 'Expense';
}
This will add the type key in the query results.

Related

Building an array in nested foreach loops in Laravel controller

I am trying to build an array of user ids from a long eloquent relationship, using nested foreach loops in a Laravel controller, but can't get it to work.
Users can have publishers, those publishers can have teams and each team has members. Users can be in multiple teams so I also need to remove duplicate IDs.
I want to end up with a count to see how many team members are associated with a user.
In my user model
public function publishers()
{
return $this->belongsToMany('App\Publisher')->withTimestamps();
}
In my publisher model
public function teams()
{
return $this->belongsToMany('App\Team')->withTimestamps();
}
and in my team model
public function members()
{
return $this->belongsToMany('App\User')->withPivot('status', 'title', 'team_role_ids')->withTimestamps();
}
and in my profile controller
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds[] = $publisherTeam->members->pluck('id')->toarray();
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);
But I'm getting multiple arrays and not just one compiled array and the count isn't working. Any idea what I'm doing wrong?
You are assigning a new array into $teamUserIds each iteration. That's why you are getting multiple arrays.
$teamUserIds = [];
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds, $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);
you are adding arrays of id $publisherTeam->members->pluck('id')->toarray(); as a new index in $teamUserIds . but what you want to do is to merge the array of ids
so your code would be like this :
foreach ($user->publishers as $userPublisher) {
foreach ($userPublisher->teams as $publisherTeam) {
$teamUserIds = array_merge($teamUserIds , $publisherTeam->members->pluck('id')->toarray());
}
}
$deDupedIds = array_unique($teamUserIds, SORT_NUMERIC);
$idsCount = count($deDupedIds);

Laravel Eloquent groupBy to return one title of each group

I have a very complex issue, I want to show items under one title if title is the same for every item, Im new to Laravel and dont know how to do this, I hope there is a real soution for this issue, below screen shot of the result, please help me in a very detailed solution to solve this issue, im suffering since a week to solve it but cant do this
screen shot:
https://imgur.com/IOLGpzU
Tables:
https://imgur.com/AbVNDqP
https://imgur.com/kQTzQA2
https://imgur.com/brGYl54
https://imgur.com/oLXjGl9
Controller:
$customizeorders = OrderCustomize::where('userorder_id',$order_number)->with('customizeproduct')->get()->groupBy('customizetitle_id');
OrderCustomize Model:
protected $table = "ordercustomizes";
protected $fillable = [
'customizeproduct_id',
'userorder_id',
'product_id'
];
public function customizeproduct()
{
return $this->belongsTo(CustomizeProduct::class);
}
CustomizeProduct Model:
protected $table = "customizeproducts";
protected $fillable = [
'customizetitle_id',
'product_id',
'selection_type',
'selection_number',
'customize_title',
'customize_price'
];
public function customizetitle()
{
return $this->belongsTo(CustomizeTitle::class);
}
Blade:
#if(count($customizeorders)>0)
#foreach ($customizeorders as $customizetitle => $groupCustomizes)
#foreach($groupCustomizes as $key=>$customize)
#if(($userorder->product_id)==($customize->product_id))
<div>{{$customize->customizeproduct->customizetitle->name}}:</div>
{{$customize->customizeproduct->customize_title}} .
#endif
#endforeach
#break
#endforeach
#endif
//you need to create array to store the array of items having same title.
//i guess the item having same title also have same id.
Then you should use order by id not group by.
//it will provide you the data of same id in the conitnuous queue
//then you can use foreach loop to push the group of items in array and wrap that array with another array.
//so that you can push that in view. then you can loop through the array in view get the desired data.
//here in this method it have check if the items belongs to previous items or not using the $previousItem variable
public function show_device_report(Request $request)
{
//store the overall report.
$wholeData = [];
//stores the individual wrapper.
$wrapper = [];
//getting the id for the first items in the list
$previousItem = $datas[0]->id;
//transforming the values before sending to the view by
foreach ($datas as $data) {
//store the report of every items
$singleItem = [];
if ($data->id == $previousItem) {
$id = $data->id
//get all the item you need and push in the array.
array_push($singleItem, $id, $name, $etc);
array_push($wrapper, $singleItem);
} else {
$previousItem = $data->id;
array_push($wholeData, $wrapper);
//set the wrapper to null so that it can store the another items group in another index.
$wrapper= [];
}
return $wholeData ;
}
You need to modify little code according to your needs. As there is no any table structure provided by you.
store the individual item in singleItem[], then store all the single items in wraper[], and all the wraper[] in wholedata[]. Send wholedata[] to the view.
whole[
[wrapper1[item1,item2,item3]],
[wrapper2[item1,item2,item3,item4]],
[wrapper3[item1,item2]],
]

How can I group multiple columns into an object when making a database call in Laravel?

Let's say I am fetching users
Each user has 10 columns associated with it
How can I group 5 columns together into an object on each user so I can more easily map over them with javascript?
I could do
foreach ($users as $user)
{
$user['new_object']['col_1'] = $user->col_1;
unset($user->col_1);
$user['new_object']['col_2'] = $user->col_2;
// etc
}
But surely there is a way to group columns into an object on Laravel?
For example, something like
$users = User::where('verified', 1)
->group('new_object', ['col_1', 'col_2', 'col_3']),
->get();
Or is there a way for me to update my User model to do this?
you can do something like this:
$users = User::where('verified', 1)->get()->map(function($row)
{
$row->new_obj = [$row->col1, $row->col2, $row->col3];
unset($row->col1, $row->col2, $row->col3);
return $row;
});
You can use mutators in your model:
public function getNewObjAttribute() {
return [
$this->col1,
$this->col2,
$this->col3,
];
}
And in $appends attribute inside that model:
protected $appends = [
'new_obj',
];

Laravel relationship query where using array

I'm trying to return all the attributes from my database that have a set foreign key (Attribute groups). I've set up all the relationships in my model but I'm unsure how to query these relationships using a collection or array.
AttributeGroup -
public function attribute()
{
return $this->hasMany('App\Attribute', 'group_id');
}
Attribute -
public function attributeGroup()
{
return $this->belongsTo('App\AttributeGroup');
}
My current query -
$page = Page::where('slug', $slug)->firstOrFail();
$groups = AttributeGroup::where('page_id', $page->id)->get()->toArray();
$atts = Attribute::where('group_id', $groups[0]['id'])->get();
This works because we have set the specific index of the array using $groups[0]
Is there a simple way I can pass an array through to the query using their relationships or is looping through the results and then passing my own array to the query the best approach?
$attributes = array();
foreach ($groups as $group){
array_push($attributes, $group['id']);
}
$atts = Attribute::where('group_id', $attributes)->get();
$groups is a collection. Assume them as arrays on steroids. Therefore you can use the pluck() method to get those ids you need:
$page = Page::where('slug', $slug)->firstOrFail();
$groups = AttributeGroup::where('page_id', $page->id)->get();
$atts = Attribute::where('group_id', $groups->pluck('id'))->get();
Also if you've set your relationships correctly, you should be able to loop through $groups and access the attributes of those $groups. You can test it:
$groups = AttributeGroup::where('page_id', $page->id)->get();
dd($groups->first()->attributes);

Laravel: Count number of rows in a relationship

I have the following relationship:
A venue has many offers
A offer has many orders
I have the following Eloquent model to represent this:
class Venue {
public function orders()
{
return $this->hasManyThrough(Order::class, Offer::class);
}
}
I want to determine the total number of orders for venues with location_id = 5 using Laravel's Eloquent model.
The only way I managed to do this is as follows:
$venues = Venue::where('location_id', 5)->with('orders')->get();
$numberOfOrders = 0;
foreach($venues as $venue) {
$numberOfOrders += $venue->orders->count();
}
dump($numberOfOrders); // Output a single number (e.g. 512)
However, this is obviously not very efficient as I am calculating the count using PHP instead of SQL.
How can I do this using Eloquent model alone.
You can use Eloquent. As of Laravel 5.3 there is withCount().
In your case you will have
$venues = Venue::where('location_id', 5)->with('orders')->withCount('orders')->get();
Then access it this way
foreach ($venues as $venue) {
echo $venue->orders_count;
}
Can find reference here: https://laravel.com/docs/5.3/eloquent-relationships#querying-relations
$venues = Venue::with([
'orders' => function ($q) {
$q->withCount('orders');
}
])->get();
then use it this way for getting single record
$venues->first()->orders->orders_count();
Alternatively, you can use this way too for collections
foreach($venues as $venue)
{
echo $venue->order_count;
}
If you are using Laravel 5.3 or above you can use withCount.
If you want to count the number of results from a relationship without
actually loading them you may use the withCount method, which will
place a {relation}_count column on your resulting models. For example:
$venues = Venue::withCount(['orders'])->get;
foreach ($venues as $venue) {
echo $venue->orders_count;
}
You can read more about withCount in the Laravel Documentation.
If you are using lower than 5.3, you can make a custom relation on your Venue model:
public function ordersCount()
{
return $this->belongsToMany('App\Models\Order')
->selectRaw('venue_id, count(*) as aggregate_orders')
->groupBy('venue_id');
}
public function getOrderCount()
{
// if relation is not loaded already, let's do it first
if (!array_key_exists('ordersCount', $this->relations)) {
$this->load('ordersCount');
}
$related = $this->getRelation('ordersCount')->first();
// then return the count directly
return ($related) ? (int) $related->aggregate_orders : 0;
}
which can then be used as: Venue::with('ordersCount');. The benefit of this custom relation is you only are querying the count rather than the querying all of those relations when they are not necessary.

Categories