所以我从Laravel那里得到了这个想法。使用Laravel,您可以执行以下操作。
$user = new User;
$user->where('name', 'george')->get();
// which is the same as...
User::where('name', 'george')->get();
所以我猜测User类有一个__callStatic设置,所以它将一个新实例作为后备。我能够使用以下代码复制它。
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);
}
}
但是当我尝试多次继承该类时会出现问题。我希望所有类都能够继承__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
答案 0 :(得分:1)
您遇到的问题是由于$ instance属性是静态的,并在父类上声明。项目中只有一个实例属性,它是Driver的类属性。
有几种方法可以解决这个问题。您可以在子类上定义$ instance,将Driver :: $ instance作为map(array)作为[className =>实例],或者更好的是,完全摆脱那片全球状态;)
拥有" singleton-like"无论如何,$ instance结构可能会在以后导致更多问题。请考虑以下示例:
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仍指向原始实例,但由于Foo :: named(' bob')将名称bob分配给同一个实例,因此您不小心将Alice重命名为Bob。
您可能正在寻找的更像是:
abstract class Driver
{
public static function __callStatic(string $name, array $arguments)
{
$instance = new static;
$instance->$name(...$arguments);
return $instance;
}
}
这样,您每次都会创建新实例。