How would I refactor the code below so that there is only one reject function not two and have only one call to the db instead of three. I am also trying to not have any duplicates.
$latestListings = $repo->whereExclusive(['property_status' => 'Active'],['created_at' => 'desc'],[],0, 4);
$latestListingsIds = $latestListings->map(function (Listing $listing) {
return $listing->id;
})->toArray();
$highCflListings = $repo->whereExclusive(['property_status' => 'Active'],['cfl' => 'desc'],[],0, 4);
$highCflListingIds = $highCflListings->map(function (Listing $listing) {
return $listing->id;
})->toArray();
$highCflListingsOccupied = $repo->whereExclusive(
['property_status' => 'Active', 'occupied_percentage' => 100],
['cfl' => 'desc'],
[],
0,
12
)->reject(function (Listing $listing) use ($latestListingsIds) {
return in_array($listing->id, $latestListingsIds);
})->reject(function (Listing $listing) use ($highCflListingIds) {
return in_array($listing->id, $highCflListingIds);
})->take(4);
I don’t know how you’re setting $latestListingsIds and $highCflListingIds but if these are just arrays of IDs, combine them and reject on those:
$exclude = $latestListingsIds + $highCflListingIds;
$highCflListingsOccupied = $repo->whereExclusive(['property_status' => 'Active', 'occupied_percentage' => 100], ['cfl' => 'desc'], [], 0, 12)
->reject(function (Listing $listing) use ($exclude) {
return in_array($listing->id, $exclude);
})
->take(4);
Related
I have one array which contains all the records. I am passing all those records to a loop and there I am getting the sum of the clear column which has null upto.
This part is working fine, now my requirement is I want to add one more check which is based on the one more column refund.
If any column contains refund=1 that amount should be subtracted from the total, can you please help me to achieve the scenario
foreach ($row_data as $key => $value) {
$data_arr[$key]['total'] = ['Price'=> $value->whereIn('clear', null)->sum('amount')];
}
Data
data = [
{'amount' => 55, 'clear' => 'null', 'refund' => '0'},
{'amount' => 5, 'clear' => 'null', 'refund' => '1'},
{'amount' => 10, 'clear' => 'null', 'refund' => '0'},
];
Expected result is :-60
ACtual Result is :- 70
reduce should help.
$data = [
['amount' => 55, 'clear' => null, 'refund' => '0'],
['amount' => 5, 'clear' => null, 'refund' => '1'],
['amount' => 10, 'clear' => null, 'refund' => '0'],
];
You can be very explicit
// sum if refund is 0, substract if refund is 1
$sum = collect($data)
->where('clear', null)
->reduce(function ($carry, $item) {
if ($item['refund'] == '0') {
return $carry + $item['amount'];
} elseif ($item['refund'] == '1') {
return $carry - $item['amount'];
}
}, 0);
Or write it a bit shorter
// sum if refund is 0, substract otherwise
$sum = collect($data)
->where('clear', null)
->reduce(fn($carry, $item) => ($item['refund'] == '0')
? $carry + $item['amount']
: $carry - $item['amount']);
You can even do it without collections using php's array_reduce and array_filter functions. Works pretty much in the same way.
$sum = array_reduce(
array_filter($data, function ($item) {
return $item['clear'] == null;
}),
function($carry, $item) {
return $item['refund'] == '0'
? $carry + $item['amount']
: $carry - $item['amount'];
});
$sum = array_reduce(
array_filter($data, fn($item) => $item['clear'] == null)
fn($carry, $item) => $item['refund'] == '0'
? $carry + $item['amount']
: $carry - $item['amount']
);
I don't have all your code with variable declaration so I created logic snippet with your use case.
EDIT: You can simply get your total amount and substract you total refund as you can see in code below
/** #var Collection $data */
$data = collect([
['amount' => 55, 'clear' => null, 'refund' => false],
['amount' => 5, 'clear' => null, 'refund' => true],
['amount' => 10, 'clear' => null, 'refund' => false],
]);
$totalAmount = $data->whereNull('clear')->sum('amount');
$totalRefund = $data->whereNull('clear')
->where('refund', true)
->sum('amount'); // = 5
$subValue = $totalAmount - $totalRefund
Basically, I have an array of $course_id. I want to save multiple times according to number of $course_id
Here is my code:
$courselist[] = new Courselist;
for($i=0;$i<count($course_id);$i++)
{
$comparelist = Courselist::select('course_id','internal','external')
->where('course_id','=',$course_id[$i])
->get();
if($comparelist->isEmpty())
{
$courselist[$i]->course_id = $course_id[$i];
$courselist[$i]->internal = $internal;
$courselist[$i]->external = $external;
$courselist[$i]->save();
}
}
Does anyone know how can I save this?
you can use updateOrCreate() function like this
for ($i = 0; $i < count($course_id); $i++) {
Courselist::updateOrCreate([
['course_id' => $course_id[$i]],
[
'internal' => $internal,
'external' => $external
],
]);
}
ref link https://laravel.com/docs/8.x/eloquent#upserts
I use insert() function and it works
for($i=0;$i<count($course_id);$i++)
{
$data[] = array(
'course_id' => $course_id[$i],
'internal' => $internal,
'external' => $external
);
}
Courselist::insert($data);
I have small Laravel project working on collection editing. I have eloquent as below.
public function Import(){
$org = LabGroup::get();
return $org;
}
The returned result as below,
[
{
id: 1,
uuid: "491cd440-79d0-11e9-a294-b93a2fd40038",
branch: 0,
name: "productA",
},
{
id: 2,
uuid: "491d0b70-79d0-11e9-aba8-4d9cdb66858f",
branch: 0,
name: "productB",
},
{
id: 3,
uuid: "491d0c20-79d0-11e9-a243-0d208e55c95a",
branch: 0,
name: "productC",
}
]
My need is to change all branch value from 0 to 1. I can do by loop through but I may use other better like 'map' that I'm not familiar. Any advise or guidance would be greatly appreciated, Thanks.
You can use map() in this way:
$org = LabGroup::get();
$org_branch_1 = $org->map(function ($item, $key) {
return [
'id' => $item->id,
'uuid' => $item->uuid,
'branch' => 1,
'name' => $item->name,
];
});
return $org_branch_1;
If you don't need the original collection you can use transform() in the same way:
$org = LabGroup::get();
return $org->transform(function ($item, $key) {
return [
'id' => $item->id,
'uuid' => $item->uuid,
'branch' => 1,
'name' => $item->name,
];
});
EDIT:
This will work too:
return LabGroup::get()->transform(function ($item, $key) {
$item->branch = 1;
return $item;
});
You can use eloquent update() method on your query:
$updatedOrg = LabGroup::get()->update(['branch' => 1]);
return $updatedOrg; \\Returns the result with the updated branch value.
I have a sql request concerning admin :
$admin = Admin::findOrFail(Auth::guard('admin')->user()->id);
from this sql request I also manage to get the users of the admin ...
$users = $admin->users;
Each users must follow training sessions. and I must calculate it by using SQL requests for each users ... So i wrote this foreach statement
foreach ($users as $user) {
$todo = User::select() .....where('users.id' = $user->id)->get();
$done = User::select() .....where('users.id' = $user->id)->get();
$totalTimes = $todo->toBase()->sum('dureeformation');
$spendTimes = $done->toBase()->sum('dureeformation');
$remainingTimes = $totalTimes - $spendTimes;
$timeData[] = ['id' => $user->id, 'totalTime' => $totalTimes, 'spendTime' => $spendTimes, 'remainingTime' => $remainingTimes];
}
the totalTimes, spendTimes and remainingTimes are operations on Collections and i get expected results ...
$users->each(function ($record) use ($timeData) {
$record['totalTime'] = $timeData[$record['id']]['totalTime'];
$record['spendTime'] = $timeData[$record['id']]['spendTime'];
$record['remainingTime'] = $timeData[$record['id']]['remainingTime'];
//dd($record['totalTime']);
});
After this :
$timeData = collect($timeData);
$timeData= $timeData->keyBy('id');
$users = collect($users->toArray());
I have an issue here :
$users->each(function ($record) use ($timeData) {
$record['totalTime'] = $timeData[$record['id']]['totalTime'];
$record['spendTime'] = $timeData[$record['id']]['spendTime'];
$record['remainingTime'] = $timeData[$record['id']]['remainingTime'];
//var_dump($record);
});
$record in the function gives me what i expect ... the var_dump($records) added columns where it was expected but i can't take those results out of the function.
I tried to do this :
$variable = $users->each(function ($record) use ($timeData)...
dd($variable)
but unsuccessfully ...
Looks to me like your $timeData array is built differently than you access it. In your code you are doing
$timeData[] = [
'id' => $user->id,
'totalTime' => $totalTimes,
'spendTime' => $spendTimes,
'remainingTime' => $remainingTimes,
];
which will produce an array like this
[
0 => [
'id' => 17,
'totalTime' => 5,
'spendTime' => 4,
'remainingTime' => 3
],
1 => [
'id' => 17,
'totalTime' => 7,
'spendTime' => 5,
'remainingTime' => 2
]
]
but what you actually want is to have the id as index, right? Then you'd have to build the array this way:
$timeData[$user->id] = [
'totalTime' => $totalTimes,
'spendTime' => $spendTimes,
'remainingTime' => $remainingTimes,
];
or, as an alternative, perform a different lookup:
$users->each(function ($record) use ($timeData) {
$times = array_first($timeData, function ($value, $key) use ($record) {
return $value['id'] === $record['id'];
});
$record['totalTime'] = $times['totalTime'];
$record['spendTime'] = $times['spendTime'];
$record['remainingTime'] = $times['remainingTime'];
});
Both solutions have pros and cons, though. On the one hand, using the user identifier as the index will produce a huge array that is only filled partially. On the other hand, the second solution is a bit slower. As long as you are not going to deal with thousands of entries in the $timeData array, this won't be an issue, though.
I am having some trouble querying some data in Laravel.
I start my query doing the following:
$query = User::whereRole('advertiser');
When I query for example $usersall = $query->whereHave_pics('1')->get();
Then I also get users that have 0 in have_pics
The $query can consist of a long string of where queries that are dynamic depending on the users choices. Some of these where queries, the users that have 0 in have_pics do qualify for, but when I end the query with whereHave_pics('1'), shouldn't I only get the users that have '1' in Have_pics?
What I am wondering, is, if there is a max number of steps that laravel can handle in the query builder?
For example, if I but whereHave_pics('1') at the beginning of the query, like this:
$query = User::whereRole('advertiser')->whereHave_pics('1');
/* More queries are added */
$usersall = $query->get();
Then it completely ignores the whereHave_pics but not the whereRole...
If I do it at the end of the query, like this:
$query = User::whereRole('advertiser');
/* More queries are added */
$usersall = $query->whereHave_pics('1')->get();
Then it is dependent on the users choices that also creates queries.
I have been trying a ton of different work arounds, like changing the query model, e.g. instead of whereHave_pics('1') I have done where('have_pics', '1') or where('have_pics', true) etc.
I have no idea what to try next.
This is the complete function, that queries the users
public function search_adv(Request $request, $locale = 'dk') {
App::setLocale($locale);
$hair_queries = [
['input' => 'blonde', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'brown', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'red', 'operator' => '=', 'field' => 'haircolor'],
['input' => 'dark', 'operator' => '=', 'field' => 'haircolor'],
];
$eye_queries = [
['input' => 'green', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'brown', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'blue', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'hazel', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'silver', 'operator' => '=', 'field' => 'eyecolor'],
['input' => 'amber', 'operator' => '=', 'field' => 'eyecolor'],
];
$query = User::whereRole('advertiser');
/* HAIRCOLOR */
$hair = 0;
foreach($hair_queries as $filter) {
if($hair == 0) {
if(!empty($request->input($filter['input']))) {
$query = $query->where(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
if(!empty($request->input($filter['input']))) {
$hair++;
}
}
if ($hair >= 2) {
foreach($hair_queries as $filter){
if(!empty(request()->input($filter['input']))){
$query = $query->orWhere(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
}
/* END HAIR COLOR */
/* EYECOLOR */
$eye = 0;
foreach($eye_queries as $filter) {
if($eye == 0) {
if(!empty($request->input($filter['input']))) {
$query = $query->where(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
if(!empty($request->input($filter['input']))) {
$eye++;
}
}
if ($eye >= 2) {
foreach($eye_queries as $filter){
if(!empty(request()->input($filter['input']))){
$query = $query->orWhere(
$filter['field'],
$filter['operator'],
$filter['input']
);
}
}
}
/* END EYE COLOR */
$usersall = $query->whereHave_pics('1')->get();
return view('search', compact('usersall'));
}
The problem is you need to understand how where chaining and orWhere chaining works in Laravel.
When you say $query->where(..a..)->orWhere(..b..)->where(..c..)->orWhere(..d..) it will evaluate to: (a || (b && c) || d). Where you may have intended ((a || b) && (c || d)) or you may have intended ((a && c) || b || d). This is why when you need advanced where clauses, use where closures and parameter grouping