Как я могу использовать PHP IDE для контейнеров для инъекций зависимостей?

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

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

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

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

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

Ответ 1

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

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

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

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

Ответ 2

В то время как вы можете, конечно, указать своей 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'];
    }
}

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

public function foo() {
    /* @var $service MyService */
    $service = $container['service'];
    ...
}

Ответ 3

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

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

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

Код завершает работу снова на $mailer.

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

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

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

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

/** @var $mailer MailerInterface */

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

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

/** @var MailerInterface $mailer  */

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

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

Ответ 4

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

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

Ответ 5

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

Ответ 6

Pimple просто вводит принцип построения контейнера. Если вы это понимаете, вам больше не нужен 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 для настройки зависимости лучше. Более того, большинство исходных данных зависимостей (аргумент typehints конструкторов) просто игнорируются Pimple и sfDepenencyContainer, что делает вашу конфигурацию раздутой и хрупкой.