Two variable in one one variable - php

I have two queries.
$createdServer = Server::where('created_at', '>=', \Carbon\Carbon::now()->subMonth())
->selectRaw('COUNT(id) as createserver, DATE(created_at) as date,DAY(created_at) as day')
->groupBy('day', 'date')
->orderBy('date', 'ASC')
->orderBy('day', 'ASC')
->get();
$deletedServer = Server::where('deleted_at', '>=', \Carbon\Carbon::now()->subMonth())
->selectRaw('COUNT(id) as deleteserver, DATE(deleted_at) as date,DAY(deleted_at) as day')
->groupBy('day', 'date')
->orderBy('date', 'ASC')
->orderBy('day', 'ASC')
->onlyTrashed()
->get();
The output is:
"deletedServer": [
{
"deleteserver": 1,
"date": "2019-04-29",
"day": 29
}
],
"createdServer": [
{
"createserver": 2,
"date": "2019-04-29",
"day": 29
}
],
My requirement is:
"allServer": [
{
"deleteserver": 1,
"createserver": 2,
"date": "2019-04-29",
"day": 29
}
],
deleteServer and createServer count data in database.

You can retrieve with below code:
$allSevers = collect([
"deleteserver" => $deleteServer->count(), // retrieving the deleteServer count
"createserver" => $createServer->count(), // retrieving the createServer count
"date" => date('Y-m-d'), //date format in Year - Month - Date
"day" => date('j') // date format for mday
]);

merge function would solve the issue in your current case: link
$merged = $createdServer->merge($deletedServer);
$merged->all();
Edit:
$merged = $createdServer[0]->merge($deletedServer[0]);
$merged->all();

Related

Laravel get sums from models with two and more joins

I want to get the sum of prices from contract table and sum of transactions together connected to user id. And how can i use where in this.
Table Contracts:
[
{
"id": 1,
"user_id":97,
"price":"100"
},
{
"id": 2,
"user_id":97,
"price":"200"
},
{
"id": 3,
"user_id":97,
"price":"300"
}
]
Table Transactions:
[
{
"id": 1,
"user_id":97,
"sum":"100"
},
{
"id": 2,
"user_id":97,
"sum":"200"
},
{
"id": 3,
"user_id":97,
"sum":"300"
}
]
My query:
$query = User::where([
['contracts_sum', '<', 'transactions_sum'],
])
->join('contracts', 'contracts.user_id', '=','users.id')
->join('transactions', 'users.id', '=','transactions.user_id')
->groupBy(['users.id'])
->select(
'users.id', 'users.name',
DB::raw('SUM(contracts.price) AS contracts_sum'),
DB::raw('SUM(transactions.sum) AS transactions_sum'),
)
->get();
But this variant returns sum multiplied to count of transactions table rows like this:
[
{
"id":97,
"name":"JOHN",
"contracts_sum":"1800",
"transactions_sum":"1800"
}
]
But i would like to get the data in this kind of form:
[
{
"id":97,
"name":"JOHN",
"contracts_sum":"600",
"transactions_sum":"600"
}
]
My advice would be to make use of laravel's relation feature, as it would make it a lot easier.
class User
{
public function transactions()
{
return $this->hasMany(Transaction::class, 'user_id', 'id');
}
public function contracts()
{
return $this->hasMany(Contract::class, 'user_id', 'id');
}
}
Then, in your controller, you could do the following:
$user = User::where('id', 97)
->withSum('contracts', 'price')
->withSum('transactions', 'sum')
->get();
return [
'id' => $user->id,
'name' => $user->name,
'contracts_sum' => $user->transactions_sum_sum,
'transactions_sum' => $user->contracts_sum_price
];
Not only does this look a lot cleaner, the query will be more efficient as well. More information on the aggregate functions can be found in the laravel documentation.

How to merge two objects into one object using laravel

