How can I get property from Laravel Illuminate\Support\Collection? - laravel-5

I'm trying to property from collections, but I can't do this.
I have this query:
$calls = collect(
DB::select("SELECT count(id)
FROM calls
WHERE started_at >= '" . $date . "' AND
linked_id IS NULL") );
And as the result I got this
Illuminate\Support\Collection {#82146
all: [
{#1097
+"count": 15,
},
],
}
How can I get this "count"? I've tried to
$calls->count
$count = get_object_vars($calls)
but in first case I have:
PHP error: Undefined property: Illuminate\Support\Collection::$count on line 1
and in the second I got empty array.

First, Please give alias to "count(id) as calls_count"
Here is your query.
$calls = collect(DB::select("SELECT count(id) as calls_count FROM calls WHERE started_at >= '" . $date . "' AND linked_id IS NULL"));
Here are few ways to get value of count now.
1.)
echo $calls[0]->calls_count;
2.)
$calls = $calls->first();
echo $calls->calls_count;
3.)
echo $calls->pluck('calls_count')->first()
(I prefer this)
Hope this help, Let me know i comment, if any doubt.

Related

Codeigniter update_batch in Core PHP

everyone.
In the codeigniter there is update_batch function by using it we are able to bulk update multiple rows.
$this->db->update_batch('table_name', $update_data_array, 'where_condition_field_name');
I want similar functionality in core PHP in one function or in one file. Is there any workaround?
Is there any way to extract update_batch function from Codeigniter in one file/function?
I tried to extract this function but it is very lengthy process and there will be many files / functions should be extracted.
Please help me in this regard
Thanks in advance
You can also insert multiple rows into a database table with a single insert query in core php.
(1)One Way
<?php
$mysqli = new mysqli("localhost", "root", "", "newdb");
if ($mysqli == = false) {
die("ERROR: Could not connect. ".$mysqli->connect_error);
}
$sql = "INSERT INTO mytable (first_name, last_name, age)
VALUES('raj', 'sharma', '15'),
('kapil', 'verma', '42'),
('monty', 'singh', '29'),
('arjun', 'patel', '32') ";
if ($mysqli->query($sql) == = true)
{
echo "Records inserted successfully.";
}
else
{
echo "ERROR: Could not able to execute $sql. "
.$mysqli->error;
}
$mysqli->close();
? >
(2)Second Way
Let's assume $column1 and $column2 are arrays with same size posted by html form.
You can create your sql query like this:-
<?php
$query = 'INSERT INTO TABLE (`column1`, `column2`) VALUES ';
$query_parts = array();
for($x=0; $x<count($column1); $x++){
$query_parts[] = "('" . $column1[$x] . "', '" . $column2[$x] . "')";
}
echo $query .= implode(',', $query_parts);
?>
You can easily construct similar type of query using PHP.
Lets use array containing key value pair and implode statement to generate query.
Here’s the snippet.
<?php
$coupons = array(
1 => 'val1',
2 => 'va2',
3 => 'val3',
);
$data = array();
foreach ($coupons AS $key => $value) {
$data[] = "($key, '$value')";
}
$query = "INSERT INTO `tbl_update` (id, val) VALUES " . implode(', ', $data) . " ON DUPLICATE KEY UPDATE val = VALUES(val)";
$this->db->query($query);
?>
Alternatively, you can use CASE construct in UPDATE statement. Then the query would be something
like:
UPDATE tbl_coupons
SET code = (CASE id WHEN 1 THEN 'ABCDE'
WHEN 2 THEN 'GHIJK'
WHEN 3 THEN 'EFGHI'
END)
WHERE id IN(1, 2 ,3);

Wrong total pagination with select distinct in Laravel 6

