Mysql
 sql >> Base de Dados >  >> RDS >> Mysql

A coluna de tempo do CakePHP 3 recebe a data adicionada


Os valores de data/hora estão sendo convertidos para a mesma estrutura base, que é um DateTime ou DateTimeImmutable e, portanto, valores somente de data terão um valor de hora adicionado (00:00:00 ), e os valores somente de hora vêm com uma data (a data atual).

O CakePHP usará subclasses específicas dependendo do tipo de dados SQL, ou seja,
  • \Cake\I18n\Time ou \Cake\I18n\FrozenTime por TIME , TIMESTAMP e DATETIME
  • \Cake\I18n\Date ou \Cake\I18n\FrozenDate para DATE

Nas versões anteriores do CakePHP 3 havia apenas \Cake\I18n\Time .

Seria bom se houvesse uma classe separada para tipos somente de tempo, que teria um formato de saída padrão somente de tempo adequado, mas até que algo assim seja adicionado, você terá que cuidar do formato de saída você mesmo .

Formatar em suas visualizações


Cabe a você como exibir isso em suas visualizações. Você pode facilmente usar o i18nFormat() método do Time instância de classe
$record['start_time']->i18nFormat(
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)

ou o Time auxiliar, para mostrar apenas a parte do tempo
$this->Time->i18nFormat(
    $record['start_time'],
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)

Acho que não faria mal se o bake gerar um código semelhante de acordo com o tipo de coluna, você pode querer sugerir isso como um aprimoramento . Como mencionado, usar classes adicionais (ou talvez opções) para colunas somente de tempo pode ser algo que vale a pena considerar também.

Use uma classe de tempo personalizada


Se você quisesse esse comportamento em todos os lugares em que a representação de string do objeto estivesse sendo usada, sem precisar invocar manualmente o formatador, você poderia usar um \Cake\I18n\Time estendido ou \Cake\I18n\FrozenTime classe com um $_toStringFormat substituído propriedade, para que formate a data de acordo.

src/I18n/FrozenTimeOnly.php
namespace App\I18n;

use Cake\I18n\FrozenTime;

class FrozenTimeOnly extends FrozenTime
{
    protected static $_toStringFormat = [
        \IntlDateFormatter::NONE,
        \IntlDateFormatter::SHORT
    ];
}

src/config/bootstrap.php
use Cake\Database\Type\TimeType;
use App\I18n\FrozenTimeOnly;
TimeType::$dateTimeClass = FrozenTimeOnly::class;

// remove the default `useImmutable()` call, you may however
// want to keep further calls for formatting and stuff
Type::build('time'); 
// ...

Isso deve ser autoexplicativo, time colunas que estão sendo mapeadas para TimeType , agora usará App\I18n\FrozenTimeOnly em vez do padrão Cake\I18n\Time .

DateTimeType::$dateTimeClass está obsoleto


Para lidar com isso, será necessário um tipo de banco de dados personalizado, o que também é bastante simples.

src/Database/Type/TimeOnlyType.php
namespace App\Database\Type;

use App\I18n\FrozenTimeOnly;
use Cake\Database\Type\TimeType;

class TimeOnlyType extends TimeType
{
    public function __construct($name)
    {
        parent::__construct($name);
        $this->_setClassName(FrozenTimeOnly::class, \DateTimeImmutable::class);
    }
}

Deve-se notar que atualmente isso instanciará uma classe de dados/tempo duas vezes, pois o construtor pai invocará _setClassName() também, que é onde uma instância da classe dada será instanciada.

src/config/bootstrap.php
use App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);

Então, o que isso fará é substituir o time padrão mapeamento de tipo para usar o \App\Database\Type\TimeOnlyType personalizado classe, que por sua vez usará a classe \App\I18n\TimeOnly class ao converter valores de banco de dados em objetos PHP, que quando convertidos em uma string, usarão o formato somente de tempo.

Veja também