Php 是否有可能为每个底层RDBMS提供一个日期时间映射器?

Php 是否有可能为每个底层RDBMS提供一个日期时间映射器?,php,datetime,pdo,rdbms,Php,Datetime,Pdo,Rdbms,我正试图在PDO的基础上开发自己的ORM框架,该框架遵循活动记录的概念,并且易于使用。在深入研究时,我发现,每个关系数据库都对日期和时间数据类型有自己的理解。我想在ORM中只使用PHP的DateTime,并将其映射到底层RDBMS,以便我们可以利用这些数据类型的优势。但我不确定,如果可能的话,想想一个时期和其他时期之间的比较。实际上,这也是Doctrine的DBAL似乎不关心的地方。当涉及到日期和时间的差异时,他们只是在不同的数据类型上说不受支持 我想要的是这样的东西: MySQL:

我正试图在
PDO
的基础上开发自己的ORM框架,该框架遵循活动记录的概念,并且易于使用。在深入研究时,我发现,每个关系数据库都对日期和时间数据类型有自己的理解。我想在ORM中只使用PHP的
DateTime
,并将其映射到底层RDBMS,以便我们可以利用这些数据类型的优势。但我不确定,如果可能的话,想想一个时期和其他时期之间的比较。实际上,这也是Doctrine的DBAL似乎不关心的地方。当涉及到日期和时间的差异时,他们只是在不同的数据类型上说
不受支持

我想要的是这样的东西:

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
...
用户应该能够在该关系对象上使用setter方法设置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]);
    }
}

创建适配器接口

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

我认为这三个都支持unix时间戳。那可能值得探索。我已经看过了。时间戳也不同。有些人使用UNIX纪元,另一些人使用自诞生以来的时间戳作为他们的0年,等等。。我不确定它们是如何保存到数据库的。因为时间戳通常不关心闰年和夏令时等。这有点解释了条令的方法:)在每个系统中始终有效的一个日期/时间存储是一个整数形式的Unix时间戳。不要担心不同格式的本机存储,因为大多数DBs都有可以处理时间戳的本机函数,并且在许多情况下可以使用简单的数学。时区是一个单独的问题,可以存储在单独的字段中。使您的代码非常简单和通用。好的,谢谢,这解决了一个方向。但我需要它。我的意思是,将日期和时间字段从数据库转换回PHP DateTime对象。这种接口架构是一个好主意。请编辑您的答案以完全符合我的需要。我添加了另一个接口方法,并更新了答案。:-)非常感谢您的订婚。但我目前不确定,这是否真的解决了我的问题。现在我将试着用另一种语言向您解释我需要什么:基本上,我需要一个抽象层,这样程序员只处理
DateTime
对象,以便
CRUD
与底层数据库交互。这意味着,如果需要,映射器应将其拆分为日期和时间,并应在读取数据并准备再次构建为
DateTime
对象时再次将其合并在一起,另外一点:是否有可能从UNIX
Timestamp
返回到
DateTime
对象?我的意思是,据我所知,当你用
Timestamp
s计算时间间隔时,不可能得到一个准确的日期,只是接近,但不准确,因为
Timestamp
s不考虑闰年等等。这可能是您的解决方案中尚未解决的一点。请告诉我怎么做或向我解释。欢迎对此提出任何意见。@delboy1978uk你也要注意时区
converToDateTime()
需要一个可选的第二时区参数。不过,这是一个很好的解决方案。