I use Laravel 6.12, I have this request :
$queryJob = DB::table('jobs as j')->join('job_translations as jt', 'j.id', 'jt.job_id')
->whereNull('j.deleted_at')
->whereNull('jt.deleted_at')
->select('j.id', 'j.short_name', 'j.status', DB::raw("case when j.short_name = '{$request->short_name}' then 0 else 1 end"))
->distinct();
$jobs = $queryJob->paginate($qtyItemsPerPage);
The results displays an error for the total :
The total = 3, but as you can see the data contains only 2 elements.
I read here that when using a distinct, I must be clear on which column the total must be calculated: distinct() with pagination() in laravel 5.2 not working
So I modified my query like that:
$jobs = $queryJob->paginate($qtyItemsPerPage, ['j.*']);
But without success, the total is still wrong.
Hoping that I don't misunderstand your DB and relations structure and purpose of your query perhaps this will avoid using distinct or groupBy altogether?
$shortname = $request->input('short_name');
$queryJob = Job::with('job_translations')->select('id','short_name',
'status', DB::raw("case when short_name = '" . $shortname . "'
then 0 else 1 end")
->paginate($qtyItemsPerPage);
Pagination can be easily manually added with skip and take in case you need to use groupBy
$queryJob->skip(($page - 1) * $qtyItemsPerPage)->take($qtyItemsPerPage)->get();
The solution for me was to pass a field name to the distinct() method.
With your example:
$queryJob = DB::table('jobs as j')
// joins, where and other chained methods go here
->distinct('j.id')
Solution taken from https://stackoverflow.com/a/69073801/3503615

Laravel Eloquent how to query the avrege and compare it between two values

I am looking for a solution to filte jobs basing on the salary.
I have a Job model which has 2 column min_salary and max_salary, and the user is going to use a slider to pick two values as min and max salary.
I have tried the whereBetween and orWhereBetween but the problem is the query gets closed and I can't proceed with other filters, so am trying to get the average between the model min/max salary and use it instead of the two slaries.
Here's what i tried:
$salary = explode(',',$request->salary); // geting the salary range from the request as array
$jobs = Job::whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
This solution does not work as I want, as I can't proceed with other filters.
I also tried to do a custom orWhere function and do seperated whereBetween queries, but I got the same result.
What I am trying now is to get the average between the model max and min salary without creating another field*, and then proceed to do something like that :
$jobs = Job::whereBetween('theCalculatedAvg',$salary);
I appreciate any help with any kind of solution that does not require creating another field in the database, and i wont mind an sql raw solution if it does the job.
Thank you.
Update
Heres the whole function u had :
if($request->has('offset')) {
$salary = explode(',',$request->salary);
$jobs = Job::whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
if ($request->has('lat')) {
$sqlDistance = DB::raw
('
( 6371 * acos
( cos
( radians
(' . $request->lat . ')
)
* cos
( radians
( lat )
)
* cos
( radians
( lon )
- radians
(' . $request->lon . ')
)
+ sin
( radians
(' . $request->lat . ')
)
* sin
( radians
( lat )
)
)
)
');
$jobs->when($sqlDistance != null, function ($query) use ($sqlDistance,$request){
$query->whereHas('address', function ($subQuery) use ($sqlDistance,$request) {
$subQuery->addSelect(DB::raw("{$sqlDistance} AS distance"));
$subQuery->havingRaw("distance <= ?", [(int)$request->range]);
});
})
->with('company')
->with('address');
}
if ($request->has('key')) {
$jobs->where('title', 'like', '%' . $request->key . '%');
}
if ($request->has('cat')) {
$cat = explode(',',$request->cat);
$jobs->whereIn('category_id', $cat);
}
if ($request->has('type')) {
$type = explode(',',$request->type);
$jobs->whereIn('type', $type);
}
if($request->has('hs')) {
return view("General::browseJobs", [
'jobs' => $jobs->orderBy('created_at','desc')->skip($request->offset * 2)->take(2)->get(),
'count' => count($jobs->get())
]);
}
$view = view('General::loaders.jobs', [
'jobs' => $jobs->orderBy('created_at','desc')->skip($request->offset * 2)->take(2)->get()
])->render();
return response()->json(['html' => $view , 'count' => count($jobs->get()) ]);
}
return view("General::browseJobs", [
'jobs' => Job::orderBy('created_at','desc')->take(2)->get(),
'count' => count(Job::all())
]);
The issue is that i just want the salary filter to work this way:
lets say the user picked twho values : $min and $max (will be stored in an array)
now i want to show him the jobs where the min_salary is between [$min, $max]
or the max_salary is between [$min, $max].
NB : if i use :
Job::whereBetween('min_salary',$salary)->whereBetween('max_salary',$salary);
without the or it works just fine, but i want the or logic to be implemented.
You need to scope the or to those 2 conditions only:
Jobs::where(function ($q) use ($salary) {
$q->whereBetween('min_salary',$salary)->orWhereBetween('max_salary',$salary);
})
To understand why this is required, you need to consider the sql query produced by eloquent.
If you write:
$jobs = Jobs::where([condition1])->orWhere([condition2]);
.. some other code..
$jobs->where([condition3]);
...
$jobs->where([condition4]);
The resulting query will be:
SELECT *
FROM jobs
WHERE [condition1] OR [condition2] AND [condition3] AND [condition4]
But in SQL, the AND operator has precedence over the OR, so the conditions are logically considered like this:
([condition1]) OR ([condition2] AND [condition3] AND [condition4])
This is not the behavior you want.
By scoping the OR condition in a where closure, you basically tell eloquent to add a parenthesis around the conditions, so:
$jobs = Jobs::where(function ($q) {
$q->where([condition1])->orWhere([condition2]);
});
.. some other code..
$jobs->where([condition3]);
...
$jobs->where([condition4]);
Results in the following query:
SELECT *
FROM jobs
WHERE ([condition1] OR [condition2]) AND [condition3] AND [condition4]
which is the desidered one
Ok, thank you for updating the question. I'm pretty sure I'm not able to answer it in one go, but I'll do my best.
As far as I can see, you are working on a Job site where you want to allow users to enter filters, and only show jobs matching those filters.
I see you have filters for min/max salary, distance, title, categories and types.
You also have a hs key which decides which view to open with which data.
I would consider the min/max salary to be an OR statament, and the rest an AND.
In that case I would do
$mainQuery = Job::where(function($query) use($salary)
{
$query->whereBetween('min_salary', $salary)->orWhereBetween('max_salary', $salary);
});
So you can do $mainQuery->where('anothermust-have', $somevalue);

Laravel 5.6: how to create a subquery using Query Builder

I would like to reproduce following mySQL query using Laravel query builder:
*SELECT SUM(scores) FROM (SELECT scores FROM player_games WHERE player_id = 1 ORDER BY id DESC LIMIT 2) scores
Any suggestions?
Here the solution:
$sub = playerGame::where('player_id',1)->where('scores','>',0)->limit(2)->orderBy('id','desc');
$count = DB::table( DB::raw("({$sub->toSql()}) as sub") )
->mergeBindings($sub->getQuery())
->sum('scores');
return $count;
Use fromSub():
$sub = playerGame::select('scores')
->where('player_id', 1)
->where('scores', '>', 0)
->limit(2)
->orderBy('id','desc');
$sum = DB::query()->fromSub($sub, 'scores')->sum('scores');
$responce= DB::table('player_games')->where('player_id',1)->sum('amount');
dd(collect($responce)->sortByDesc('id')->take(2));
please cheack this one.....i try it's work....and add use DB;in the top of controller....

Doctrine create subquery with bound params

I am trying to construct a query that will basically pull all entries whose id's have 2 particular entries in another table so I am trying the below:
$query = $this->createQuery('e');
$subquery1 = $query->createSubquery('sea')
->select('sea.entry_id')
->from('Table sea')
->addWhere('sea.form_element_id = ?', $element)
->addWhere('sea.answer = ?', $answer)
->getDQL();
$subquery2 = $query->createSubquery('sea2')
->select('sea2.entry_id')
->from('Table sea2')
->addwhere('sea2.form_element_id = ?', $element2)
->addWhere('sea2.answer = ?', $answer2)
->getDQL();
$query->addWhere('e.id IN ?', $subquery1)
->addWhere('e.id IN ?', $subquery2);
return $query->execute();
However this is gives me an error on bound params.
What is the correct ways of constructing such subqueries?
NOTE that if I dont bind the params in the subqueries it works fine.
$nestedQuery = " id IN (SELECT sea.entry_id from table sea where sea.form_element_id = ? and sea.answer = ?) "
. " and id IN (SELECT sea2.entry_id from table sea2 where sea2.form_element_id = ? and sea2.answer = ?)";
return $this->findBySql($nestedQuery, array($param1, $param2, $param3, $param4));
That obviously returns a doctrine collection but you can do getFirst or loop through the returned objects or even use the Hydrator to get an array!

Resources