链式方法能力无需使用php的新关键字

Kiy*_*ash 10 php method-chaining

我正在编写一个必须像这样调用的脚本:

$father = Father::firstName('Esaaro')->lastName('Ozaaraa')->age(42);

Person::firstName("Soobaasaa")->lastName( "Ozaaraa")->age(17)
  ->setFather( $father )-> toArray();
Run Code Online (Sandbox Code Playgroud)

所以我们有两个名为Person和的类Father.

firstName两个类的static方法是方法和其他方法public.

这是我的文件结构

<?php

class Person
{
    protected static $name;
    protected $lastName, $age, $father, $result;

    public static function firstName($name = null)
    {
        self::$name = $name;
    }

    public function lastName($lastName = null)
    {
        $this->lastName = $lastName;
    }

    public function age($age = null)
    {
        $this->age = $age;
    }

    public function toArray()
    {

    }

    public function setFather(Father $father)
    {

    }
}


    /*
     * Father Class
     */

class Father
{
    protected static $name;
    protected $family, $age, $result;

    public static function firstName($name = null)
    {
        self::$name = $name;
    }

    public function lastName($lastName = null)
    {
        $this->family = $lastName;
    }

    public function age($age = null)
    {
        $this->age = $age;
    }

    public function toArray()
    {
        ( (isset(static::$name) && static::$name !== null) ? $this->result['firsName'] = self::$name : '' );
        ( (isset($this->family) && $this->family !== null) ? $this->result['lastName'] = $this->family : '' );

        return $this->result;
    }
}
Run Code Online (Sandbox Code Playgroud)

上面的代码只是结构,我刚刚开始编写脚本.文件结构无法改变,因为这是一个挑战.

我应该如何操作我的脚本,我可以调用我之前提到的方法?

提前致谢

Phi*_*hil 8

实际上,您只需要静态firstName方法来创建类的新实例并将其返回.

其他安装只需要返回$this以提供所谓的流畅界面.

如果创建实例的唯一方法是通过静态firstName方法,那么您还需要添加私有/受保护的构造函数.

例如

class Person
{
    private $firstName;
    private $lastName;
    private $age;
    private $father;

    private function __construct(string $firstName) {
        $this->firstName = $firstName;
    }

    public static function firstName(string $name) {
        return new Person($name);
    }

    public function lastName(string $lastName) {
        $this->lastName = $lastName;
        return $this;
    }

    public function age(int $age) {
        $this->age = $age;
        return $this;
    }

    public function setFather(Father $father) {
        $this->father = $father;
        return $this;
    }

    public function toArray() {
        // just an example
        return [
            'firstName' => $this->firstName,
            'lastName'  => $this->lastName,
            'age'       => $this->age,
            'father'    => $this->father->toArray(),
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

我强烈建议不要将$name财产保持为静态.您不希望更改一个实例$name并让其更改所有其他实例.这就是我private $firstName在上面的例子中改变它的原因.


Aar*_*ray 6

我知道这是一个挑战所以你可能必须使用特定的类结构.但还有另一种方法可以做到这一点:

class Father
{
    protected static $instance;

    protected $firstName = '';
    protected $lastName = '';

    public function __call($name, $arguments)
    {
        if (property_exists($this, $name)) {
            $this->$name = array_shift($arguments);
        }

        return $this;
    }

    public static function __callStatic($name, $arguments)
    {
        if (is_null(static::$instance)) {
            static::$instance = new static;
        }

        return static::$instance->$name(...$arguments);
    }

    public function toArray()
    {
        return [
            'firstName' => $this->firstName,
            'lastName' => $this->lastName
        ];
    }
}
Run Code Online (Sandbox Code Playgroud)

在此版本中,您可以将受保护变量命名的函数调用为静态变量.所以,你可以这样做Father::firstName('dad')->lastName('saray'),反之亦然Father::lastName('saray')->firstName('dad').为简洁起见,我省略了其他方法,如年龄.

根据评论中的要求,这是发生的事情:

当您调用firstName()lastName()作为静态时,__callStatic()运行魔术方法.如果它检测到没有实例,它将创建一个实例,调用该方法并返回实例.然后所有未来的调用都将由魔术方法处理__call().这将设置属性并返回相同的实例.现在,这意味着您可以先调用firstName()lastName()作为静态调用,然后所有后续调用都将是非静态调用.