The wrong record in my database is getting updated - php

im using laravel eloquent to update a record in a database table. Im passing in a parameter of 52 which is the id of the record I want to update (primary key).
I am printing the query to check which record its finding and its printing the record with the id of 13 and then when i check the table, id 13 has been updated.
protected $connection = 'sqlsrv';
protected $table = 'todo';
public $timestamps = false;
public static function complete($todoId, $userId)
{
$now = new DateTime();
$query = Self::join('todoTypes', 'todo.typeId', 'todoTypes.id')
->where('todoTypes.canComplete', 1)
->whereNull('todo.completedDate')
->find(52);
$query->where(function ($query) use ($now)
{
$query->whereNull('cancelDate')
->orWhere('cancelDate', '>', $now);
});
if ($query)
{
$query->completedDate = $now;
$query->save();
}
}

How about trying like this?
The query after using find did not make any sense since find returns the first object not a query builder instance.
public static function complete($todoId, $userId)
{
$now = new DateTime();
$object = Self::join('todoTypes', 'todo.typeId', 'todoTypes.id')
->where('todoTypes.canComplete', 1)
->whereNull('todo.completedDate')
->where(function ($query) use ($now) {
$query->whereNull('cancelDate')
->orWhere('cancelDate', '>', $now);
})->find(52);
if ($object) {
$object->completedDate = $now;
$object->save();
}
}

I have managed to fix this by just adding a select at the start
select('todo.id', 'todo.completedDate')
It seems it was getting the right row, but displaying the id as something else.
When I took out the join and the joins where clause, it worked. I suspect it was using the id of the joint row from the todoTypes table as that was 13.

Related

How to write correct way of sql query in php laravel

I want to fetch all data from this table for that i am using query :
$emp = Employee::where('user_id', '=', $user->id)->first();
$holidays = Holiday::orderBy('holidays.id', 'desc')->take(5)->where('holidays.id', '=', $emp->id)->get();
It is not giving me any result. I am new to php can anyone help me out yrr?
The "eloquent" way to do it would be in your Employee model to set up the relationship between Employees and Holidays :
public function holidays() {
return $this->hasMany(Holiday::class);
}
and then in your Holiday model set up the reverse :
public function employee() {
return $this->belongsTo(Employee::class, 'created_by');
}
Note that we're having to pass over the name of the foreign key explicitly as it's not what Laravel is expecting (employee_id).
Then you can just load your Employee :
$emp = Employee::where('user_id', $user->id)->first();
and then access their holidays :
$holidays = $emp->holidays;
or :
$lastfiveholidays = $emp->holidays()->take(5);

laravel eloquent complex select inside where statement

halo, i have data and want to display it like picture below
there are two models relationship, Person and Installment.
this is Person model:
class Person extends Model
{
protected $table = 'person';
public function angsuran()
{
return $this->hasMany(Installment::class);
}
}
this is Installment model:
class Installment extends Model
{
protected $table = 'installment';
public function person()
{
return $this->belongsTo(Person::class);
}
}
and this is my controller to querying and display data
$data = Person::with('angsuran')
->whereHas('angsuran', function ($q) {
$q->whereBetween('installment_date', [\DB::raw('CURDATE()'), \DB::raw('CURDATE() + INTERVAL 7 DAY')])
->where('installment_date', '=', function () use ($q) {
$q->select('installment_date')
->where('status', 'UNPAID')
->orderBy('installment_date', 'ASC')
->first();
});
});
return $data->get();
it show error unknow colum person.id in where clause
please help. thanks.
As the comment said, you need to put $q as a parameter to the Closure.
When using subqueries, it's useful to tell the query builder which table it is supposed to query from.
I've rewritten your query. It should achieve what you're looking for. Also, changed the CURDATE to Carbon objects.
today() returns a datetime to today at 00:00:00 hours. If you need the hours, minutes and seconds, replace today() by now().
$data = Person::with('angsuran')
->whereHas('angsuran', function ($subquery1) {
$subquery1->where('installment_date', function ($subquery2) {
$subquery2->from('installment')
->select('created_at')
->where('status', 'UNPAID')
->whereBetween('installment_date', [today(), today()->addWeeks(1)])
->orderBy('installment_date')
->limit(1);
});
});
Using with and whereHas you will end up with two query even if you have limit(1) in your subQuery and the result will show all 4 installment related to the person model. also I don't think you can order on the subquery, it should be before the ->get
so here's i've rewritten your code
$callback = function($query) {
$query->whereBetween('installment_date', [today(), today()->addDays(7)])
->where('status', 'UNPAID')
->orderBy('installment_date');
};
$data = Person::whereHas('angsuran', $callback)->with(['angsuran' => $callback])->get();
or you can use query scope. please see this answer Merge 'with' and 'whereHas' in Laravel 5

