如何使用 Yii3 及其 Cycle-ORM 集成设置生日?

问题描述 投票:0回答:4

先决条件

  1. mySql 数据库 client_birthdate 字段设置为 DATE,如果用户未输入日期,则可为空。
  2. 用户在 __form 文本框中输入客户的出生日期作为 mySql 格式 YYYY/MM/DD 或其他格式的字符串。
  3. Yii3的ClientForm获取字符串或空字符串并转换为DATETIME,以便Cycle Orm可以处理它。
  4. Yii3 的 ClientService 使用 Cycle 的客户端实体的 getter 和 setter 方法以及注释来保存日期。
  5. PHP 7.4.9
  6. 键入属性。以前 php 允许在类下面声明此变量
    public $var;
    现在在 public 和 $var 之间插入类型化属性,即
    public ?string $var = ''
    排除其他类型。类型前的问号允许空值输入。所以只有两种选择。
  7. 理解mySql的'0000-00-00'用于非日期输入。
  8. 下载 https://github.com/yiisoft/yii-demo 的分支

dateHelper.php(改编自 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 标题

 <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;
    }

客户端/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;
        } 
    }

客户端/客户端服务

<?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());
orm date
4个回答
0
投票

注意事项:

  1. 确保 _form 'id' 和 'name' 值例如。 client_birthdate 对应于实体@column 和数据库表字段。即一致地使用字段名称 通过实体、注释。 ClientForm 的 getter 方法将从 __form 接收数据,该数据是字符串或 null。 getter 会将其转换为 DATETIME 或 null,以便 CYCLE ORM(螺旋框架)可以处理它。
  2. 确保 Entity/Client.php 实例化区域中的初始化,即。 BEFORE 构造和 IN 构造。

提示

  1. 上面函数的注释是通过Cycle的注释来读取的。
  2. 注释之前的
  3. use \DateTime;
    。不要忘记反斜杠来指示 DateTime 是一个不在当前命名空间中的 php 类。
  4. mySql 在数据库中输入 DATE,并在下面的注释中包含“日期”。 IE。
    * @Column(type="date", nullable=true)
    否则Cycle将无法读取它。
  5. 我选择使用简单的无类型、可为空的字符串。

.../Entity/Client.php

   public function getClient_birthdate() : ?\DateTimeImmutable  

   public function setClient_birthdate(?\DateTime $client_birthdate): void

...src/Invoice/Entity/Client.php...

     /**
     * @Column(type="date", nullable=true)
     */
    private $client_birthdate = '';   
  1. 从 Coalface __form 接受的值使用字符串,因此使用字符串初始化 ClientForm.php 的
    private ?string $client_birthdate = null
    不是日期时间函数。
  2. ?\DateTime 之前的问号允许空值。在函数声明中一致使用,如下所示。

...src/Invoice/Client/ClientForm.php

    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;
        } 
    }

上面的代码可以简化为:

 public function getClient_birthdate() : ?\DateTime
    {
       // convert the input string on the form received by means of '$this->client_birthdate'
       // back into DateTime so that Cycle can deal with it and
       // save it in 'date' format in mysql behind the scenes
       return new DateTime($this->client_birthdate);
    }

0
投票

2022 年 9 月 21 日更新

现在属性比注释更受青睐,因此上面的代码已更改。

本质上,要在表单上表示 DateTimeImmutable,必须使用 ->format() 命令来呈现。合适的日期样式必须位于括号之间,例如。 Y-m-d 甚至 d-m-Y。为了实现这一点,可以使用额外的代码,例如。

__form.php

<div class="mb-3 form-group has-feedback">
        <?php
           $bdate = $datehelper->get_or_set_with_style($body['client_birthdate']);
        ?>
        <label form-label for="client_birthdate"><?= $s->trans('birthdate') .' ('.$datehelper->display().')'; ?></label>
        <div class="input-group">
            <input type="text" name="client_birthdate" id="client_birthdate" placeholder="<?= ' ('.$datehelper->display().')';?>"
                   class="form-control input-sm datepicker" readonly                   
                   value="<?= null!== $bdate ? Html::encode($bdate instanceof \DateTimeImmutable ? $bdate->format($datehelper->style()) : $bdate) : null; ?>" role="presentation" autocomplete="off">
            <span class="input-group-text">
            <i class="fa fa-calendar fa-fw"></i>
        </span>
        </div>        
    </div>  

