Сделать DateTime:: createFromFormat() вернуть дочерний класс вместо родительского
Я расширяю DateTime
, добавляю полезные методы и константы.
При использовании new
для создания нового объекта все в порядке, но при использовании статического метода createFromFormat
он всегда возвращает исходный объект DateTime
, и, конечно, ни один из дочерних методов не доступен.
Я использую следующий код, чтобы обойти эту проблему. Это лучший подход?
namespace NoiseLabs\DateTime;
class DateTime extends \DateTime
{
static public function createFromFormat($format, $time)
{
$ext_dt = new self();
$ext_dt->setTimestamp(parent::createFromFormat($format, time)->getTimestamp());
return $ext_dt;
}
}
Ответы
Ответ 1
Это путь. Однако, поскольку вы хотите сделать класс DateTime расширяемым, я бы предложил использовать static
вместо self
:
namespace NoiseLabs\DateTime;
class DateTime extends \DateTime
{
static public function createFromFormat($format, $time)
{
$ext_dt = new static();
$parent_dt = parent::createFromFormat($format, $time);
if (!$parent_dt) {
return false;
}
$ext_dt->setTimestamp($parent_dt->getTimestamp());
return $ext_dt;
}
}
Это не обязательно, если вы не планируете расширять класс, но если кто-то это сделает, это не позволит ему снова сделать то же обходное решение.
Ответ 2
Я думаю, ваше решение в порядке. Альтернативный способ (просто реорганизованный бит) заключается в следующем:
public static function fromDateTime(DateTime $foo)
{
return new static($foo->format('Y-m-d H:i:s e'));
}
public static function createFromFormat($f, $t, $tz)
{
return static::fromDateTime(parent::createFromFormat($f, $t, $tz));
}
Я не уверен, что лучший способ реализовать fromDateTime
. Вы даже можете взять то, что у вас есть, и поместить его туда. Просто не теряйте часовой пояс.
Обратите внимание, что вы даже можете реализовать __callStatic
и использовать немного отражения, чтобы сделать это будущим доказательством.
Ответ 3
class DateTimeEx extends DateTime
{
static public function createFromFormat($format, $time, $object = null)
{
return new static(DateTime::createFromFormat($format, $time, $object)->format(DateTime::ATOM));
}
}
Ответ 4
Предыдущие решения пренебрегают часовыми поясами и микросекундами, поэтому мое небольшое улучшение уже здесь. Я предпочитаю вариант 1, но с точки зрения производительности 2 может быть немного быстрее на старых PHP.
class NDateTimeImmutable extends \DateTimeImmutable
{
public static function createFromFormat1($format, $time)
{
$parent = parent::createFromFormat($format, $time);
if (!$parent) {
return false;
}
//Seting timezone like this and not by format to preserve timezone format
$static = new static($parent->format('Y-m-d\TH:i:s.u'), $parent->getTimezone());
return $static;
}
public static function createFromFormat2($format, $time)
{
$parent = parent::createFromFormat($format, $time);
if (!$parent) {
return false;
}
$serialized = serialize($parent);
// numbers can be computed by strlen()
// eg. strlen(parent::class) = 17 but it is slow
$serialized = strtr($serialized, ['17:"'.parent::class => '18:"'.static::class]);
return unserialize($serialized);
}
}