How to change time zome in different tables in Laravel

Can you give an idea?
I have two tables in to postgresql DB.
The are filled with recods by two separate csv files. But the records of the first csv file are with local timestamp. The second csv file is with timestamps UTC.
So I need to change the time in local of the view in this table that is filled with records with timezone UTC. I used to deal with that problem before using laravel with this code in every page that I need to do that, for example:
date_default_timezone_set('Europe/Sofia');
The controller:
function getdata_chart(Request $request)
{
$start_date = date('d-m-Y 00:00:00');
$end_date = date('d-m-Y 23:59:59');
if($request->start_date != '' && $request->end_date != '')
{
// if user fill dates
$dateScope = array($request->start_date ." 00:00:00", $request->end_date ." 23:59:59");
} else {
// default load page - today
$dateScope = array($start_date, $end_date);
};
$students = MeasCanal::whereBetween('recordtime', $dateScope)
->selectRaw('recordtime')
->selectRaw('max(formattedvalue) filter (where fullname = \'Данни.Кота\') as iazovir')
->selectRaw('max(formattedvalue) filter (where fullname = \'Данни.Температура\') as temperatura350')
->where(function ($query) {
$query->where('fullname', 'like', "Язовир.Данни.Кота")
->orWhere('fullname', 'like', "ГСК_11_350.Данни.Температура");
})
->groupBy('recordtime')
->orderBy('recordtime')
->get();
return response()->json($students);
}
return response()->json($students);
}
Update your Model MeasCanal and add the following :
Import and use :
use Carbon\Carbon;
Add Function :
/**
* Get the user's recordtime.
*
* #param string $value
* #return string
*/
public function getRecordtimeAttribute($value)
{
return Carbon::parse($value)->timezone('Europe/Sofia')->toDateTimeString();
}
I'm not sure this is what you want but i think you can get the idea.
First Method,
You can use accessor;
public function getCustomTimestampAttribute($value)
{
// you can use your logic here to set your timezone by table
$timezone = 'Europe/Sofia';
return Carbon::parse($this->custom_timestamp)->timezone($timezone)->toDateTimeString();
}
then you can get the value like: $model->custom_timestamp
Second Method,
You can use map;
$customDates = $dates->map(function ($date, $key) {
$date->custom_timestamp = Carbon::parse($date->custom_timestamp)->timezone('Europe/Sofia')->toDateTimeString();
return $date;
});
EDIT
In your model(MeasCanal) set recordtime attribute;
public function getRecordtimeAttribute($value)
{
// you can use your logic here to set your timezone by table
$timezone = 'Europe/Sofia';
return Carbon::parse($this->recordtime)->timezone($timezone)->toDateTimeString();
}
then you can simply see the result after the query in your controller like
dd($students);
or even simpler to see:
dd($students->first()->recordtime); // first matched rows recordtime attr.
Note: you cant use accessors with raw queries you should use eloquent models btw.

How use with() when also joining a table

