使DateTime::createFromFormat()返回子类而不是父类

11

我正在扩展 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;
    }
}

好的。感谢您的审核,@lonesomeday。 - noisebleed
4个回答

14

这是正确的做法。但是,由于你似乎想要渲染可扩展的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;
    }
}

如果您不打算扩展该类,则没有必要这样做,但是如果将来有人需要扩展该类,这将防止他再次执行同样的解决方法。


没错,这是一个好的实践,感谢你引入了static。我本来希望能够模仿createFromFormat并将self替换为static,但由于DateTime是一个C实现,所以我猜没有其他办法了,对吗? - noisebleed

1

我认为你的解决方案很好。一种另外的方法(只是稍微重构了一下)如下:

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并使用一些反射来使其具备未来的可扩展性。


1
以前的解决方案忽略了时区和微秒,所以我的小改进在这里。我更喜欢变体1,但在旧版PHP上,性能方面变体2可能会更快一点。
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);
    }
}


0
class DateTimeEx extends DateTime
{
    static public function createFromFormat($format, $time, $object = null)
    {
        return new static(DateTime::createFromFormat($format, $time, $object)->format(DateTime::ATOM));
    }
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接