Как заставить мою PHP IDE понимать контейнеры внедрения зависимостей? - PullRequest
63 голосов
/ 18 июня 2011

Текущая ситуация: в моем проекте есть зависимости, которые я решаю с помощью внедрения зависимостей.Я хочу сделать следующий логический шаг, используя контейнер ввода зависимостей (DIC), чтобы упростить управление моими зависимостями и ленивые классы загрузки.

Я посмотрел на Bucket , Pimple и sfServiceContainer , провели некоторый тест и по-настоящему оценили работу DIC.Я бы, наверное, выбрал Pimple из-за его простоты и грубой силы.Если у меня не было этой проблемы:

Из-за абстракции, которую предлагает DIC, используемая мной среда IDE (PHPStorm) больше не понимает, что происходит в моем коде.Он не понимает, что $ container ['mailer'] или $ sc-> mailer содержит объект класса.Я также попробовал IDE Netbeans: та же проблема.

Это действительно проблема для меня, потому что моя IDE становится бесполезной.Я не хочу программировать без подсказок кода, автозаполнения и инструментов рефакторинга при работе с классами.И я не хочу, чтобы моя IDE находила всевозможные ложные срабатывания при проверке кода.

Поэтому мой вопрос: кто-нибудь имел дело с этой проблемой и нашел решение?

Ответы [ 6 ]

57 голосов
/ 18 июня 2011

Вы можете определить класс переменной «вручную»:

/** @var YourClassType $mailer */
$mailer = $container['mailer'];

В PhpStorm (и по стандартам ) используйте две звездочки и запишите тип данных перед именемпеременная.

Вы можете записать тип данных без имени переменной (но не имя без типа данных).

44 голосов
/ 21 июня 2011

Хотя вы, безусловно, можете указать своей IDE тип объекта, извлекаемого из контейнера каждый раз, когда вы получаете к нему доступ, лучше сделать это один раз. Оба из следующих решений включают создание подкласса контейнера. Я только начал использовать Pimple, который все равно рекомендует это делать.

Для контейнеров, в которых используются члены экземпляра, доступ к которым осуществляется с помощью -> или предоставляется с помощью волшебного метода __get, вы можете сообщить своей IDE, какой тип они содержат. Это здорово, потому что он не требует дополнительного анализа при запуске кода - он беспокоит только IDE.

/**
 * My container. It contains things. Duh.
 *
 * @property MyService $service
 * @property MyDao $dao
 */
class MyContainer extends Container { }

Для Pimple и других контейнеров, которые действуют как массивы, вы можете создавать функции доступа для объектов верхнего уровня, которые вам понадобятся. Хотя это означает, что при создании контейнера требуется больше разбора, это следует сделать один раз и сохранить в APC. В любом случае, я предпочитаю метод, а не доступ к массиву, поскольку он помещает легко забываемый ключ массива в автоматически завершенный метод.

class MyContainer extends Pimple
{
    /**
     * @return MyService
     */
    public function getMyService() {
        return $this['service'];
    }
}

Кстати, для встроенных переменных с подсказками типов с @var в NetBeans необходимо использовать /* с одной звездочкой . Это , а не комментарий блока документов и не работает с /** или //. Также имя предшествует типу.

public function foo() {
    /* @var $service MyService */
    $service = $container['service'];
    ...
}
13 голосов
/ 18 июня 2011

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

Netbeans / Phpstorm / PDT / ZendStudio Пример

/* @var $mailer MailerInterface */
$mailer = $sc->mailer

Код завершения начинается сснова работать на $mailer.

Для PDT важно, чтобы:

  1. Комментарий начинался только с одного *.
  2. Сначала имя переменной, чемподсказка.

Альтернативные варианты комментариев

Поскольку это было предметом большого обсуждения, оно может отличаться в разных IDE.Однако большинство IDE поддерживают подсказки переменных для встроенных кодовых переменных описанным выше способом.Так что в зависимости от IDE это может быть написано по-разному, но похоже, как здесь с двумя звездочками впереди:

/** @var $mailer MailerInterface */

Совместимость с PHPDoc

У парсеров PHPDoc могут возникнуть проблемыесли вы имитируете doc-комментарий класса var для встроенного кода следующим образом:

/** @var MailerInterface $mailer  */

Эта документация обычно используется для переменных класса ( @ var - Документируйте тип данных переменной класса ).После этого в PHPDoc отсутствует определение переменной класса после комментария, что влечет за собой бремя для QA.

Однако некоторые IDE предлагают дополнения кода и для простых переменных, когда они написаны в стиле clas-variable PHPDoc.Я не знаю, есть ли у этого побочные эффекты для завершения кода текущего класса, тогда как новый член мог бы быть представлен, который фактически не существует.

7 голосов
/ 15 января 2017

Для тех, кто пришел сюда из гугла.

PHPStorm на самом деле предоставляет способ решения этой проблемы вместо того, чтобы писать PHPDocs снова и снова - создавая и устанавливая файл .phpstorm.meta.php способом , описанным здесь , обеспечивает бесперебойную работу автозаполнения и проверки типов.

1 голос
/ 09 марта 2016

Я знаю, что вопрос касается только DIC, но есть поставщик услуг Silex Pimple Dumper , который создает дамп контейнера в файл json. Тот же автор написал плагин для PHPStorm , который может прочитать этот файл и открыть автозаполнение с именами служб и их типом (класс, строка и т. Д.). Я использую эти два компонента и могу сказать, что это хорошие варианты для автозавершения для Silex / Pimple.

0 голосов
/ 07 июля 2012

Прыщ просто представьте контейнеростроителю принцип.Если вы понимаете это, вам больше не нужен Pimple:


class Container
{
    private $shared = array();

    public function getService() {
        return new Service(
            this->getFirstDependence(),
            this->getSecondDependence()
        );
    }

    protected function getFirstDependence() {
        return new FirstDependence(
            this->getSecondDependence()
        );
    }

    protected function getSecondDependence() {
        return isset($this->shared[__METHOD__]) ? $this->shared[__METHOD__] : $this->shared[__METHOD__] =
        new SecondDependence(
        );
    }
}

Таким образом, Pimple не скрывает тип объекта в смешанном $ c ['some key'].Вы будете иметь предложения автозаполнения при редактировании вашего контейнера.Phpstorm может автоматически восстанавливать тип возврата метода из вашего кода.И у вас будет чистый контейнер.Вы можете когда-либо переопределить контейнер:


class TestContainer extends Container
{
    protected function getFirstDependence() {
        return new FirstDependenceMock(
        );
    }
}

Если быть честным, контейнер, написанный на языке программирования, - неправильный путь.Ответственность за контейнер заключается в том, чтобы доставить инициализированный граф объектов вызывающей стороне.Доступ к «языку программирования» позволяет легко нарушать эту ответственность.Некоторые DSL для настройки зависимости лучше.Более того, Pimple и sfDepenencyContainer просто игнорируют большую часть исходной информации о зависимостях (аргументы типов конструкторов), что делает вашу конфигурацию раздутой и хрупкой.

...