Manual function inside query? - laravel

Is there any way to put a manual function inside a query in Laravel.
I've timestamp saved in string in DB. I want to convert timestamp from one timezone to another. All the timestamp is inserted in one time zone, and depending upon my user I fetch the timestamp and convert it into their timezone.
what I want to achieve is something like this..
$query = BlogCategory::select('merchant_id', userTime(added_at))
->where('site_id', $site_id)
->get();
userTime() function takes two parameter, the timestamp and the timezone and converts the timsestamp to time of the user.
I want to use userTime() function before fetching the data. I dont want to fetch the data first and then do foreach and so on.
I know I might be absolutely absurd but is there anything of this sort in Laravel?

Well you can achieved that using collection map
$query = BlogCategory::select('merchant_id', 'added_at')
->where('site_id', $site_id)
->get();
$dateAdded = $query->map(function ($data) {
// try this if error $data['merchant_id']
return array(
'merchant_id' => $data->merchant_id,
'added_at' => $this->userTime($data->added_at)
);
})
dd($dateAdded);
Read Collection documentation here: https://laravel.com/docs/5.8/collections

You should use the selectRaw statement and let your DB do this logic for you if you don't want to loop over the result set.
For example if your underlying database is MySQL you can use the CONVERT_TIMEZONE function and do something like this.
BlogCategory::selectRaw('merchant_id, CONVERT_TZ(added_at, "GMT", "MET") as added_at')
->where('site_id', $site_id)
->get();

Related

Laravel eloquent compare datetime with query builder

I'd like to compare datetime values (with date AND time). First I tried this, but it does not work, as it only compares the date, not the time:
$events = $events->whereDate('end', '>=', $input['after']);
I thought that a simple where would help, but it does not:
$events = $events->where('end', '>=', $input['after']);
The reason for that is, that my input value is 2022-10-10T00:00:00 and the database read gives 2022-10-10 00:00:00 (the T in the middle was added in the input).
I'd like to stick to the isoformat (using the T), however inside the database that format gets casted to a value without T it seems. The reason for that might be the cast in the model: 'end' => 'datetime',
What would be the best way to solve this issue and compare datetime objects (and how)?
Change the model cast
Cast the input
What would be the best way to solve this issue and compare datetime objects
The best way is still to convert the input with the data type format of the date and time column
You can use : $dateConvert = date('Y-m-d H:i:s', strtotime($input['after']));
But I suggest you use carbon library :
$dateConvert = \Carbon\Carbon::parse($input['after'])->format('Y-m-d H:i:s');
And :
$events = $events->where('end', '>=', $dateConvert );

use a custom function inside a laravel select

I have a query that needs to use a custom function like is showed below.
The problem is that one of the parameters is a value of another field from the same query.
The function is "calcula_distancia" and "$ofps[0]->latitude" and "$ofps[0]->longitude" are fields from a previus query.
The function needs 4 parameters and the last two are field from $necps that is beeing selected, but I can not retrieve the value from it using just 'participantes.latitude' or even without cotes. It passes a string only, to the function.
So, how can I pass the value from this fields beeing selected to the function?
Tryed to use RAW but not work.
Sorry for the big question. thanks! :-)
use App\Classes\MinhasFuncoes;
$mf = new MinhasFuncoes();
$necps = DB::table('necessidades_part')->where('necessidades_part.id_part',"<>",$id_part)
->where(function($query) use ($searchValues){
foreach ($searchValues as $value) {
if(strlen($value)>3){
$query->orwhere('obs','like','%'.($value).'%')
->orwhere('necessidades.descricao','like','%'.($value).'%')
->orwhere('categorias.descricao','like','%'.($value).'%');
}
}
})
->join('participantes','necessidades_part.id_part','=','participantes.id')
->join('necessidades','necessidades_part.id_nec','=','necessidades.id')
->join('categorias','necessidades.id_cat','=','categorias.id')
->join('unidades','necessidades.id_unid','=','unidades.id')
->select('participantes.id as id_part','participantes.nome_part','participantes.latitude',
'participantes.longitude','participantes.nome_part','necessidades_part.id as id_nec_part',
'necessidades_part.id_nec','necessidades_part.quant','necessidades_part.data',
'necessidades_part.obs','necessidades.descricao as desc_nec',
'categorias.descricao as desc_cat','unidades.descricao as desc_unid',
$mf->calcula_distancia($ofps[0]->latitude,$ofps[0]->longitude,'participantes.latitude',
'participantes.longitude').' as distancia')
->orderBy('data','desc')
->paginate(10);
you can not execute your PHP function inside of your DB query. you should use MySQL function instead of that or you should fetch results from the database then map your result just in PHP

Laravel compare timestamps in where statement

I have a block of code in which I am passing a Carbon date that looks like this:
2017-08-18 22:53:50.031922
And want to compare it to created_at time stamps of some records. However, it seems that the records are not being filtered out; is the comparison in the where statement valid?
$test = Auth::user()->tests()->with([
'participants.testRecords' => function ($query) use ($latestCapture) {
$query->select('id', 'score', 'test_id', 'participant_id', 'capture_timestamp', 'score', 'created_at');
$query->where('test_records.created_at', '>', $latestCapture);
}])->findOrFail($id)->toArray();
If $latestCapture is instancej Carbon, you should rather use here:
$latestCapture->toDateTimeString()
to make sure you pass valid date string.
There is also one more thing - you should make sure created_at is filled in PHP and not in MySQL (this is default in Laravel) - if it's not you can expect time shifts when you have different time zones in PHP and MySQL

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

Laravel/Eloquent and comparing dates

I want to return all of the rows in my database table that are a day or less old. I'm using Laravel 4. This is what I tried:
$date = date('Y-m-d H:i:s');
return MainContact::where(DATEDIFF('timestamp', $date), '<=', 1)->get();
This doesn't work. I read the documentation and it doesn't seem like you can pass Laravel MySQL functions. timestamp is a datetime field. How can I compare these dates in Laravel 4?
The answer that user1977808 gave you is not good because MySQL can't use an index on the timestamp column, since it has to compute an output of the DATE_SUB function for every row. Avoid such queries, they have to process the entire table every time!
How about something like this:
return MainContact::where('timestamp', '>=', time() - (24*60*60))->get();
I put the >= in there because you said "a day or less old", so they must have timestamp that is later than yesterday.
Alternatively,
You can use Carbon API that bundle with Laravel.
ModelName::where( 'timestamp', '>=', Carbon::now() )->get();
Reference: http://laravel.com/docs/5.1/eloquent-mutators
You could also use whereDate(), whereDay(), whereMonth() and whereYear(). In this case, whereDate() could be used as such, with Carbon's easy date functions:
return MainContact::whereDate('dateField', '<', Carbon::now()->subDay())->get();
return MainContact::where('timestamp', '>=', time() - (24*60*60))->get();
You can also do a raw query by using:
$results = DB::query( 'query' );
You only don't the the model object back in the results var

Resources