How to handle Query builder with date formats - cakephp

I would like to show only the events for which startdate begins as of tomorrow. How can I proceed ? For the moment it's taking h:i:s into account as well.
public function display()
{
$now = date('Y-m-d H:i:s');
$this->loadModel('Events');
$events = $this->Events
->find()
->contain(['Categories', 'Venues'])
->limit(5)
->order(['events.startdate' => 'ASC'])
->where(['events.startdate >' => $now]);
$this->set('upcomingEvents', $events);
}
I tried this but it's not working:
public function display()
{
$now = date('Y-m-d');
$this->loadModel('Events');
$events = $this->Events
->find()
->contain(['Categories', 'Venues'])
->limit(5)
->order(['events.startdate' => 'ASC'])
->where(['date_format("%Y-%m-%d", events.startdate)' => $now]);
$this->set('upcomingEvents', $events);
}

No need to format the date in the query and lose the indexing functionality, instead compare against a datetime string that uses 00:00:00 for the time part, eg the start of the day.
You can achieve this easily with date('Y-m-d 00:00:00'), however that would be today, not tomorrow, you'd need to feed date() with a timestamp like date('Y-m-d 00:00:00', strtotime('+1 day')).
You can also use the datetime functionality that ships with CakePHP. Today \Cake\Chronos\Date::tomorrow() would create a date object representing 2021-10-06 where the time part will always be 00:00:00.
->where(['Events.startdate >=' => \Cake\Chronos\Date::tomorrow()])
The ORM will automatically format the date object accordingly to the column type, so for your I suppose DATETIME column, it would end up as 2021-10-06 00:00:00 in the SQL.
See also
Cookbook > Date & Time
Chronos Cookbook

Not sure if this is the right way to proceed, but it using function DATA_FORMAT()
DATE_FORMAT(events.startdate, "%Y-%m-%d")
So here is the query :
public function display()
{
$now = date('Y-m-d');
$this->loadModel('Events');
$events = $this->Events
->find()
->contain(['Categories', 'Venues'])
->limit(5)
->order(['events.startdate' => 'ASC'])
->where(['DATE_FORMAT(events.startdate, "%Y-%m-%d") >' => $now]);
$this->set('upcomingEvents', $events);
}
Or we can use it in a conditions array as well
public function display()
{
$this->loadModel('Events');
$events = $this->Events
->find('all', array('conditions' => array('DATE_FORMAT(events.startdate, "%Y-%m-%d") >' => date('Y-m-d'))))
->contain(['Categories', 'Venues'])
->limit(5)
->order(['events.startdate' => 'ASC']);
$this->set('upcomingEvents', $events);
}

Related

CakePHP 3.6 - Find All Records Created Between Two Dates

I am looking for all records between two dates
My variables
$start = '01/01/2009';
$end = '07/24/2019';
I have tried
$gross = $this->CartOrders->find('all')->where(['placed >=' => $start])->andWhere(['placed <=' => $end])->all();
Query Snippet for above
... FROM cart_orders CartOrders
WHERE (placed >= :c0 AND placed <= :c1)
[params] => Array (
[:c0] => Array ( [value] => 01/01/2009 [type] => datetime [placeholder] => c0 )
[:c1] => Array ( [value] => 07/24/2019 [type] => datetime [placeholder] => c1 ) )
Results in
Cake\ORM\ResultSet Object ( [items] => Array ( ) )
I have also tried
$gross = $this->CartOrders->find('all')->where(function($exp) use($start,$end) {
$exp->lte('placed', $end);
$exp->gte('placed', $start);
return $exp;
})->all();
I also have tried
$gross = $this->CartOrders->find('all')->where(function($q) use($start,$end) {
return $q->between('CartOrders.placed', $start, $end, 'date');
})->all();
Any ideas on how I can accomplish this?
Use QueryExpression
use Cake\Database\Expression\QueryExpression;
$query = $this->CartOrders->find()
->where(function (QueryExpression $exp, Query $q) use ($start,$end){
return $exp->between('placed', $start, $end);
});
Probably add a time at condition if the user tried to search within the same day
return $exp->between('placed', $start . " 00:00:00", $end . " 23:59:59");
Try using
$this->CartOrders->find('all', array('conditions' => array(
'date(placed) BETWEEN "'.$start.'" AND "'.$end.'"')));
It's an unorthodox solution but its something that has worked for multiple scenarios for me
$this->set('gross',$this->CartOrders-> find(
'all', array(
'conditions' => array(
'CartOrders.placed >=' => $start,
'CartOrders.placed <=' => $end
))
)); // here gross is a variable to store the data from DB and CartOders is the Model name
This turned out to be a date format issue.
The following solved my problem.
$start = '01/01/2009';
$end = '07/24/2019';
$start = DateTime::createFromFormat('d/m/Y', $start);
$end = DateTime::createFromFormat('d/m/Y', $end);
$gross = $this->CartOrders->find('all')->where([
'placed >=' => $start->format('Y-m-d')
])->andWhere([
'placed <=' => $end->format('Y-m-d')
])->all();
This link helped
PHP convert date format dd/mm/yyyy => yyyy-mm-dd

