Why are my dates not properly localized with default_locale? - cakephp

I cannot figure out why my dates are not converted to FR locale, although I have properly setup the APP_DEFAULT_LOCALE in my app.php file.
I got Sun, 3 October, 09:00, but I would like to have Dim, 3 octobre, 09:00
Is there something else I need to do ?
'App' => [
'namespace' => 'App',
'encoding' => env('APP_ENCODING', 'UTF-8'),
'defaultLocale' => env('APP_DEFAULT_LOCALE', 'fr_FR'),
'defaultTimezone' => env('APP_DEFAULT_TIMEZONE', 'Europe/Brussels'),
Here is how I show the date in my view :
<?= h($upcomingEvent->startdate->format('D, j F, H:i')) ?>
Thanks for your help !

That setting does not affect the format() method, but the i18nFormat() method (and object to string conversion)!
Also be aware that the i18nFormat() method does not use the standard PHP formatting pattern syntax, but the ICU syntax:
$upcomingEvent->startdate->i18nFormat('E, d MMMM, HH:mm')
See also
Cookbook > Date & Time > i18nFormat()

Related

Converting array to string for date format in CakePHP 3.x

In my form, when I submit it, I send a notification email that is populated with the form inputs. One these inputs is called date.
When I submit the form, it is submitted in the format of an array as follows:
[
'year' => 'yyyy',
'month' => 'mm',
'day' => 'dd'
]
In my controller, I then send an email to the logged in user before saving the form data to the database.
This is an excerpt of my email's ViewVars:
$email->viewVars([
'date' => $date,
]);
Because the date is in the form of an array, I get the following error in the email:
Notice (8): Array to string conversion [APP/Template\Email\html\bookingrequest.ctp, line 15]
with line 15 being the line where I do an echo of the viewVars variable $date, as follows:
<?= $date ?>
I was looking up ways of doing a conversion from array to string and have tried the following:
Given $date = $data['session']['date'];
$date = date('Y-m-d',$date->getTimestamp()); - cannot be used on an array
$date = $this->Bookings->Sessions->deconstruct('date', $date); - found out it was deprecated
$date = $data['session']['date']->i18nFormat(); - cannot be used on an array
You can use the same functionality that CakePHP internally uses to transform array representations of dates to actual date objects, that is utilizing the marshal() method of the respective database type object. Once you have a date object, you can then easily format it to whatever you like.
For date-only types you would use \Cake\Database\Type\DateType, which should be retrieved via the \Cake\Database\Type::build() singleton method, in order to use the same instance as the rest of the application:
$dateObject = \Cake\Database\Type::build('date')->marshal($date);
// ... maybe add a check here to ensure that the conversion was successful
echo $dateObject->i18nFormat();
See also
Cookbook > Datebase Access & ORM > Database Basics > Data Types
API > \Cake\Database\Type::build()
API > \Cake\Database\Type\DateType::marshal()

Filtering parameters in CakePHP

In Rails, we can specify the allowed parameters to be used in the controller when saving data. So, with params being the submitted data, I can do this:
params.require(:person).permit(:name, :age)
Which will ensure that the :person key is present and will filter out anything that is not a person's :name or :age.
Is there any way in CakePHP to accomplish this?
EDIT: I know I can write PHP, I want to know if there's a Cake component / plugin that already does this.
Something in this PHP way:
// submited data
$this->request->data['Person'] = array(
'name' => 'Salines',
'age' => '41',
'job' => 'Web Developer'
);
// check if isset and filter out anything that is not a person's name or age
if(isset($this->request->data['Person']))
{
$permit = array('name' => '','age' => '');
$this->request->data['Person'] = array_intersect_key($this->request->data['Person'],$permit);
}
//and return $this->request->data like
array(
'Person' => array(
'name' => 'Salines',
'age' => '41'
)
);
I'm looking for a Cake-provided solution (if there is one)
Well, define "cake-provided", you mean by the framework itself? No, the core doesn't have this functionality but there are two plugins.
For Cake3: Plum Search
For Cake2 & 3: CakeDC Search
For Cake3 I would go for Plum-Search, it is written by the same person as the initial code of the other plugin but a complete rewrite and makes a better use of Cake3.
Next time you ask name your exact Cake version.
Both plugins implement the PRG pattern but don't explicitly allow or deny query parameters. They'll only grab the parameters you specified in your filter declaration and turn them into the request. Validate and save to exclude unwanted fields.
Make a url link like this
echo $this->Html->url(array('controller'=>'users','action'=>'hello','par1'=>23,'par2'=>'sud'));
In hello function in users controller
pr($this->params->named['par1']);
pr($this->params->named['par2']);

cakephp date 'dmy' validdation is not working

I want to validate with dmy format. Here is what I wrote in my model:
'birthdate' => array(
'date' => array(
'rule' => array('date','dmy'),
'message' => 'Solo data valida',
'allowEmpty' => true,
)
)
However, when I submit the form with the date, I get an error.
One thing you should verify is the value of "birthday" DIRECTLY PRIOR to validation. Try debugging $this->request->data in your controller before calling $this->Model->save, or $this->Model->validate. It's quite possible that you are transforming that date value before you pass it to validation, and thus it could be failing.
For instance, I typically use a beforeSave, and afterFind callback to transform dates going into and coming from MySQL, or you may have something in your appController or beforeFilter callback that's inadvertently transforming the data.

What is the best way to process complex datatypes in CakePHP?

My Goal: Replace the Default Cake Datepicker
I hate the default CakePHP FormHelper date-picker select elements and I'd like to use jQuery UI Datepicker widget instead. In order to degrade gracefully, I want to have a date field (enabled with the widget) and a time-picker select box constrained to 15-minute increments.
In case I explained that poorly, here is what it looks like:
My Ideal Solution
To minimize repetition, I want to put the HTML in a layout Element and process it using a Behavior function. This way I could do something like the following:
view.ctp
echo $this->element( 'datepicker', array( 'data' => $data ) );
model.php
$actsAs = array( 'Datepicker' );
function beforeSave( $options ){
$this->parseDatepickers(); //behavior function would alter $this->data
return true;
}
The Problem
Unfortunately, by the time it gets to the beforeSave (or beforeValidate) callback, the datepicker & timepicker fields have been destroyed by the model's deconstruct function. deconstruct seems to be looking for dates & times to be reported the way FormHelper creates them.
In short, it's looking for:
[date_field] => Array
(
[year] => 2011
[month] => 11
[day] => 11
[hour] => 8
[min] => 00
[meridian] => pm
)
but instead it's finding:
[date_field] => Array
(
[datepicker] => 11/11/2011
[timepicker] => 8:00 pm
)
And because it doesn't find the structure it expects, I end up with this:
[date_field] =>
I know I can have jQuery update hidden inputs with the appropriately-named fields, but this wouldn't degrade well.
Current Workaround
What I'm doing, for the moment, is washing the data through my behavior function prior to saving -- but this doesn't feel like the right way to do it:
$this->request->data = $this->Event->fixDates( $this->data );
$this->Event->save( $this->data );
So...............
What is the best way to do this? Putting it in beforeSave or beforeValidate seems like "the Cake way", but deconstruct kills me. Do I need to extend AppModel and override deconstruct? That seems ugly too.
I normally make my date fields as text fields in the view to override the default Form Helper output and then use jQuery date picker (or whatever your alternative picker would be) to set the date:
echo $this->Form->input('date', array('type' => 'text', 'class' => 'datepicker'));
This would output a typical tag rather than all the drop downs.
Then, in my model's beforeSave function, I change the format to MySQL formatted date:
$this->data['Model']['date'] = date('Y-m-d G:i:s', strtotime($this->data['Model']['date']));
(remember to return true in beforeSave)
This works with a proper datetime datatype in the database and it sounds like what you are trying to do.

cakephp: how to make NOW() work in search condition?

I'm trying to get all records with date greater then now. I tried this but it doeasnt work:
$all_dates = $this->TourDate->find('all', array('conditions' => array('TourDate.date >=' => 'NOW()'), 'order' => array('TourDate.date ASC')));
If I replace NOW() with the current date it works. Why's that?
I do not use CakePHP but I am pretty sure that your 'NOW()' is parsing to string and finally you got something like
TourDate.date >= 'NOW()'
Maybe you should just try
array('TourDate.date >= NOW()')
as a value only instead of spliting it to key => value style ?
If you are looking for a way to do it with PHP-function istead of MySQL-functions you don't have to use the verbous format $conditions = array('begin >' => date('Y-m-d H:i:s')), MySQL understands the shorter 'c' preset of PHPs date() for ISO 8601 dates with $conditions = array('begin >' => date('c')).
I like this for doing queries like 'begin >' => date('c', strtotime("+4 weeks")), which is very readable code and great to debug when you look at the SQL-Queries.
'conditions' => array('TourDate.date >= NOW()')
Otherwise, cakephp will quote the NOW() function, and mysql will think of it as a string.
hsz is correct. Cake is interpreting the NOW() condition as the string 'NOW()'. Providing a full SQL snippet in your conditions will work, as hsz suggests.
You might be tempted to use date('Y-m-d H:i:s') in place of NOW() (as I suggested in the first version of this answer). Don't do it! As hsz points out below, this will prevent the query from being cached.
I believe CakePHP strips out any SQL like functions to prevent a SQL injection attacks. Much as it annoys me, I usually use the date('Y-m-d H:i:s') trick too.

Resources