I am getting objects response like this:
"facilities": [
[
{
"facility_id": 1,
"speciality_id": null,
"is_facility_supervisor": 0,
"priv_key": "can_add_doctor,can_view_doctor"
}
],
{
"name": "Patient",
"role_id": 7
}
]
I want name and role_id into facilities and i want expected output like this
"facilities": [
[
{
"facility_id": 1,
"speciality_id": null,
"is_facility_supervisor": 0,
"priv_key": "can_add_doctor,can_view_doctor",
"name": "Patient",
"role_id": 7
}
],
]
How i can achieve this output name and role_id is in separate object but i want in one object like i shared.
My Code:
$specialities = DB::table('user_facility')
->select('user_facility.facility_id','user_facility.speciality_id','user_facility.is_facility_supervisor','user_facility.priv_key')
->where('user_id',$currentUser->id)->get();
$roles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->select('roles.name','user_facility.role_id')->first();
$superadmin = $is_super_admin->is_super_admin;
$specialities = (object) $speciality_id;
$response = ['is_super_admin' => $superadmin, 'facilities' => array_merge([$specialities,$roles])];
Your help will be highly appreciated?
How about:
$specialitiesAndRoles = DB::table('roles')
->join('user_facility', 'roles.id', 'user_facility.role_id')
->where('user_facility.user_id', Auth::user()->id)
->select('user_facility.facility_id','user_facility.speciality_id','user_facility.is_facility_supervisor','user_facility.priv_key','roles.name','user_facility.role_id')
->get();
When you are anyway joining both tables. Just select everything from the joined table. Please check/add if you have any more where clauses.

How to get users group by date and user info using laravel eloquent?

I am trying to get following data from table
Count of registered users in each date
User details
I am trying following script to get that
$users = User::select(DB::raw('count(id) as agents, left(DATE(created_at),10) as registeredDate'))
->whereHas('roles', function($q){
$q->where('name', '=', 'agent');
})
->offset($start)
->limit($limit)
->orderBy($order,'DESC')
->groupBy('registeredDate')
->get();
Above query is returning the Count of registered users in each date
if($users){
foreach($users as $r){
$nestedData['agents'] = $r->agents;
$nestedData['date'] = date('d M Y',strtotime($r->registeredDate));
$data[] = $nestedData;
}
}
But I wanted to get users details also in the same query. My desired output is
'data' => [
[
"agents" => "13",
"date" => "12 Jan 2019",
"nested_data" => [
[
'full_name' => 'john',
'status' => 'active',
'email' => 'john#gmail.com',
],
[
'full_name' => 'John',
'status' => 'active',
'email' => 'john2#gmail.com',
]
]
]
]
Can someone kindly guide me how to achieve it. I would like to appreciate. Thanks
Change your query as:
$users = User::select(DB::raw('count(id) as agents, left(DATE(created_at),10) as registeredDate'))
->whereHas('roles', function($q){
$q->where('name', '=', 'agent');
})
->offset($start)
->limit($limit)
->orderBy($order,'DESC')
->get();
Change your foreach loop as:
if($users){
foreach($users as $user){
$date = date('d M Y',strtotime($r->registeredDate));
$data[$date]['date'] = $date;
$data[$date]['nestedData'][] = ['first_name' => $user->first_name, 'status' => $user->status, 'email' => $user->email];
$data[$date]['agents'] = count($data[$date]['nestedData']);
}
}

mongodb date aggregation operators timezone adjustments with php