I have the following tables (with only relevant fields):
devices
id
name
created_at
updated_at
device_reports
id
device_id
location
created_at
updated_at
I have a report with a number of filters on it that is already working, so I want to stick with the eloquent way of doing things. Here is Controller function:
public function devices(Request $request)
{
$devicesQuery = Device::with(['latestReport']);
if ($request->ajax())
{
if($request->input('start') && $request->input('start')!='')
{
$start_date = date('Y-m-d', strtotime($request->input('start')));
$end_date = date('Y-m-d', strtotime($request->input('end')));
$devicesQuery = $devicesQuery->lastReportBetween($start_date,$end_date);
}
$devices = $devicesQuery->paginate(10);
return Response::json(View::make('devices/table', array('devices' => $devices))->render());
}
}
The model's latestReport is defined as:
public function latestReport()
{
return $this->hasOne('App\Models\DeviceReport')->latest();
}
The model's function lastReportBetween is defined as:
public function scopeLastReportBetween($query, $start, $end)
{
$query = $query->join('device_reports AS dr', 'dr.device_id', '=', 'devices.id');
$query = $query->where('dr.id', '=', DB::raw('(SELECT max(dr2.id) FROM device_reports AS dr2 WHERE dr2.device_id = devices.id)'));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '>=', DB::raw("STR_TO_DATE('".$start."', '%Y-%m-%d')"));
$query = $query->where(DB::raw("(IFNULL(dr.gps_time, dr.created_at))"), '<=', DB::raw("STR_TO_DATE('".$end."', '%Y-%m-%d')"));
return $query;
}
When running the above with a start/end date selected, I get the correct records returned, but I don't get anything returned in "latestReport", but when I run the page without the date filters in place, it correctly returns the device information and the most recent report record in the latestReport class variable.
Can anyone help me understand how to change this code such that I do get the latestReport back when I also call the lastReportBetween function?
I figured out my problem. I should have been using "whereHas()" instead of manual joins and whatnot.
public function scopeLastReportBetween($query, $start, $end)
{
return $query->whereHas('latestReport', function($reportsQuery) use ($start, $end)
{
$reportsQuery->whereBetween('created_at', [$start, $end])
->where('device_reports.id', '=', DB::raw('(SELECT max(dr2.id) FROM device_reports AS dr2 WHERE dr2.device_id = device_reports.device_id)'));
});
}

Reusing a Yii2 query

Am trying to reuse a query but it fails.
In my method I have:
public function getPacked($from, $to){
$initquery = RealTimeTblTrucks::find()
->leftJoin('tbl_truck_history','tbl_truck_history.truck_id=tbl_trucks.id')
->where(["between","tbl_truck_history.created_at",$from,$to])
->andWhere(["tbl_truck_history.status"=>20]);
$data = [];
$data[SELF] =$initquery
->andWhere(["tbl_trucks.truck_category"=>28])
->count();
$data[NORMAL] = $initquery->andWhere(["tbl_trucks.truck_category"=>27])
->count();
$data[BULKER] = $initquery->andWhere(['in', 'tbl_trucks.truck_category', [26,34]])
->count();
return $data;
}
Now the first ($data[SELF]) returns the correct information but the next ones NORMAL and BULKER didn't return the correct information.
When I check on the raw query I can see that the last two are affected by the first one such that the new query at $data[NORMAL] contains a check for truck_category = 20 which should only be executed on the first array item (SELF).
How to refactor this to make it work?
Advantage of clone over creation a new object, is that, all properties will be copied into the new object instead of resetting them. This is quite useful when you use query builder.
public function getPacked($from, $to) {
$initquery = RealTimeTblTrucks::find()
->leftJoin('tbl_truck_history','tbl_truck_history.truck_id=tbl_trucks.id')
->where(["between","tbl_truck_history.created_at",$from,$to])
->andWhere(["tbl_truck_history.status"=>20]);
$data = [];
$querySelf = clone $initquery;
$data[SELF] = $querySelf
->andWhere(["tbl_trucks.truck_category"=>28])
->count();
$queryNormal = clone $initquery;
$data[NORMAL] = $queryNormal->andWhere(["tbl_trucks.truck_category"=>27])
->count();
$queryBulker = clone $initquery;
$data[BULKER] = $queryBulker->andWhere(['in', 'tbl_trucks.truck_category', [26,34]])
->count();
return $data;
}
Refer Yii2 clone detail

Categories