So I got this idea from Laravel. With Laravel you can do something like the following.
$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. 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.
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. There is only one instance property in your project, it's a class property of 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 ;)
The whole concept of having a "singleton-like" $instance structure is probably going to cause more problems later on, anyway. 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.
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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.