I'm trying to adjust the timezone with date aggregation operators.
I need to make -7 hours adjustment on the $signs.timestamp field.
This is my code:
function statsSignatures() {
$cursor = $this->db->collection->users->aggregate(
array('$unwind' => '$signs'),
array('$project'=>array(
'signs'=>'$signs',
'y'=>array('$year'=>'$signs.timestamp'),
'm'=>array('$month'=>'$signs.timestamp'),
'd'=>array('$dayOfMonth'=>'$signs.timestamp'),
'h'=>array('$hour'=>'$signs.timestamp')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
return $cursor['result'];
}
I'm using MongoDB version 2.6.3.
Thank you a lot !
You can use $project with $subtract operator to make a -7 hour adjustment to a Date field:
{
$project : {
ts : { $subtract : [ "$signs.timestamp", 25200000 ] }
}
}
// 25200000 == 1000 milis x 60 sec x 60 mins x 7 h
The projected field ts is a Date that's offset by -7 hours.
Edit
This is the correct PHP syntax when using $subtract.
array(
'$project' => array(
'ts' => array('$subtract' => array('$signs.timestamp', 25200000))
)
)
Subtract accepts an array of values, not a key=>value pair.
I'm not sure why, but I'm getting "exception: invalid operator '$signs.timestamp'" if i'm trying to subtract this in php like this code:
$cursor = $app['mdb']->changemi->users->aggregate(
array('$unwind' => '$signs'),
array('$project' => array(
'ts'=>array('$subtract'=>array(
'$signs.timestamp'=> 25200000
))
)),
array('$project'=>array(
'y'=>array('$year'=>'$ts'),
'm'=>array('$month'=>'$ts'),
'd'=>array('$dayOfMonth'=>'$ts'),
'h'=>array('$hour'=>'$ts')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
So I came with 2 workarounds:
backend php. json_decode
$cursor = $app['mdb']->changemi->users->aggregate(
array('$unwind' => '$signs'),
json_decode('{"$project" : {"ts" : { "$subtract" : [ "$signs.timestamp", 25200000 ] }}}',true),
array('$project'=>array(
'y'=>array('$year'=>'$ts'),
'm'=>array('$month'=>'$ts'),
'd'=>array('$dayOfMonth'=>'$ts'),
'h'=>array('$hour'=>'$ts')
)),
array('$group'=>array(
'_id'=>array('year'=>'$y','month'=>'$m','day'=>'$d','hour'=>'$h'),
'total'=>array('$sum'=>1)
)),
array('$sort'=>array(
'_id.year'=>1,
'_id.month'=>1,
'_id.day'=>1,
'_id.hour'=>1
))
);
frontend javascript (minusHours)
Date.prototype.minusHours= function(h){
this.setHours(this.getHours()-h);
return this;
}
...
"date": new Date({{ i._id.year }}, {{ i._id.month -1 }}, {{ i._id.day }}, {{ i._id.hour }}, 0, 0, 0).minusHours(7),
Here is what worked for me. Instead of doing the timezone conversion in the 'project', I just convert the timestamp while grouping.
group._id = {
year: { $year : [{ $subtract: [ "$timestamp", 25200000 ]}] },
month: { $month : [{ $subtract: [ "$timestamp", 25200000 ]}] },
day: { $dayOfMonth : [{ $subtract: [ "$timestamp", 25200000 ]}] }
};
group.count = {
$sum : 1
};
There's no need to close some objects in array, this way worked for me:
group._id = {
year: { $year : { $subtract: [ "$timestamp", 25200000 ]}},
month: { $month : { $subtract: [ "$timestamp", 25200000 ]}},
day: { $dayOfMonth : { $subtract: [ "$timestamp", 25200000 ]}}
};
group.count = {
$sum : 1
};

Query to select documents based only on month or year

Is there a query to select documents based only on month or year in MongoDB, something like the equivalent for the following code in mysql;
$q="SELECT * FROM projects WHERE YEAR(Date) = 2011 AND MONTH(Date) = 5";
I am looking for the MongoDB equivalent, can anyone help?
Use the aggregation framework to get the query, in particular the Date Aggregation Operators $year and $month. The aggregation pipeline that gives you the above query would look like this:
var pipeline = [
{
"$project": {
"year": { "$year": "$date" },
"month": { "$month": "$date" },
"other_fields": 1
}
},
{
"$match": {
"year": 2011,
"month": 5
}
}
]
db.project.aggregate(pipeline);
The equivalent PHP query would be:
$m = new MongoClient("localhost");
$c = $m->selectDB("examples")->selectCollection("project");
$pipeline = array(
array(
'$project' => array(
"year" => array("$year" => '$date'),
"month" => array("$month" => '$date'),
"other_fields" => 1,
)
),
array(
'$match' => array(
"year" => 2011,
"month" => 5,
),
),
);
$results = $c->aggregate($pipeline);
var_dump($results);

Categories