Doctrine 中的 AFAIK 但不支持 postgres 间隔。但是,可以编写列的自定义映射以及 dbal 类型。这是一个例子:
#[ORM\Column(type: 'carbon_interval', columnDefinition: 'INTERVAL NOT NULL')]
private CarbonInterval $duration;
碳的包装类型:
#[Immutable]
final class CarbonIntervalPostgresType extends DateIntervalPostgresPostgresType
{
public const NAME = 'carbon_interval';
public function convertToPHPValue($value, AbstractPlatform $platform): ?CarbonInterval
{
//1 years 0 mons 0 days 0 hours 0 mins 0.0 secs
$interval = parent::convertToPHPValue($value, $platform);
if ($interval instanceof DateInterval) {
$interval = CarbonInterval::instance($interval);
}
return $interval;
}
}
覆盖dateinterval
学说类型以使用 postgres 格式。请注意,在现有的代码库中,它可能会破坏很多东西,所以要小心,如果你不确定不要覆盖。
#[Immutable]
class DateIntervalPostgresPostgresType extends IntervalPostgresType
{
public const NAME = Types::DATEINTERVAL;
}
Next 类负责提供适当的 postgresql 间隔格式和 php DateInterval 转换。顺便说一句,如果您定义getSQLDeclaration
,那么您甚至不需要手动编写 columnDefinition 。
#[Immutable]
class IntervalPostgresType extends Type
{
public const NAME = 'interval';
/** @see \Doctrine\DBAL\Types\Type::getName() */
public function getName(): string
{
return static::NAME;
}
/** @see \Doctrine\DBAL\Types\Type::getSQLDeclaration() */
public function getSQLDeclaration(array $fieldDeclaration, AbstractPlatform $platform): string
{
return static::NAME;
}
/** @see \Doctrine\DBAL\Types\Type::convertToDatabaseValue() */
public function convertToDatabaseValue($value, AbstractPlatform $platform)
{
if ($value === null) {
return null;
}
if (!$value instanceof DateInterval) {
throw new InvalidArgumentException('Interval value must be instance of DateInterval');
}
$parts = array(
'y' => 'year',
'm' => 'month',
'd' => 'day',
'h' => 'hour',
'i' => 'minute',
's' => 'second',
);
$sql = '';
foreach ($parts as $key => $part) {
$val = $value->{$key};
if (empty($val)) {
continue;
}
$sql .= " {$val} {$part}";
}
return trim($sql);
}
/**
* @throws ConversionException
* @see \Doctrine\DBAL\Types\Type::convertToPHPValue()
*/
public function convertToPHPValue($value, AbstractPlatform $platform): ?DateInterval
{
if ($value === null) {
return null;
}
$matches = array();
preg_match(
'/(?:(?P<y>[0-9]+) (?:year|years))?'
.' ?(?:(?P<m>[0-9]+) (?:months|month|mons|mon))?'
.' ?(?:(?P<d>[0-9]+) (?:days|day))?'
.' ?(?:(?P<h>[0-9]{2}):(?P<i>[0-9]{2}):(?P<s>[0-9]{2}))?/i',
$value,
$matches
);
if (empty($matches)) {
throw ConversionException::conversionFailed($value, static::NAME);
}
$interval = new DateInterval('PT0S');
if (!empty($matches['y'])) {
$interval->y = (int)$matches['y'];
}
if (!empty($matches['m'])) {
$interval->m = (int)$matches['m'];
}
if (!empty($matches['d'])) {
$interval->d = (int)$matches['d'];
}
if (!empty($matches['h'])) {
$interval->h = (int)$matches['h'];
}
if (!empty($matches['i'])) {
$interval->i = (int)$matches['i'];
}
if (!empty($matches['s'])) {
$interval->s = (int)$matches['s'];
}
return $interval;
}
}