Uh, so like, if you wanna make sure your date shows up all right after some stupid validation errors, here’s what you gotta do, okay?
First thing, you gotta set your application language and formatter locale to French, like for real. So in your config, you do:
'formatter' => [
'locale' => 'fr-FR',// Set locale explicitly
'dateFormat' => 'dd/MM/yyyy',// your preferred format
'decimalSeparator' => ',',
'thousandSeparator' => '.',
'currencyCode' => 'EUR',
],
And also, don’t forget to set the app language at the top level:
'language' => 'fr-FR',
This way Yii understands, okay, I gotta be all French style and stuff.
Now, uh, the \yii\jui\DatePicker thingy, it uses jQuery UI DatePicker, but by default it’s like all American-ish (mm/dd/yyyy), so you gotta tell it, “Hey, be French too!”
Like this:
<?= $form->field($model, 'Date_of_birth')->widget(\yii\jui\DatePicker::classname(), [
'language' => 'fr',
'dateFormat' => 'dd/MM/yyyy',
]) ?>
Alright, so then, here’s the tricky part—your model gets the date in dd/MM/yyyy, but MySQL wants it as YYYY-MM-DD. So, before you validate or save, you gotta transform it, or else… uh, bad things happen.
You do this by overriding beforeValidate():
public function beforeValidate()
{
if (parent::beforeValidate())
{
if (!empty($this->Date_of_birth))
{
// Convert date from dd/MM/yyyy to Y-m-d
$date = \DateTime::createFromFormat('d/m/Y', $this->Date_of_birth);
if ($date !== false)
{
$this->Date_of_birth = $date->format('Y-m-d');
}
else
{
// Invalid date format, leave as is to trigger validation error
}
}
return true;
}
return false;
}
And after you get the data from the database, you wanna change the date back to dd/MM/yyyy to show in the form. So in afterFind():
public function afterFind()
{
parent::afterFind();
if (!empty($this->Date_of_birth))
{
$date = \DateTime::createFromFormat('Y-m-d', $this->Date_of_birth);
if ($date !== false)
{
$this->Date_of_birth = $date->format('d/m/Y'); // for form display
}
}
}
But if you wanna be super organized, you can make a helper class to handle the dates so you don’t screw up everywhere, y’know? Like this: Helpers: Helpers Overview | The Definitive Guide to Yii 2.0 | Yii PHP Framework
declare(strict_types=1);
namespace app\helpers;
use DateTime;
use DateTimeImmutable;
use Yii;
class DateHelper
{
// For Yii formatter & JS dateFormat
const DISPLAY_FORMAT = 'dd/MM/yyyy';
private const PHP_DISPLAY_FORMAT = 'd/m/Y';
private const PHP_STORAGE_FORMAT = 'Y-m-d';
// Convert date from display format (dd/MM/yyyy) to storage format (Y-m-d)
public static function toStorageFormat(string $dateStr): ?string
{
$date = DateTime::createFromFormat(self::PHP_DISPLAY_FORMAT, $dateStr);
$errors = DateTime::getLastErrors();
if ($date === false || $errors['warning_count'] > 0 || $errors['error_count'] > 0)
{
return null;
}
return $date->format(self::PHP_STORAGE_FORMAT);
}
// Convert date from storage format (Y-m-d) to display format (dd/MM/yyyy) using Yii formatter
public static function toDisplayFormat($dateStr)
{
if ($dateStr === '')
{
return null;
}
// Validate strict format using DateTimeImmutable for immutability
$date = DateTimeImmutable::createFromFormat(self::PHP_STORAGE_FORMAT, $dateStr);
$errors = DateTimeImmutable::getLastErrors();
if ($date === false || $errors['warning_count'] > 0 || $errors['error_count'] > 0)
{
return null;
}
// Use Yii formatter to format date with locale-aware output
return \Yii::$app->formatter->asDate($date->getTimestamp(), self::DISPLAY_FORMAT);
}
// Format any given date value using Yii formatter.
public static function formatDate(string|int $value, string $format = self::DISPLAY_FORMAT): ?string
{
if ($value === '' || $value === 0)
{
return null;
}
$timestamp = is_int($value) ? $value : strtotime($value);
if ($timestamp === false || $timestamp < 0)
{
return null;
}
return \Yii::$app->formatter->asDate($timestamp, $format);
}
}
And then in your model, instead of writing the date conversion yourself all over, just use the
helper like this:
use app\helpers\DateHelper;
public function beforeValidate()
{
if (parent::beforeValidate())
{
if (!empty($this->Date_of_birth))
{
$converted = DateHelper::toStorageFormat($this->Date_of_birth);
if (!$converted)
{
$this->addError('Date_of_birth', 'Date invalide (jj/mm/aaaa)');
return false;
}
$this->Date_of_birth = $converted;
}
return true;
}
return false;
}
public function afterFind()
{
parent::afterFind();
if (!empty($this->Date_of_birth))
{
$displayDate = DateHelper::toDisplayFormat($this->Date_of_birth);
if ($displayDate !== null)
{
$this->Date_of_birth = $displayDate;
}
}
}
Oh! And don’t forget to set your formatter in config/web.php like this:
'formatter' => [
'class' => 'yii\i18n\Formatter',
'locale' => 'fr-FR',
'dateFormat' => 'php:d/m/Y',// can use PHP format string here
'datetimeFormat' => 'php:d/m/Y H:i:s',
'timeFormat' => 'php:H:i:s',
'decimalSeparator' => ',',
'thousandSeparator' => '.',
'currencyCode' => 'EUR',
],
So umm, yeah, that’s basically it. Just gotta tell the system to speak French everywhere, convert your dates right before saving, then convert them back for display, and maybe use the helper so you don’t mess up.
Hope this helps! I-I’m not Rick, so if this sounds a little clumsy… well, at least I tried, okay? Geez.