Arhn - архитектура программирования

Как заставить мою PHP IDE понимать контейнеры внедрения зависимостей?

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

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

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

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

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


  • вы можете попробовать через теги phpdocumentor /** @var $inst My_Object **/ $inst = $sc->mailer; 18.06.2011
  • Вы можете проголосовать за WI-17116, если вы заинтересованы в поддержке этого в PHPStorm. . 04.11.2014

Ответы:


1

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

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

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

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

18.06.2011
  • Ссылка, которую вы разместили, касается переменных класса. 18.06.2011
  • @hakre: это относится и к обычным переменным;) 18.06.2011
  • @nikic: Как вы понимаете этот заголовок: @var — документировать тип данных переменной класса? Достаточно хорошо соответствует объему PHPDoc, но в любом случае не нужно быть педантичным. 18.06.2011
  • @hakre, вы правы, и все IDE делают это неправильно. Я тоже думал об этом, но, как вы говорите: педантичный. 18.09.2011
  • netbeans не поддерживает этот пример (думал, что должен), но берет типы из тегов phpdoc. 16.12.2011
  • Я думаю, что хитрость в том, что вы хотите определить это один раз в контейнере, а не каждый раз, когда вы его используете, засоряя код phpdoc. 22.03.2013
  • @thevikas Вам нужно использовать одну звездочку с NetBeans и поставить имя перед типом. 03.08.2014
  • Пример NetBeans: /* @var $mailer YourClassType */ 17.12.2014

  • 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'];
        }
    }
    

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

    public function foo() {
        /* @var $service MyService */
        $service = $container['service'];
        ...
    }
    
    20.06.2011
  • +1 за подсказку об одиночной звездочке. двойная звездочка сломала это для меня. Спасибо. 11.07.2012
  • Синтаксис с одной звездочкой работает и в Eclipse PDT, спасибо! 15.04.2013
  • В PhpStorm работает двойная звездочка. /** @var MyService $service */. 27.02.2015
  • И для докблока @property. Это можно использовать в сочетании с магией __get(). Но работает ли он также с доступом к массиву? Я сомневаюсь в этом. (По крайней мере, в PhpStorm) 27.02.2015
  • @donquixote Нет, @property предназначен только для доступа к собственности через ->. Для доступа к массиву вам нужно будет создать функции доступа, пока не будет создана новая аннотация для PHPDoc и реализована в IDE. 28.02.2015
  • @DavidHarkness Хорошо, я так и думал. Но в ответе даже не упоминается магия __get(). Может быть, его следует изменить? 28.02.2015
  • dqxtech.net/blog/2014- 06-13/ Не уверен, что Pimple также поддерживает magic __get(). 28.02.2015
  • @donquixote Второй абзац напрямую касается свойств, предоставляемых через __get, но я поясню это. 01.03.2015

  • 3

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

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

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

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

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

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

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

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

    /** @var $mailer MailerInterface */
    

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

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

    /** @var MailerInterface $mailer  */
    

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

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

    18.06.2011
  • пожалуйста, добавьте еще одну звездочку, чтобы сделать его действительным комментарием phpdoc. 18.06.2011
  • Второй пример показывает неправильное использование phpdoc-comment. Тип должен быть только ДО переменной. Он работает только для поддержки старого кода. manual.phpdoc.org/HTMLframesConverter/default/phpDocumentor/ 18.06.2011
  • @nikic: я осмеливаюсь этого не делать, так как это код тела функции, а не комментарий phpdoc. 18.06.2011
  • @hakre, так что PDT - это кусок дерьма. Потому что стандарт phpdoc говорит сначала писать тип данных (см. ссылку в предыдущем комментарии). 18.06.2011
  • @OZ_: Прошу прощения, но похоже, что вы неправильно прочитали спецификации phpdoc, на которые вы ссылались, которые касаются переменных класса. Это не переменная класса, а код в теле функции. PDT естественно поддерживает комментарии PHPDoc для переменных класса в соответствии со спецификациями, которые вы связали. 18.06.2011
  • @hakre: Как уже сказал OZ, PDT действительно кусок дерьма. Правильный документ: /** @var MailerInterface $mailer */. Все остальное может быть неправильно распознано лучшими IDE (большинство из них будет иметь резервный код для поддержки одной звездочки, но вы не должны полагаться на это). 18.06.2011
  • @hakre нет различий между class variables и другими переменными. Кроме того, этот вопрос помечен тегом phpstorm, а не PDT или eclipse. Вот мой +1 к этому ответу, но вы отредактировали его в неправильном варианте. 18.06.2011
  • @Blaise Kal, не пишите тип после имени переменной. 18.06.2011
  • @Blaise Kal: Можете себе представить, что это часть интерфейса/класса. 18.06.2011
  • @Blaise Kal попробуйте прочитать комментарии - вы найдете ссылку на стандарты. 18.06.2011
  • @hakre: Это в моем файле: use namespace\MailerInterface;, так что он уже может знать пространство имен. Но я не жалуюсь :) 18.06.2011
  • @hakre вы написали ссылку на вопрос fixed :) одна звездочка работает и в PhpStorm (но только для поддержки старого кода). 18.06.2011
  • @Blaise Kal: Я так не думал ;) И приятно видеть, что это работает для вас. Может очень помочь в таких случаях. 18.06.2011
  • @OZ_: Мне все еще не хватает от вас правильной ссылки на стандарт Phpdoc для стандартных переменных. Тот, который вы указали, предназначен только для переменных класса, о которых здесь не спрашивали. 27.12.2012


  • 5

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

    07.07.2012
  • Единственная проблема с этим подходом заключается в том, что он не объектно-ориентированный - он просто использует классы... В вашем примере Container нельзя использовать повторно, так как вам нужно будет добавлять/удалять к нему методы каждый раз, когда у вас есть новая зависимость. С Pimple вы просто регистрируете новые зависимости и никогда не меняете внутренности класса, как вы это делаете (классы должны быть закрыты для модификаций). 29.10.2013
  • Просто чтобы убедиться, что люди не принимают это во внимание, я бы настоятельно не советовал этого делать. По сути, то, что я здесь делаю, — это создание поставщика услуг с предварительно настроенной цепочкой зависимостей. Не ремонтопригоден. 30.01.2017

  • 6

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

    08.03.2016
  • Это именно то, что я искал. Это все меняет. :D 09.06.2016
  • Новые материалы

    Коллекции публикаций по глубокому обучению
    Последние пару месяцев я создавал коллекции последних академических публикаций по различным подполям глубокого обучения в моем блоге https://amundtveit.com - эта публикация дает обзор 25..

    Представляем: Pepita
    Фреймворк JavaScript с открытым исходным кодом Я знаю, что недостатка в фреймворках JavaScript нет. Но я просто не мог остановиться. Я хотел написать что-то сам, со своими собственными..

    Советы по коду Laravel #2
    1-) Найти // You can specify the columns you need // in when you use the find method on a model User::find(‘id’, [‘email’,’name’]); // You can increment or decrement // a field in..

    Работа с временными рядами спутниковых изображений, часть 3 (аналитика данных)
    Анализ временных рядов спутниковых изображений для данных наблюдений за большой Землей (arXiv) Автор: Рольф Симоэс , Жильберто Камара , Жильберто Кейрос , Фелипе Соуза , Педро Р. Андраде ,..

    3 способа решить квадратное уравнение (3-й мой любимый) -
    1. Методом факторизации — 2. Используя квадратичную формулу — 3. Заполнив квадрат — Давайте поймем это, решив это простое уравнение: Мы пытаемся сделать LHS,..

    Создание VR-миров с A-Frame
    Виртуальная реальность (и дополненная реальность) стали главными модными терминами в образовательных технологиях. С недорогими VR-гарнитурами, такими как Google Cardboard , и использованием..

    Демистификация рекурсии
    КОДЕКС Демистификация рекурсии Упрощенная концепция ошеломляющей О чем весь этот шум? Рекурсия, кажется, единственная тема, от которой у каждого начинающего студента-информатика..