Passing parameters into a model/table function

I am trying to pass a value called schoolYear which right now is 2019 lets say or whatever the user chooses really. Below is executed once the user selected submit and it executed a if post request then proceeds onto the edit controller via screen 2. on screen 2 I have a edit function with schoolYear being passed into it and a echo returning 2019 the correct value i choose. Great! Now i am struggling with passing that particular parameter into the table function so it can be used as shown. Can someone point me in the right direction, Thanks
Right now i get no error messages but if i take a look at the sql being passed, it is showing FiscalYear = 0 in the sql being executed which means $schoolyear is not being set from my controller hmmmmmm
return $this->redirect([
'controller' => 'MassUpdateCalender',
'action' => 'edit',
$schoolYear,
$allElementary,
]);
public function edit($schoolYear)
{
$InformationCalenderTable = $this->loadModel('MMSDvSchoolFromCalendar');
echo $schoolYear;
$elementarySchools = $InformationCalenderTable->getSchoolsByLevel('0%', $schoolYear);
public function getSchoolsByLevel($schoolYear, string $code = '0', string $isSummerSchool = '0')
{
$query = $this->find()
->where([
'FiscalYear' => $schoolYear,
'DistrictCode' => 'MA',
'summerSchool' => $isSummerSchool,
'SchoolCode like' => $code,
]);
return $query->toArray();
}
The outcome will return a list of all the schools with that where criteria.
From what I understand, you are trying to get schools based on what year they are in. For that, do this:
function edit($schoolYear) {
$this->loadModel('MMSDvSchoolFromCalendar');
$elementarySchools = $this->MMSDvSchoolFromCalendar->find('all', array('conditions' => array('MMSDvSchoolFromCalendar.FiscalYear' => $schoolYear)));
}
However, if you are trying to execute the query in your getSchoolsByLevel function, do this:
function edit($schoolYear) {
$this->loadModel('MMSDvSchoolFromCalendar');
$code = $isSummerSchool = 0;
$elementarySchools = $this->MMSDvSchoolFromCalendar->find('all', array('conditions' => array('FiscalYear' => $schoolYear, 'DistrictCode' => 'MA', 'summerSchool' => $isSummerSchool, 'SchoolCode LIKE' => $code)));
}
If you want to break out your function, like in your example, do this:
function edit($schoolYear) {
$this->loadModel('MMSDvSchoolFromCalendar');
$elementarySchools = $this->_getSchoolsByLevel($schoolYear);
}
function _getSchoolsByLevel($schoolYear, string $code = '0', string $isSummerSchool = '0') {
return $this->MMSDvSchoolFromCalendar->find('all', array('conditions' => array('FiscalYear' => $schoolYear, 'DistrictCode' => 'MA', 'summerSchool' => $isSummerSchool, 'SchoolCode LIKE' => $code)));
}
Notes:
Put var $uses = array('MMSDvSchoolFromCalendar'); at the top of your controller class, so you don't have to keep loading the model.
The underscore before the function denotes a private function. Use this so that users can't go to the MMSDvSchoolFromCalendar/getSchoolsByLevel page.

How to get only today,7 days, one month and 1 year data from today in cakephp 3?

How to get only today,7 days, one month and 1 year data from today in cakephp 3 ? any idea?
Controller code:
if($status == 1){
$data = $this->Sites->find('all')->where(['user_id' => $uid]);
$a = $data->toArray();
$id = $a[0]['id'];
$this->loadModel('Details');
$details = $this->Details->find('all')->where(['site_id' => $id]);
$tmp = $details->toArray();
print_r($tmp);
}
view code:
Form->create('Add',(['id' => 'frm'])); ?>
Form->input('status', array(
'type' => 'select',
'id' => 'mySelect',
'onchange' => 'myFunction()',
'empty' => 'View Details',
'options' => array('1'=>'1 Day','7'=>'7 Days', '30' => '1 Month', '365' => '1 Year')
)
);
?>
To answer you question, use the CakePHP Time class or the PHP DateTime class.
You could use the Time Class like this :
$now = Time::now();
$details = $this->Details->find('all')->where(['site_id' => $id, 'downtime' => $now]);
The above example would give Date and Time at the current call. You could instantiate an object with the Time class and passing in a string:
$today = new Time('today');
$seven_days_ago = new Time('7 days ago');
$one_month_ago = new Time('1 month ago');
Or you could actually do it through the class actions:
$today = Time::now();
$seven_days_ago = (Time::now())->subDays(7);
To answer your edited question, you would get the as needed and then pass them into the query builder:
$now = Time::now();
$seven_days_ago = new Time('7 days ago');
$details = $this->Details->find('all')->where(['site_id' => $id, function($exp) use($now, $seven_days_ago) {
$exp->between('downtime', $seven_days_ago, $now);
}]);

CakePHP: datetime as text

I want to insert a datetime using a simple text input (not a datetime input), but there is something wrong.
For example, I'm inserting this date:
2015-09-07 15:10
My code:
debug($this->request->data['created']);
$post = $this->Posts->patchEntity($post, $this->request->data);
debug($post->created);
Output:
/home/mirko/Server/MeCms_Plugin/src/Controller/Admin/PostsController.php (line 158)
'2015-09-07 15:10'
/home/mirko/Server/MeCms_Plugin/src/Controller/Admin/PostsController.php (line 160)
object(Cake\I18n\Time) {
'time' => '2013-03-07T15:10:00+0000',
'timezone' => 'UTC',
'fixedNowTime' => false
}
Why does this happen?
I suspect there is a problem in converting the string into a Time object.
Thanks.
Look in your Mysql table the data type
ex: change DATE to VARCHAR(50)
Or try this code :
$date = new DateTime($post->created);
$srt_date = $date->format('Y-m-d H:i:s');

Get Time from DateTime in CakePHP

I have a table which contains the field "created". It is a DateTime type. I am getting the data using:
$this->MyModel->find("all");
I only need the time (12:00:00) from the DateTime (2013-12-27 12:00:00). In SQL it is very easy to do by using DATE_FORMAT() but I have no Idea how to do this in cake... I want to do this in the model by getting the data from DB and not one by one in the view using TimeHelper.
You can use a virtual field
class MyModel extends AppModel {
var $virtualFields = array(
'time' => 'DATE_FORMAT(myModel.date_time,"%H/%i/%s")');
//the rest of the class
}
In your find()'s options->fields array,
'fields' => array(
"DATE_FORMAT(created, '%Y-%m-%d') as created"
);
$query = $product->find();
$query->select(['id', 'available_date']);
$list = $query->toArray();
foreach ($list as $datalist) {
$final_list['available_date_new']['date'] = $datalist->available_date->i18nFormat('dd-MM-Y');
}
print_r($final_list);

Resources