Способность цепных методов без форсирования нового ключевого слова с использованием php - PullRequest
0 голосов
/ 05 октября 2018

Я работаю над сценарием, который ДОЛЖЕН вызывать так:

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

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

Итак, у нас есть два класса с именами 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;
    }
}

приведенный выше код является просто структурой, и ятолько начал работать над сценарием.Структура файла не может измениться, потому что это сложная задача.

Как мне манипулировать сценарием, чтобы я мог вызывать методы, как я упоминал ранее?

Заранее спасибо

Ответы [ 2 ]

0 голосов
/ 08 октября 2018

Я понимаю, что это сложная задача, поэтому вам, возможно, придется использовать определенную структуру классов.Но есть и другой способ сделать это:

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').Для краткости я не учел другие методы, такие как age.

Как и было запрошено в комментарии, вот что происходит:

Когда вы вызываете firstName() или lastName() как статический, магический метод__callStatic() запущен.Если он обнаружит, что экземпляра нет, он создаст экземпляр, вызовет этот метод и вернет экземпляр.Все последующие вызовы будут обрабатываться магическим методом __call().Это установит свойство и вернет тот же экземпляр.Теперь это означает, что вы можете сначала вызвать firstName() или lastName() как статические, а затем все последующие вызовы будут нестатичными.

0 голосов
/ 08 октября 2018

На самом деле все, что вам нужно, это статические методы 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(),
        ];
    }
}

Я бы настоятельно рекомендовал не сохранять свойство $name как статическое.Вы не хотите изменять $name одного экземпляра, и он должен изменять все остальные.Вот почему я изменил его на private $firstName в моем примере выше.

...