PHP цепочечные методы класса объединены с другими классами - PullRequest
0 голосов
/ 21 февраля 2019

Я начинаю с примера.

Класс пресс-формы

<?php
class Mold {
  public $current;

  function merge($first, $second) {
    $this->current = $first . $second;
    return $this;
  }

  function phone() {
    $this->current = '<a href="tel:' . $this->current . '">' . $this->current . '</a>';
    return $this;
  }

  function __toString() {
    return $this->current;
  }
}

function mold() {
  return new Mold();
}

В действии

Работает, как и ожидалось.

echo mold()->merge('sada', 'asdsa')->phone();

Задача

У меня есть один или несколько классов с методами, которые также должны быть доступны.

Класс плагинов

class MyPlugin {
  function link() {
    // Code
  }

  function currency($number) {
    // Code
  }
}
class MyPlugin2 {
  // Other methods
}

Код мечты

Точное изменение событий ниже может не иметь никакого смысла.В любом случае, я собираюсь сделать следующее:

echo mold()->merge('sada', 'asdsa')->currency(45)-link();
  • Вызов mold(), который создает новый экземпляр класса Mold.
  • Цепочка merge(), котораяиспользуется из класса Mold.
  • currency() или link() метод не существует в классе Mold.Вместо этого они должны быть загружены из одного из плагинов.

В заключение

  • Я знаю, что могу расширить класс, но это на самом деле не решает проблему, потому что может бытьнесколько классов плагинов.
  • Я знаю, что могу создавать экземпляры классов плагинов, но они так или иначе должны знать класс Mold.
  • Добавление методов в классум, а также классы слияния.

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Технически вы могли бы использовать __call() для этого.Ваш «основной» класс может содержать / отслеживать набор экземпляров плагина, и любой неизвестный вызов метода может быть найден и делегирован, если он доступен в плагине.

Я бы не рекомендовал это.Свободные API часто хрупки и могут стать неудобными даже с классом one .Участие нескольких классов в беглых вызовах может быстро привести к путанице.Беспорядок, с которым даже IDE не может помочь вам (или другому человеку, работающему с кодом), так как он не имеет ни малейшего представления о всей происходящей магии.

Я очень рекомендую изучить альтернативные шаблоны для такого API, как этот.

0 голосов
/ 21 февраля 2019

Концепцией, которую вы можете попытаться применить, является Композиция над наследованием .

Решением может быть компоновка текущего объекта Mold и передача двух экземпляров плагинов так, чтобы онможет использовать их в своих методах, например так:

<?php
class Mold {
  public $current;

  public function __construct(Plugin1 $plugin1, Plugin2 $plugin2) {
      $this->plugin1 = $plugin1;
      $this->plugin2 = $plugin2;
  }

  public function merge($first, $second) {
    $this->current = $first . $second;
    return $this;
  }

  public function phone() {
    $this->current = '<a href="tel:' . $this->current . '">' . $this->current . '</a>';
    return $this;
  }

  public function __toString() {
    return $this->current;
  }

  public function link() {
      $this->plugin1->link();
      return $this;
  }
}

function mold() {
  return new Mold(new Plugin1(), new Plugin2());
}

Другим решением может быть создание некоторого класса MoldHandler, который имеет объект Mold в качестве свойства вместе с другими плагинами,который может быть использован внутри этого непосредственно.

public class MoldHanlder {

    protected $mold;
    protected $plugin1;
    protected $plugin2;

    public function __contruct($mold, $plugin1, $plugin2) {
        $this->mold    = $mold;
        $this->plugin1 = $plugin1;
        $this->plugin2 = $plugin2;
    }

    public function merge() {
        $this->mold = $this->mold->merge();
        return $this;
    }

    public function link() {
        $foo = $this->plugin1->method();

        return $this;
    }

    ...
}

Вы также можете просто создать экземпляры классов внутри construct, но если вы планируете писать модульные тесты, внедрение зависимостей - это путь

Я думаю, что первый подход намного лучше, потому что вы избегаете переписывания некоторого кода класса Mold, который не нужен

NB. Это действительно грубое решение, предложенное просто для того, чтобы вы лучшепонять идею, я бы выбрал ура

...