2016-12-24 3 views
2

Я пытаюсь разработать свою собственную структуру ORM поверх PDO, которая следует концепции Active Record и проста в использовании. Погрузившись в нее, я понял, что каждая реляционная база данных имеет собственное представление о типах данных даты и времени. Я хотел бы использовать в своем ORM только PHP DateTime и сопоставить его с базовыми RDBMS, чтобы мы могли использовать преимущества этих типов данных. Но я не уверен, если это возможно, просто подумайте о сравнении между периодом и так далее. На самом деле, это также и то, что DBAL Doctrine, похоже, не волнует. Они просто говорят not supported о разных типах данных для даты и времени, когда речь идет о различиях.Возможно ли иметь средство отображения DateTime для каждой подстилающей СУБД?

То, что я хочу что-то вроде этого:

MySQL:  PHP DateTime => maps to MySQL DateTime field 
PostgreSQL: PHP DateTime => maps to a splitted date field and a time field 
Oracle:  PHP DateTime => maps to TIMESTAMP 
... 

Пользователь должен быть в состоянии установить его DateTime поле с помощью метода сеттер на этом реляционную объекта. Когда выполняется выбор, вставка, обновление или удаление, он должен быть сопоставлен с тем, что, возможно, разделенное поле даты и времени. То же самое должно появиться, если пользователь запрашивает это значение через метод getter.

Пожалуйста, расскажите мне, как это возможно, и также дайте несколько примеров. Большое спасибо! :-)

Редактирование: Я немного поиграл с адаптером, как указано ниже. Я думаю, что это решает проблему:

<?php 
namespace Diana\Core\Persistence\Sql\Dbal\Gateway; 

interface IAdapter 
{ 
    /** 
    * Drills an DateTime instance down to underlaying RDBMS date and time string. 
    * 
    * @param \DateTime $date 
    * @return string 
    */ 
    public function drillDownDateTime(\DateTime $date); 


    /** 
    * Parse the RDBMS rows back to an DateTime instance. 
    * 
    * @param array $rows 
    * @return \DateTime 
    */ 
    public function parseDateTime(array $rows); 
} 


<?php 
namespace Diana\Core\Persistence\Sql\Dbal\Gateway; 

class OracleAdapter implements IAdapter 
{ 
    const FORMAT = 'Y-m-d H:i:s e'; 
    /** 
    * @inheritdoc 
    */ 
    public function drillDownDateTime(\DateTime $date) 
    { 
     return $date->format(self::FORMAT); 
    } 

    /** 
    * @inheritdoc 
    */ 
    public function parseDateTime(array $rows) 
    { 
     return \DateTime::createFromFormat(self::FORMAT, $rows[0]); 
    } 
} 

<?php 
namespace Diana\Core\Persistence\Sql\Dbal\Gateway; 

class PostgreSqlAdapter implements IAdapter 
{ 
    const FORMAT = 'Y-m-d H:i:s e'; 

    /** 
    * @inheritdoc 
    */ 
    public function drillDownDateTime(\DateTime $date) 
    { 
     return $date->format(self::FORMAT); 
    } 

    /** 
    * @inheritdoc 
    */ 
    public function parseDateTime(array $rows) 
    { 
     return \DateTime::createFromFormat(self::FORMAT, $rows[0]); 
    } 
} 

Как я нашел в документации в

Oracle

MySQL

PostgreSQL

Это должно работать. В MySQL часовой пояс - это настройка в базе данных, поэтому мы ничего не можем позаботиться. Это также просто пример. Но эти файлы в готовой версии скоро станут частью моего framework. Из-за моего собственного класса Date, который автоматически выводит локальную строку даты при выводе, мы используем DateTime в качестве параметра здесь, так что оба могут быть переданы.

+0

Я думаю, что все три поддержки UNIX метки времени. Это может стоить изучить. – vascowhite

+0

Я уже посмотрел. Временные метки тоже отличаются. Некоторые используют UNIX-эпоху, другие используют временные метки с Рождества в качестве своего года 0 и т. Д. И я не уверен, как они сохраняются в базе данных. Поскольку обычно timestamps не заботятся о високосных годах и летнее время и т. Д. – alpham8

+0

Вид объясняет подход Doctrine тогда :) – vascowhite

ответ

1

Создайте интерфейс адаптера!

<?php 

interface DbAdapterInterface 
{ 
    /** 
    * @param DateTime $date 
    * @return string 
    */ 
    public function convertFromDateTime(DateTime $date); 

    /** 
    * @param DateTime $date 
    * @return array 
    */ 
    public function convertToDateTime(array $row); 
} 

class MySqlAdapter implements DbAdapterInterface 
{ 
    public function convertFromDateTime(DateTime $date) 
    { 
     return $date->format('Y-m-d H:i:s'); 
    } 

    public function convertToDateTime(array $row) 
    { 
     return new DateTime($row['date']); 
    } 
} 

class OracleAdapter implements DbAdapterInterface 
{ 
    public function convertFromDateTime(DateTime $date) 
    { 
     return $date->getTimestamp(); 
    } 

    public function convertToDateTime(array $row) 
    { 
     return new DateTime('@'.$row['date']); 
    } 
} 

class Db 
{ 
    /** @var DbAdapterInterface $adapter */ 
    private $adapter; 

    public function setAdapter(DbAdapterInterface $adapter) 
    { 
     $this->adapter = $adapter; 
    } 

    public function insert($data) 
    { 
     $date = $data['date']; 
     $dateString = $this->adapter->convertFromDateTime($date); 
     // do your insert 
     return $dateString; 
    } 

    public function findById($id) 
    { 
     // fetch row by id here, this is just an example, I'm using the id as the date string 
     $row = ['date' => $id]; 
     $row = $this->adapter->convertToDateTime($row); 
     // do your insert 
     return $row; 
    } 
} 


// Example 

$data = [ 
    'date' => new DateTime(),  
]; 

$db = new Db(); 
$db->setAdapter(new MySqlAdapter()); 
echo $db->insert($data)."\n"; 
$db->setAdapter(new OracleAdapter()); 
echo $db->insert($data)."\n"; 

$time = '1493308146'; 
var_dump($db->findById($time)); 

$db->setAdapter(new MySqlAdapter()); 
$time = '2014-09-18 22:00:00'; 
var_dump($db->findById($time)); 

Смотрите здесь для рабочего примера: https://3v4l.org/pYgbE

+0

Хорошо, спасибо, что решает одно направление. Но мне это нужно двунаправлено. Я имею в виду преобразование поля даты и времени из базы данных обратно в объект PHP DateTime. Эта архитектура интерфейса - отличная идея. Пожалуйста, отредактируйте свой ответ немного, чтобы полностью удовлетворить мои потребности. – alpham8

+0

Я добавил еще один метод интерфейса и обновил ответ.:-) – delboy1978uk

+0

Большое спасибо за ваше участие. Но я в настоящее время не уверен, если это действительно решает мою проблему. Теперь я попытаюсь объяснить вам другие слова, что мне нужно: в принципе, мне нужен слой абстракции, так что программист использует только объекты DateTime для взаимодействия с CRUD в базе данных подкласса. Это означает, что картограф должен разделить его на дату и время, если это необходимо, и должен объединить его снова вместе, когда данные были прочитаны и готовы снова собраться в объекты DateTime, чтобы он вписывался в его атрибут класса ORM еще раз. – alpham8

Смежные вопросы