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
对象时再次将其合并在一起,另外一点:是否有可能从UNIXTimestamp
返回到DateTime
对象?我的意思是,据我所知,当你用Timestamp
s计算时间间隔时,不可能得到一个准确的日期,只是接近,但不准确,因为Timestamp
s不考虑闰年等等。这可能是您的解决方案中尚未解决的一点。请告诉我怎么做或向我解释。欢迎对此提出任何意见。@delboy1978uk你也要注意时区converToDateTime()
需要一个可选的第二时区参数。不过,这是一个很好的解决方案。