Текущая ситуация: у меня есть зависимости в моем проекте, которые я решаю, используя инъекцию зависимостей. Я хочу сделать следующий логический шаг, используя контейнер инъекций зависимостей (DIC), чтобы облегчить управление моими зависимостями и классами ленивой загрузки.
Я посмотрел на Bucket , Pimple и sfServiceContainer , провел несколько тестов и действительно оценил работу DIC. Я, вероятно, поеду за Пимплом из-за его простоты и сырой силы. Если бы у меня не было этой проблемы:
Из-за абстракции, которую предлагает DIC, IDE, которую я использую (PHPStorm), больше не понимает, что происходит в моем коде. Он не понимает, что $ container ['mailer'] или $ sc-> mailer содержит объект класса. Я также попробовал Netbeans IDE: та же проблема.
Это действительно проблема для меня, потому что моя IDE становится бесполезной. Я не хочу программировать без подсказок кода, средств автозаполнения и рефакторинга при работе с классами. И я не хочу, чтобы моя IDE находила всевозможные ложные срабатывания при проверке кода.
Поэтому мой вопрос: кто-нибудь справился с этой проблемой и нашел решение?
Вы можете определить класс переменной «вручную»:
/** @var YourClassType $mailer */ $mailer = $container['mailer'];
В PhpStorm (и по стандарту ) используйте две звездочки и напишите тип данных до имени переменной.
Вы можете написать тип данных без имени переменной (но не имя без типа данных).
Хотя вы, безусловно, можете указать своей среде 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']; ... }
Поскольку 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-класс clas-variable. Я не знаю, имеет ли это побочные эффекты для завершения кода текущего класса, а затем, поскольку новый член может быть введен, что на самом деле не существует.
Для тех, кто пришел сюда из Google.
PHPStorm на самом деле предоставляет способ решить эту проблему вместо того, чтобы писать PHPDocs снова и снова – создание и настройка файла .phpstorm.meta.php
описанным здесь образом обеспечивает плавно работающие проверки автозаполнения и типа.
Я знаю, что речь идет только о DIC, но есть поставщик услуг Silex Pimple Dumper, который выгружает контейнер в json-файл. Тот же автор написал плагин для PHPStorm, который может прочитать этот файл и открыть автозаполнение с именами служб и их типом (класс, строка и т. Д.). Я использую эти два компонента, и могу сказать, что это хорошие варианты автоматического завершения для Silex / Pimple.
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, что делает вашу конфигурацию раздутой и хрупкой.