Preconditions
- mySql database client_birthdate field set as DATE and nullable if user does not enter date.
- User inputs Client's Birthdate on __form textbox as a string in mySql format YYYY/MM/DD or not.
- Yii3's ClientForm gets the string or empty string and converts to DATETIME so that Cycle Orm can process it.
- Yii3's ClientService saves the date using Cycle's Client Entity's getter and setter methods and annotations.
- Php 7.4.9
- Typed property. Previously php allowed this variable declaration below a class
public $var;
now inserting typed property between public and $var iepublic ?string $var = ''
excludes other types. Question mark before type allows for null value input. So only two alternatives. - Understanding mySql's '0000-00-00' for non date input.
- Download fork of https://github.com/yiisoft/yii-demo
dateHelper.php (adapted from Invoiceplane)
/**
* @return string|null
*/
public function date_from_mysql($date, $s)
{
//if previous input was not a date mySql would have input '0000-00-00'
if ($date <> '0000-00-00') {
//CYCLE converts all dates to DateTimeImmutable
$date = DateTime::createFromImmutable($date);
//$date = DateTime::createFromFormat('Y-m-d', $date);
//eg. $date->format('Ymd')
return $date->format($s->setting('date_format'));
}
return $date;
}
return '';
}
__form.php caption
<div class="mb-3 form-group has-feedback">
<label form-label for="client_birthdate"><?= $s->trans('birthdate'); ?></label>
<?php
$bdate = $body['client_birthdate'] ?? null;
if ($bdate && $bdate != "0000-00-00") {
//use the DateHelper
$datehelper = new DateHelper();
$bdate = $datehelper->date_from_mysql($bdate, false, $s);
} else {
$bdate = null;
}
?>
<div class="input-group">
<input type="text" name="client_birthdate" id="client_birthdate" placeholder="1900/12/01"
class="form-control data-datepicker"
value="<?= Html::encode($bdate); ?>">
<span class="input-group-addon">
<i class="fa fa-calendar fa-fw"></i>
</span>
</div>
</div>
Entity/Client.php
declare(strict_types=1);
namespace App\Invoice\Entity;
use \DateTime;
/**
* @Entity(
* repository="App\Invoice\Client\ClientRepository",
* mapper="App\Invoice\Client\ClientMapper",
* constrain="App\Invoice\Client\Scope\activeScope"
* )
* @Table(
* indexes={
* @Index(columns={"client_active"}),
* }
* )
*/
class Client
{
/**
* @Column(type="date", nullable=true)
*/
private $client_birthdate = '';
//CYCLE converts all date formats ie. DATE, DATETIME, to DateTimeImmutable so
work with DateTimeImmutable
public function __construct($client_birthdate = '')
public function getClient_birthdate() : ?DateTimeImmutable
{
if (isset($this->client_birthdate) && !empty($this->client_birthdate)){
return $this->client_birthdate;
}
if (empty($this->client_birthdate)){
return $this->client_birthdate = null;
}
}
public function setClient_birthdate(?\DateTime $client_birthdate): void
{
$this->client_birthdate = $client_birthdate;
}
Client/ClientForm.php
declare(strict_types=1);
namespace App\Invoice\Client;
use Yiisoft\Form\FormModel;
use Yiisoft\Validator\Rule\Required;
use \DateTimeImmutable;
use \DateTime;
final class ClientForm extends FormModel {
private ?string $client_birthdate = null;
public function getClient_birthdate(): ?\DateTime
{
if (isset($this->client_birthdate) && !empty($this->client_birthdate)){
return new DateTime($this->client_birthdate);
}
if (empty($this->client_birthdate)){
return $this->client_birthdate = null;
}
}
Client/ClientService
<?php
declare(strict_types=1);
namespace App\Invoice\Client;
use App\Invoice\Entity\Client;
use App\User\User;
final class ClientService
{
private ClientRepository $repository;
public function __construct(ClientRepository $repository)
{
$this->repository = $repository;;
}
public function saveClient(User $user, Client $model, ClientForm $form): void
{
$model->setClient_birthdate($form->getClient_birthdate());