Laravel 5 Query builder - laravel

I tried advanced where clauses
i have model with 2 datetime columns start and end
the request comes two values date_start, date_end
my code
->where(function($q) use ($date_start,$date_end) {
$q->where('start','>=',$date_start)
->where('end','<=',$date_start)
->where('start','>=',$date_end)
->where('end','<=',$date_end);
})
->first();
code returned nothing but in table have one record,
values on request suitable. What is wrong?

worked
$q->where('start','<=',$date_start)
->where('start','<',$date_end)
->where('end','<=',$date_end);

Related

I want to extract the first five data that match the where clause from Laravel relationships

I'd like to do something like this with Laravel's Eloquent:relationship, but it doesn't work.
$playlist->setRelation('tags', $playlist->tags->where('privacySetting', 'public')->take(5));
It works without where clause, but I want to retrieve the first 5 data in the tags relationship table that match the where clause.
How can I do this?
Laravel version is 7.28.1.
this will select top 5 based on criteria from model
$playlist = Playlist::with(['tags' => function($filter){
return $filter->where('privacySetting', 'public')
->take(5);
}])
->get();
//try dd($playlist);

How can i convert this sql query in a eloquent laravel command?

in sql query this commando do exactly i wanted:
SELECT
v.id,
(
SELECT sv.status_id
FROM status_viagem sv
WHERE sv.viagem_id = v.id
ORDER BY sv.created_at DESC LIMIT 1 ) AS status_id
FROM viagens v
Here is the sql results:
But i have no idea how can i do this using Laravel eloquent
Basically, a viagem entry can has a lot of status, but i need to get each viagem and their last status entry from status_viagem table (the pivot table)
by the way viagem/viagens means travel.
My class mapping:
class Viagem extends Model
{
...
public function status()
{
return $this->belongsToMany('App\Status')->withTimestamps();
}
...
}
class Status extends Model
{
public function viagens()
{
return $this->belongsToMany('App\Viagem')->withTimestamps();
}
}
The belongsToMany at both classes gets me a many-to-many:
can someone help me? thanks
---------- Temporary Solution -------
Thanks for all help guys. In fact i can't find a nice solution using only eloquent.
Step 1/3 - To bypass this situation i first execute the above sql to grab only the viagens under the desired status_id (last status_viagem entry):
$viagens_ids = DB::select(
"SELECT viagem_id FROM (
SELECT
v.id AS viagem_id,
(
SELECT sv.status_id
FROM status_viagem sv
WHERE sv.viagem_id = v.id
ORDER BY sv.id DESC LIMIT 1 ) AS status_id
FROM viagens v
) AS tt
WHERE tt.status_id = {$status->id}"
);
Step 2/3 - then i used the array_map to organize my viagens ids
$a = array_map(
function($obj) { return $obj->viagem_id; },
$viagens_ids
);
Step 3/3 - And at last i used elequent whereIn to fetch my viagens:
Viagem::with( 'status')->whereIn('id', $a)->get();
In fact i have solved the problem by a-old-sashion-way but i not happy with it because i wish i learn how to do it using eloquent. what bad to me.
There are many ways to query in laravel. I have created a test project for you to try. The gist are:
1. Eloquent ORM
Eloquent ORM is Laravel's magic which have some limitations in eager loading - which i just come across while contemplating your question for hours. It wont play nicely with first(), last(), and some more functions in the constrained eager loading closure.
In your case, our almost there can be fixed:
App\Models\Viagem::with(['status' => function($query){
return $query->orderBy('pivot_created_at', 'desc');
}])
->get()
It will return entire field for Viagem and Status including its pivot table (the status_viagem).
However, if you wanted to retrieve only viagem.id and status_viagem.status_id, you can map() it as such:
App\Models\Viagem::with(['status' => function($query){
return $query->orderBy('pivot_created_at', 'desc');
}])
->get()
->map(function($data){
$o = new stdClass();
$o->id = $data->id;
$o->status_id = $data->status->first()->id;
return $o;
});
Please take note that the statement above require sql query to be ran twice. Eager loading basically works by querying all the Viagem first then queries the Status and map them in memory based on the foreign keys. You can observe that replacing get with toSql will only give you the first query. Please enable Query Logging to see the second query.
2. Query Builder
Embarking from Ryan Adhitama Putra answer, you could do something like:
App\Models\Viagem::join('status_viagem', 'viagens.id', '=', 'status_viagem.viagem_id')
->orderBy('status_viagem.created_at', 'desc')
->groupBy(['status_viagem.status_id', 'viagens.id'])
->select(['viagens.id', 'status_viagem.status_id'])
->get();
This query builder approach guaranteed to be ran only once, you can replace the get() with toSql() to see the resulting query.
3. Raw Queries
Throwing DB::raw() can help sometime, but i really did not want to mention it.
I am not sure what viagens and viagem represent, but I think one of the relationships has to be belongsToMany() and the other hasMany().
then after you set relationships correctly, you can use Eloquent like this :
$status_id = Viagem::with('status')->orderBy('created_at', 'desc')->first()->pluck('status_id');
Try this.
$status_id = Viagem::join('status','viagem.id','status_viagem.viagem_id')
->select('viagem.id','status_viagem.status_id')
->get();