在布局文件中包含以下日期选择器 jquery 代码。

<?php
    // https://api.jqueryui.com/datepicker
    $js1 = "$(function () {".
       '$(".form-control.input-sm.datepicker").datepicker({dateFormat:"'.$datehelper->datepicker_dateFormat()
                                                        .'", firstDay:'.$datehelper->datepicker_firstDay()
                                                        .', changeMonth: true'
                                                        .', changeYear: true'
                                                        .', yearRange: "-50:+10"'
                                                        .', clickInput: true'
                                                        .', constrainInput: false'
                                                        .', highlightWeek: true'
                                                        .' });'.
    '});';
    echo Html::script($js1)->type('module');
?>

这里是样式参考。


0
投票

2024 年 3 月 13 日更新 客户端实体client.php

<?php
declare(strict_types=1); 

namespace App\Invoice\Entity;

use Cycle\Annotated\Annotation\Column;
use Cycle\Annotated\Annotation\Entity;
use Cycle\ORM\Entity\Behavior;
use \DateTime;
use \DateTimeImmutable; 

#[Entity(repository:\App\Invoice\Client\ClientRepository::class)]
#[Behavior\CreatedAt(field: 'client_date_created', column: 'client_date_created')]
#[Behavior\UpdatedAt(field: 'client_date_modified', column: 'client_date_modified')]    
class Client
 {
    #[Column(type: 'primary')]
    public ?int $id = null;
   
    #[Column(type: 'datetime')]
    private DateTimeImmutable $client_date_created;
    
    #[Column(type: 'datetime')]    
    private DateTimeImmutable $client_date_modified;
    
    #[Column(type:'date', nullable: true)]
    private mixed $client_birthdate;
     
    public function __construct(
            // treat as firstname
            mixed $client_birthdate=null,
    {
        $this->client_birthdate = $client_birthdate;
        $this->client_date_created = new \DateTimeImmutable();
        $this->client_date_modified = new \DateTimeImmutable();
    }
    
    public function getClient_id(): ?int
    {
        return $this->id;
    }
    
    public function getClient_date_created(): DateTimeImmutable
    {
        /** @var DateTimeImmutable $this->client_date_created */
        return $this->client_date_created;
    }

    public function getClient_date_modified(): DateTimeImmutable
    {
        /** @var DateTimeImmutable $this->client_date_created */
        return $this->client_date_modified;
    }
    
    
    //cycle 
    public function getClient_birthdate() : DateTimeImmutable|string|null  
    {
        /** @var DateTimeImmutable|string|null $this->client_birthdate */
        return $this->client_birthdate;
    }    
    
    public function setClient_birthdate(?DateTime $client_birthdate): void
    {
        $this->client_birthdate = $client_birthdate;
    }
}

表单.php

<?php

declare(strict_types=1);

namespace App\Invoice\Client;

use App\Invoice\Entity\Client;
use Yiisoft\FormModel\FormModel;
use Yiisoft\Validator\Rule\Required;
use Yiisoft\Validator\Rule\Integer;
use \DateTimeImmutable;

final class ClientForm extends FormModel
{
    private mixed $client_birthdate;
        
    public function __construct(Client $client) { 
        $this->client_birthdate = $client->getClient_birthdate();
    }
            
    public function getClient_birthdate() : string|null|DateTimeImmutable
    {
        /**
         * @var string|null|DateTimeImmutable $this->client_birthdate
         */
        return $this->client_birthdate;
    }
    
    /**
     * @return string
     *
     * @psalm-return ''
     */
    public function getFormName(): string
    {
      return '';
    }
}
<?php

declare(strict_types=1); 

namespace App\Invoice\Client;

use App\Invoice\Entity\Client;
use App\Invoice\Helpers\DateHelper;

use App\Invoice\Setting\SettingRepository;

final class ClientService
{
    private ClientRepository $repository;

    public function __construct(ClientRepository $repository)
    {
        $this->repository = $repository;
    }
    
    /**
     * 
     * @param Client $model
     * @param array $body
     * @param SettingRepository $s
     * @return int|null
     */
    public function saveClient(Client $model, array $body, SettingRepository $s): int|null
    {
        $datehelper = new DateHelper($s);
        $datetime = new \DateTime();
        isset($body['client_birthdate']) ? $model->setClient_birthdate($datetime::createFromFormat($datehelper->style(),(string)$body['client_birthdate'])) : '';
        $this->repository->save($model);
        return $model->getClient_id();
    }
    
}

form.php

<?php
declare(strict_types=1);

use Yiisoft\FormModel\Field;
use Yiisoft\Html\Html;
use Yiisoft\Html\Tag\Form;
use Yiisoft\Arrays\ArrayHelper;

/**
 * @var \Yiisoft\View\View $this
 * @var \Yiisoft\Router\UrlGeneratorInterface $urlGenerator
 * @var string $csrf
 * @var string $action
 * @var string $title
 */
?>
<?= Html::openTag('div',['class'=>'container py-5 h-100']); ?>
<?= Html::openTag('div',['class'=>'row d-flex justify-content-center align-items-center h-100']); ?>
<?= Html::openTag('div',['class'=>'col-12 col-md-8 col-lg-6 col-xl-8']); ?>
<?= Html::openTag('div',['class'=>'card border border-dark shadow-2-strong rounded-3']); ?>
<?= Html::openTag('div',['class'=>'card-header']); ?>
<?= Html::openTag('h1',['class'=>'fw-normal h3 text-center']); ?>
<?= $translator->translate('i.client_form'); ?>
<?= Html::closeTag('h1'); ?>
<?=
    Form::tag()
    ->post($urlGenerator->generate(...$action))
    ->enctypeMultipartFormData()
    ->csrf($csrf)
    ->id('ClientForm')
    ->open()
?>
<?= 
    $alert; 
?>
<?= Field::errorSummary($form)
    ->errors($errors)
    ->header($translator->translate('invoice.client.error.summary'))
    ->onlyProperties(...['client_name', 'client_surname', 'client_email', 'client_age'])    
    ->onlyCommonErrors()
?>
<?= 
    Html::openTag('div', ['class'=> 'card']),
        Html::openTag('div', ['class'=>'card-header d-flex justify-content-between']), 
            $translator->translate('i.personal_information'),
            Html::openTag('div', ['class' => 'p-2']), 
                Field::checkbox($form, 'client_active')
                ->inputLabelAttributes(['class' => 'form-check-label'])    
                ->enclosedByLabel(true)
                ->inputClass('form-check-input')
                ->ariaDescribedBy($translator->translate('i.client_active')),
            Html::closeTag('div'),
        Html::closeTag('div'),
    Html::closeTag('div')    
?>
            <?php
                $bdate = $datehelper->get_or_set_with_style($form->getClient_birthdate() ?? new \DateTimeImmutable('now'));
                echo Field::text($form, 'client_birthdate')
                ->label($translator->translate('i.birthdate'), ['class' => 'form-label'])
                ->addInputAttributes([
                    'placeholder' => $translator->translate('i.birthdate'),
                    'class' => 'form-control input-sm datepicker',
                    'id' => 'client_birthdate',
                    'role' => 'presentation',
                    'autocomplete' => 'off'
                ])
                ->value($bdate)        
                ->required(false)
                ->readonly(true)        
                ->hint($translator->translate('invoice.hint.this.field.is.not.required')); 
            ?>    
                        <?= Html::closeTag('div'); ?>
                    <?= Html::closeTag('div'); ?>
                <?= Html::closeTag('div'); ?>
            <?= Html::closeTag('div'); ?>
            <?php endif; ?>
        <?= Html::closeTag('div'); ?>
    <?= Html::closeTag('div'); ?>
<?= Html::closeTag('div'); ?>
<?= $button::back_save(); ?>                
<?= Form::tag()->close(); ?>
<?= Html::closeTag('div'); ?>
<?= Html::closeTag('div'); ?>
<?= Html::closeTag('div'); ?>
<?= Html::closeTag('div'); ?>
<?= Html::closeTag('div'); ?>

-1
投票

发票平面解决方案 发生数据库错误 错误号:1525 不正确的日期值:'0000-00-00'修复错误 58 El error se debe al modo sql, que puede ser un modo estricto
解决方案永久为错误的日期值:'0000-00-00'更改此数据示例> 1970-01-01
发票平面/应用程序/模块/发票/模型/Mdl_invoices.php

或临时解决方案 mysql SET GLOBAL sql_mode = '';

ubuntu 20.04 mysql 8

© www.soinside.com 2019 - 2024. All rights reserved.