sql >> Databasteknik >  >> RDS >> Mysql

CakePHP 3 tidskolumn läggs till datum

Datum/tid-värden castas alla till samma basstruktur, det vill säga en DateTime eller DateTimeImmutable objekt, och så naturligt kommer värden endast för datum att läggas till ett tidsvärde (00:00:00 ), och tidsvärden kommer med ett datum (det aktuella datumet).

CakePHP kommer att använda specifika underklasser beroende på SQL-datatypen, det vill säga

  • \Cake\I18n\Time eller \Cake\I18n\FrozenTime under TIME , TIMESTAMP och DATETIME
  • \Cake\I18n\Date eller \Cake\I18n\FrozenDate för DATE

I tidigare versioner av CakePHP 3 fanns det bara \Cake\I18n\Time .

Det skulle vara trevligt om det skulle finnas en separat klass för endast tidstypiska typer, som skulle ha ett korrekt standardutmatningsformat för endast tid, men tills något sådant läggs till måste du ta hand om utdataformatet själv .

Formatera i dina vyer

Det är upp till dig hur du ska visa detta i dina vyer. Du kan enkelt använda i18nFormat() metod för Time klassinstans

$record['start_time']->i18nFormat(
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)

eller Time hjälpare, för att bara visa tidsdelen

$this->Time->i18nFormat(
    $record['start_time'],
    [\IntlDateFormatter::NONE, \IntlDateFormatter::SHORT]
)

Antar att det inte skulle skada om bake skulle generera liknande kod beroende på typen av kolumn, du kanske vill föreslå det som en förbättring . Som nämnts kan det också vara värt att överväga att använda ytterligare klasser (eller kanske alternativ) för kolumner med endast tidstyp.

Använd en anpassad tidsklass

Om du hade velat ha det här beteendet överallt där strängrepresentationen av objektet används, utan att manuellt behöva anropa formateraren, kan du använda en utökad \Cake\I18n\Time eller \Cake\I18n\FrozenTime klass med ett åsidosatt $_toStringFormat egenskap, så att den formaterar datumet därefter.

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'); 
// ...

Detta borde i stort sett vara självförklarande, time kolumner som mappas till TimeType , kommer nu att använda App\I18n\FrozenTimeOnly istället för standard Cake\I18n\Time .

DateTimeType::$dateTimeClass är utfasad

För att klara av det kommer en anpassad databastyp att krävas, vilket också är ganska enkelt.

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

Det bör noteras att detta för närvarande kommer att instansiera en data-/tidsklass två gånger, eftersom den överordnade konstruktorn kommer att anropa _setClassName() också, vilket är där en instans av den givna klassen kommer att instansieras.

src/config/bootstrap.php

use App\Database\Type\TimeOnlyType;
Type::map('time', TimeOnlyType::class);

Så vad detta kommer att göra är att åsidosätta standard time typ mappning för att använda den anpassade \App\Database\Type\TimeOnlyType klass, som i sin tur kommer att använda \App\I18n\TimeOnly klass när databasvärden konverteras till PHP-objekt, som när de konverteras till en sträng kommer att använda endast tidsformatet.

Se även



  1. Använda INSERT med en PostgreSQL-databas med Python

  2. Undvik dubbla citattecken med variabel inuti HTML-eko

  3. django.db.utils.ProgrammingError:relation app_user existerar inte under manage.py-testet

  4. Problem med att anropa lagrad procedur från C# med stor CLOB