Laravel eloquent with relation data (Eager Loading)

I have two database tables items and measurement_units - item has measurement unit.
Now the problem is I want to select a particular column from items and some column from measurement_unit. I want to use Eager loading
e.g.
$items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock"])->first();
When accessing measurement_unit. It returns null. Without the select function it returns data(measurement_unit).
$items_with_mu->measurement_unit;
can anyone help me and sorry for my English.
Try this
Item::with(['measurement_unit' => function($q) {
$q->select('id','unit_column'); //specified measurement_unit column
}])
->select('id','measurement_unit_id','item_name')
->get();
If your laravel version is >=5.5 then you can write in a single line
Item::with('measurement_unit:id,unit_column')
->select('id','measurement_unit_id','item_name')
->get()
You have to select the primary column of the main model like below.
items_with_mu = Item::with("measurement_unit")->select(["item_name", "item_stock", "primary_key"])->first();

Join query in laravel with data manipulation send to view

I am having 2 tables, users and profiledetails
I am able to run Join query and access the data and send to view.
But when I am manipulation the field 'dob' (date format) in profiledetails table. No Success, Please check the code below ,
webpagesConroller:
$users = DB::table('users')
->join('profiledetails', 'users.id', '=', 'profiledetails.user_id')
->select('users.*', 'profiledetails.dob')
->get();
$age = $users->dob->diffInYears(Carbon::now());
return view('webpages.index',compact('users'))->with($age);
View:
<li class="cate_head">Age : {{ $age}}</li>
Error:
Trying to get property of non-object
I have model Profiledetails added the mutators as below,
public function getAge(){
return $this->dob->diffInYears(Carbon::now());
}
public function getDOB(){
return $this->dob->format('d-m-Y');
}
Can I not use this method on another controller for Ex- webpagesController, If yes How.
Since you are using a raw query, the data returned is not an object but an array with the data.
Also you did not limit the query, meaning it could return multiple rows.
You'll probably need to get the data from the $users as:
//with the possibily of multiple rows. Index is the row which has to be used
$users[index]['dob']
//when you are sure it only returns one row
$users[0]['dob'] // or $users['dob'] not sure as of the moment
You want to check the differences with Carbon.
So you will probably need to make a Carbon object of the dob result and check it against the Carbon::now.
$age = Carbon::createFromFormat('Y-m-d', $users[0]['dob'])->diffForHumans();
// diffForHumans() uses the local time
Note that this only gets the age for one row (the index or the first because of [0]).
If you want to do it for every row use a for or foreach where you set the $users->age for every $user. But as these are not object/models but raw data, this will not work.
Hope this helps your question a bit

Doctrine: how to return the row count of a records in a groupby statement

Seems like such a simple thing, but I can't get my query to return the number of records in a group. Here's my statement:
public function getGroupCount($user_id)
{
$q = Doctrine_Query::create()
->select('ss.*')
->from('SalarySurvey ss')
->where('ss.user_id=?', $user_id)
->groupBy('created_at')
->execute();
return $q->rowCount();
}
rowCount() does not work in the above query.
It might also be helpful to know that this is being used in a foreach statement.
As CappY suggested, this is not possible in Doctrine 1.2, as far as I know. As a work-around, I was able to finally get a count for each grouping by adding another field to the table and setting that field the same for each group at save time. Then I changed my query to pull that field and just did a simple:
$q->count();
Never work with Doctrine 1.2, but can't U use php's count function or SELECT COUNT() AS 'cnt' ?
return count($q);

Resources