[英]PHP use static function to create new instance w/ Inheritance
So I got this idea from Laravel. 所以我从Laravel那里得到了这个主意。 With Laravel you can do something like the following.
使用Laravel,您可以执行以下操作。
$user = new User;
$user->where('name', 'george')->get();
// which is the same as...
User::where('name', 'george')->get();
So I'm guessing the User class has a __callStatic setup so it makes a new instance as a fallback. 因此,我猜测User类具有__callStatic设置,因此它使新实例成为后备。 I was able to replicate that using the following code.
我能够使用以下代码复制该代码。
class Driver
{
protected static $instance = null;
public static function __callStatic($name, $args) {
$classname = get_called_class();
if (empty(static::$instance)) static::$instance = new $classname;
return static::$instance->$name(...$args);
}
}
But a problem occurs when I try to inherit the class more than once. 但是,当我尝试多次继承该类时,就会出现问题。 I want all classes to be able to inherit the __callStatic and be able to call any of their ancestor's public functions statically.
我希望所有类都能够继承__callStatic并能够静态调用其祖先的任何公共函数。
class A extends Driver
{
public function hello() {
echo "hello";
return $this;
}
public function world() {
echo " world";
return $this;
}
}
class B extends A
{
public function name() {
echo "\nMy Name is George";
return $this;
}
}
class C extends B
{
// class can be empty
}
C::hello()->world()->name();
// returns: hello world
// My name is George
The problem you face is due to the $instance property being static, and declared on the parent class. 您遇到的问题是由于$ instance属性是静态的,并且在父类上声明的。 There is only one instance property in your project, it's a class property of Driver.
您的项目中只有一个实例属性,它是Driver的类属性。
There are several ways around this. 有几种解决方法。 You could define $instance on the subclasses, make Driver::$instance a map (array) as [className => instance], or better yet, get rid of that piece of global state entirely ;)
您可以在子类上定义$ instance,将Driver :: $ instance作为地图(数组)作为[className => instance],或者更好的是,完全摆脱该全局状态;)
The whole concept of having a "singleton-like" $instance structure is probably going to cause more problems later on, anyway. 无论如何,具有“类似单例”的$ instance结构的整个概念可能会在以后引起更多的问题。 Consider the following example:
考虑以下示例:
class Foo extends Driver
{
private $name;
public function named(string $name) : self
{
$this->name = $name;
return $this;
}
public function name() : string
{
return $this->name;
}
}
$alice = Foo::named('Alice');
$bob = Foo::named('Bob');
echo $alice->name(); // Outputs "Bob"!
$alice still points to the original instance, but since Foo::named('bob') assigns the name bob to that very same instance, you accidentally renamed Alice into Bob. $ alice仍然指向原始实例,但是由于Foo :: named('bob')将名称bob分配给了相同的实例,因此您不小心将Alice重命名为Bob。
What you're probably looking for is more like: 您可能正在寻找的更像是:
abstract class Driver
{
public static function __callStatic(string $name, array $arguments)
{
$instance = new static;
$instance->$name(...$arguments);
return $instance;
}
}
That way, you'll create new instances every time. 这样,您每次都会创建新实例。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.