使用php

时间:2018-10-05 04:34:36

标签: php method-chaining

我正在编写一个脚本,该脚本必须要这样调用:

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

Person::firstName("Soobaasaa")->lastName( "Ozaaraa")->age(17)
  ->setFather( $father )-> toArray();

因此,我们有两个名为PersonFather的类。

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;
    }
}

上面的代码只是结构,我刚刚开始处理脚本。文件结构无法更改,因为这是一个挑战。

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

预先感谢

2 个答案:

答案 0 :(得分:8)

您真正需要的只是静态firstName方法来创建该类的新实例并返回它。

其他设置者只需要返回$this来提供称为fluent interface的内容。

如果创建实例的唯一方法是通过静态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(),
        ];
    }
}

我强烈建议不要将$name属性保持为静态。您不想更改一个实例的$name并让它更改所有其他实例。这就是为什么在上面的示例中将其更改为private $firstName的原因。

答案 1 :(得分:6)

我知道这是一个挑战,因此您可能必须使用特定的类结构。但是还有另一种方法可以做到:

bin2hex(openssl_pseudo_random_bytes(16))

在此版本中,您可以将以受保护变量命名的函数称为静态或非静态。因此,您可以像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 ]; } } 那样做Father::firstName('dad')->lastName('saray'),反之亦然。为简洁起见,我省略了其他方法,例如年龄。

根据评论的要求,会发生以下情况:

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