I was using MySQL for my db before and moved to using MongoDB just recently. I have been converting my queries to MongoDB format then I encountered a problem along the way.
I wanted to get the payslip_id of a specific user where date_generated (of the payslip) is in between the start and end dates of a specific payroll period. Here's the original query (MySQL):
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => 'user_id'])->where('date_generated BETWEEN :start_time AND :end_time', array(':start_time' => $session['start'], ':end_time' => $session['end']));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->payslip_id : '';
}
Now, here's my converted query to MongoDB:
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$in' => array($session['start'], $session['end']))));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
Notice the return statements are different. I wonder if my MongoDB query is correct or not. It doesn't return any error as well.
I would really appreciate your response.
The $in operator selects the documents where the value of a field equals any value in the specified array. It is not equivalent to MySQLBETWEEN.
Use $gte and $lte operators.
public function getPayslipDetails()
{
$time = date_default_timezone_set('Asia/Manila');
$time = date('Y/m/d', time());
$session = Yii::$app->session;
return $this->hasOne(Payslip::className(), ['user_id' => '_id'])->where(array('date_generated' => array('$gte' => $session['start']), 'date_generated' => array('$lte' => $session['end'])));
}
public function getPayslipID()
{
return $this->payslipDetails ? $this->payslipDetails->_id : '';
}
I am not sure about the syntax of php-mongodb but I think this should help.
Related
I'm creating a validation for the post in my Controller.
I have a problem about the date.
I have created in applications/libraries a MY_Form_validation.php page in which I wrote this:
public function valid_date($date, $format = 'Y-m-d') {
$d = DateTime::createFromFormat($date, $format);
return $d && $d->format($format) === $date;
}
Then I have created the form_validation_lang.php with
<?php
$lang['form_validation_valid_date'] = 'The field {field} is not a valid date';
While in my controller I have:
//load the libraries
$this->form_validation->set_rules('birthdate', 'birthdate', 'trim|required|valid_date');
if($this->form_validation->run() == FALSE){
$errors = $this->form_validation->error_array();
var_dump($errors);
$this->response($errors, 500);
return;
}
$person = array(
//..
'birthdate' => $this->post('birthdate'),
//...
);
It prints me that:
'birthdate' => 'string'
About my DB at the beginning my field was Data, and i received this error. Than I have changed to Datetime but the error is the same.
Now it's:
birthdate date NOT NULL,
Now for example I'm trying to post a date like '1960-04-20' and I receive back the error:
"birthdate": "The field birthdate is not a valid date"
I want to write in the db only the date and not the time, could be this the problem??
How can I do to validate date?
Thank you
Replace your function with next:
public function valid_date($date, $format = 'Y-m-d') {
$d = new DateTime($date);
return $d && $d->format($format) === $date;
}
Demo
Or with next one:
public function valid_date($date, $format = 'Y-m-d') {
$d = DateTime::createFromFormat($format,$date); // <-- replace arguments
return $d && $d->format($format) === $date;
}
Demo
DateTime::createFromFormat() documentation
You need to cast this string, after success validation, into DATE datatype and only then send it into DB. Or you can write "to_date($stringvar,$format)" in your SQL query.
Seems like CodeIgniter doesn't likes default variables in validation options. I mean, you can't declare $format = 'Y-m-d' as an argument. So, it would work if you won't use it:
public function valid_date_dmY($str)
{
$d = DateTime::createFromFormat('d.m.Y',$str);
return $d && $d->format('d.m.Y') === $str;
}
I updated a environment. I upgraded PHP and Mongo. The code was using the legacy driver but now I'm using mongodb. I'm also using mongo-php-library. This code snippet is broken now and I'm not sure how to fix it. I've read about updateOne and replaceOne but I'm not sure how to use it:
function update($collection,$criteria,$data,$insertIfNotExists = false)
{
if (!isset($this->collection[$collection])) {
$this->collection[$collection] = self::$database->selectCollection($collection);
}
if ($insertIfNotExists) {
$oldData = $this->collection[$collection]->findOne($criteria);
if ($oldData == NULL) {
$data['createdDate'] = date("Y-m-d H:i:s");
$data['modifiedDate'] = (isset($data['modifiedDate'])) ? $data['modifiedDate']:date("Y-m-d H:i:s");
return ($this->collection[$collection]->insert($data)) ? array('status'=>'ok'):array('status'=>'error','error'=>'unknown_error');
} else {
$newData = $oldData;
foreach($data as $n=>$v) {
$newData[$n] = $v;
}
$newData['modifiedDate'] = (isset($newData['modifiedDate'])) ? $newData['modifiedDate']:date("Y-m-d H:i:s");
return ($this->collection[$collection]->update($criteria,$newData)) ? array('status'=>'ok'):array('status'=>'error','error'=>'unknown_error');
}
} else {
return ($this->collection[$collection]->update($criteria,$data)) ? array('status'=>'ok'):array('status'=>'error','error'=>'unknown_error');
}
}
The new driver changed the name of some methods. Instead of update() (that was used to update one or more documents), now you have updateOne() and updateMany(). The same applies to the other legacy methods insert() and remove(). You can get all further information you need on these changes in PHP MongoDB's Extension Docs and in MongoDB PHP Library.
So, just changing to the code below would fix that error:
$this->collection[$collection]->updateOne($criteria,$data)
Edit
Seems that you only need to update the field modifiedDate, so you can do the following:
$criteria = ['number' => '999'];
$newData = ['modifiedDate' => '2019-07-11 03:00:00'];
$this->collection[$collection]->updateOne(
$criteria,
'$set' => $newData
);
More info here: Update One Document
I have some code that stores values in an array. It all seems to work but I also want to store the time that each value is added to the array (as part of the array) The code stores only unique values to a maximum of four.
function getBand() {
$band_name=$_GET['band_name'];
return $band_name;
}
$pages=$_SESSION['pages'];
if(in_array($_GET['band_name'], $pages)) {
echo"Already in Array";
} else {
if (empty($_SESSION['pages']))
$_SESSION['pages'] = array();
$_SESSION['pages'][] = getBand();
$_SESSION['pages'] = array_slice($_SESSION['pages'], -4);
}
Use time () to get the time.
And store that in the desired array.
array_push ($array, time ());
Since you're talking about "the time they are added to the array" it could be that you mean microseconds which in that case use microtime ()
Note that both functions don't return a formatted timestamp, instead they return an integer.
More on time () here
More on microtime () here
Maybe something like this could do the work:
$test = "Metallica";
$test2 = "The Black Keys";
$arr['pages'][$test] = $test;
$arr['pages'][$test] = date("D M d, Y G:i");
$arr['pages'][$test2] = $test;
$arr['pages'][$test2] = date("D M d, Y G:i");
echo '<pre>'.print_r($arr, true).'</pre>';
For date format you can see - http://php.net/manual/bg/function.date.php
Cheers
class SessionManager
{
protected static $pages = null;
protected static $maxPages = 4;
public function __construct($session) {
self::$pages = $session['pages'];
}
public static function addPage($pageName) {
self::$pages[$pageName] = array(
'name' => $pageName,
'created' => date('Y-m-d h:i:s')
);
self::$pages = array_slice(self::$pages, -1 * $maxPages);
}
public static function writeSession(&$session) {
$session['pages'] = self::$pages;
}
public static function getPages() {
return self::$pages;
}
}
session_start();
$session = new SessionManager($_SESSION);
$session->addPage($_GET['band_name']);
$session->writeSession($_SESSION);
print_pre($session->getPages());
I am trying to loop through a method I created for dates in my object. However, it's only looping the first results and I am not sure how I can make it loop through every result and apply accordingly.
Date Method
public function getDate($date) {
$date = preg_replace('/,/', '', $date);
$newDate = strtotime($date);
$dateFormat = date('l: F d, Y',$newDate);
return $dateFormat;
}
Controller calling the Model
public function showDashboard() {
$pages = Pages::orderBy('created_at', 'DESC')->get();
// foreach($pages as $page) {
// $date = $this->getDate($page->created_at);
// }
//var_dump($date); die;
return View::make('dashboard.index', ['pageTitle' => 'Dashboard','pages' => $pages]);
}
dumping $date only returns one result which looks like the last date in the database table. If I put the dump inside the loop I only get the first result.
I tried applying the method directly to the Blade template $this->getDate($page->created_at); but returns an error stating it is not a defined method. The blade template is just a simple foreach loop that would show each record. What I want accomplished is foreach one of those created_at records I want the getDate method applied to it.
You've not set $date as an array - its writing over itself each time..
public function showDashboard() {
$pages = Pages::orderBy('created_at', 'DESC')->get();
$date = array();
foreach($pages as $page) {
$date[] = $this->getDate($page->created_at);
}
var_dump($date); die;
return View::make('dashboard.index', ['pageTitle' => 'Dashboard','pages' => $pages]);
}
Any idea why the following code is working proprely, returns the device with sensors and measuraments
public function getLastMinutes($device_id,$sensor_id,$minutes = 10) {
...
$devices = Auth::user()->devices()->where("device_id",$device_id)->with(array('sensors.measurements' => function($query) use ($minutes,$sensor_id) {
$date = new DateTime;
$date->modify(-1*$minutes.' minutes');
$formatted_date = $date->format('Y-m-d H:i:s');
$query->where('measurements.created_at','>=',$formatted_date);
}))->get()->toArray();
return Response::json($devices);
...
but when i add the second where("sensor_id",$sensor_id) the measuraments disappiers from the json object returned
public function getLastMinutes($device_id,$sensor_id,$minutes = 10) {
...
$devices = Auth::user()->devices()->where("device_id",$device_id)->with(array('sensors.measurements' => function($query) use ($minutes,$sensor_id) {
$date = new DateTime;
$date->modify(-1*$minutes.' minutes');
$formatted_date = $date->format('Y-m-d H:i:s');
$query->where("sensor_id",$sensor_id)->where('measurements.created_at','>=',$formatted_date);
}))->get()->toArray();
return Response::json($devices);
...
There is something i'm missing?
Thank you for your help!
I figure out the problem. by doing with(array('sensors.measurements .... in the object query you do not have any access to sensor... this means that by doing this $query->where("sensor_id",$sensor_id) the sensors_id will be searched on the measurements table... which is uncorrected. So the solution is have to with one that contains 'sensors' and another one that contains 'sensors.measuraments'.
So from this (wrong)
public function getLastMinutes($device_id,$sensor_id,$minutes = 10) {
...
$devices = Auth::user()->devices()->where("device_id",$device_id)->with(array('sensors.measurements' => function($query) use ($minutes,$sensor_id) {
$date = new DateTime;
$date->modify(-1*$minutes.' minutes');
$formatted_date = $date->format('Y-m-d H:i:s');
$query->where("sensor_id",$sensor_id)->where('measurements.created_at','>=',$formatted_date);
}))->get()->toArray();
return Response::json($devices);
...
to this one (correct)
...
$devices = Auth::user()->devices()->where("device_id",$device_id)
->with(array('sensors' => function($query) use ($sensor_id) {
$query->where('sensors.sensor_id',$sensor_id);
}))
->with(array('sensors.measurements' => function($query) use ($minutes,$sensor_id) {
$date = new DateTime;
$date->modify(-1*$minutes.' minutes');
$formatted_date = $date->format('Y-m-d H:i:s');
$query->where('measurements.created_at','>=',$formatted_date);
}))
->get()->toArray();
return Response::json($devices);
...
little tip. laravel-debugbar is a great project and you should check it out, but it actually did not help me much since i have a SPA and Laravel is doing a RESTFUL json server and for some reason laravel-debugbar did not kick in... but this little piece of code was atually great (taken from Get the query executed in Laravel 3/4)
$queries = DB::getQueryLog();
$last_query = end($queries);
return Response::json($last_query);
Hope can help you