How do I make my PHP IDE understand Dependency Injection Containers?

18,646

Solution 1

You can define class of the variable 'manually':

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

In PhpStorm (and by standards), use two asterisks and write the data type before the name of the variable.

You can write the data type without the name of the variable (but not the name without the data type).

Solution 2

While you can certainly tell your IDE the type of the object pulled out of your container every time you access it, it's better to do it once. Both of the following solutions involve subclassing the container. I just started using Pimple which recommends doing this anyway.

For containers that use instance members accessed with -> or exposed via the magic __get method, you can tell your IDE what type they hold. This is great because it doesn't involve any additional parsing when the code is run--only the IDE is bothered by it.

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

For Pimple and other containers that act as arrays you can create accessor functions for the top-level objects you'll need. While it means more parsing when the container is created, it should be done once and kept in APC. I vastly prefer a method over array access anyway since it places the easy-to-forget array key inside an auto-completed method.

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

BTW, for type-hinting inline variables with @var in NetBeans you need to use /* with one asterisk. This is not a doc-block comment and doesn't work with /** or //. Also, the name comes before the type.

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

Solution 3

As the IDE's do not exectue the code, they do not know and need some help form you. I know this works for Eclipse and other IDEs as well: Hint the variable's type.

Netbeans / Phpstorm / PDT / ZendStudio Example

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

Code complete starts to work again on $mailer.

For PDT it's important that:

  1. The comment starts with one * only.
  2. First the variable name, than the hint.

Alternative Comment Variants

As it was subject to a lot of discussion, it can differ between IDEs. However most IDEs support variable hinting for inline code variables in the way above. So depending on the IDE this might be written differently but similar, like here with two asterisks in front:

/** @var $mailer MailerInterface */

PHPDoc compatibility

PHPDoc parsers can have a problem if you mimic the class var doc-comment for inline code as so:

/** @var MailerInterface $mailer  */

That documentation is normally used for class variables (@var - Document the data type of a class variable). PHPDoc is then missing the definition of the class variable after the comment which involves a burden for QA.

However some IDEs will offer code completition for simple variables as well when written in PHPDoc clas-variable style. I do not know if that has side-effects for the code-completition of the current class then as a new member might get introduced that actually does not exists.

Solution 4

For those who came here from google.

PHPStorm actually provides a way to solve this kind of problem instead of writing PHPDocs over and over again — creating and setting .phpstorm.meta.php file in a way described here gains smoothly working autocomplete and type inspections.

Solution 5

I know that the question is about DIC only, but there is a Silex Pimple Dumper service provider which dumps the container to a json file. The same author wrote a plugin for PHPStorm which can read that file and open the autocomplete with the service names and its type (class, string and etc). I'm using those two components and I can say that are good options for auto completion for Silex/Pimple.

Share:
18,646
Blaise
Author by

Blaise

Updated on June 06, 2022

Comments

  • Blaise
    Blaise almost 2 years

    Current situation: I have dependencies in my project that I solve by using dependency injection. I want to take the next logic step by using a dependency injection container (DIC) to ease the management of my dependencies and to lazy-load classes.

    I looked at Bucket, Pimple, and sfServiceContainer, ran some test and really appreciate how DIC’s work. I’d probably go for Pimple because of its simplicity and raw power. If I didn’t have this problem:

    Due to the abstraction that DIC’s offer, the IDE I’m using (PHPStorm) no longer understands what’s going on in my code. It doesn’t understand that $container['mailer'] or $sc->mailer is holding a class object. I also tried Netbeans IDE: same problem.

    This is really a problem for me because my IDE becomes useless. I don’t want to program without code hints, autocompletion and refactoring tools when dealing with classes. And I don’t want my IDE to find all kinds of false positives when validating code.

    So my question is: Has anyone dealt with this problem and found a solution?

  • NikiC
    NikiC almost 13 years
    please add another asterix in order to make it a valid phpdoc comment.
  • OZ_
    OZ_ almost 13 years
    Second example shows wrong usage of phpdoc-comment. Type should be BEFORE variable only. It works just to support old code. manual.phpdoc.org/HTMLframesConverter/default/phpDocumentor/‌​…
  • hakre
    hakre almost 13 years
    @nikic: I dare to not do so as this is function body code not a phpdoc comment.
  • OZ_
    OZ_ almost 13 years
    @hakre so PDT is a piece of crap. Because standard of phpdoc tells to write datatype first (see link in previous comment).
  • hakre
    hakre almost 13 years
    @OZ_: I beg your pardon, but it looks like that you have misread the phpdoc specs you linked which is about class variables. This is not a class variable but code in the function body. PDT naturally supports PHPDoc comments for class variables according to the specs you've linked.
  • NikiC
    NikiC almost 13 years
    @hakre: As OZ already said, PDT is indeed a piece of crap. The correct doccomment is /** @var MailerInterface $mailer */. Everything else might not be correctly recognized by better IDEs (most will have fallback code to support one asterix too, but you shouldn't rely on that.)
  • hakre
    hakre almost 13 years
    The link you posted is about class variables.
  • NikiC
    NikiC almost 13 years
    @hakre: It applies to normal variables, too ;)
  • OZ_
    OZ_ almost 13 years
    @hakre there is no differences between class variables and other variables. Also, this question tagged with phpstorm tag, not with PDT or eclipse. Here was my +1 for this answer, but you edited it to wrong variant.
  • hakre
    hakre almost 13 years
    @nikic: How do you read this title: @var - Document the data type of a class variable? Would match the scope of PHPDoc fairly well, but whatever, no need to be pedantic.
  • OZ_
    OZ_ almost 13 years
    @Blaise Kal, don't write type after name of variable.
  • hakre
    hakre almost 13 years
    @Blaise Kal: Can imagine so as it's part of the interface / class.
  • OZ_
    OZ_ almost 13 years
    @Blaise Kal try to read comments - you'll find link to standards.
  • Blaise
    Blaise almost 13 years
    @hakre: This is in my file: use namespace\MailerInterface;, so it could know the namsespace already. But I’m not complaining :)
  • OZ_
    OZ_ almost 13 years
    @hakre you wrote the link to the fixed issue :) one asterisk works in PhpStorm too (but just to support old code).
  • hakre
    hakre almost 13 years
    @Blaise Kal: Was not thinking so ;) And good to see it works for you. Can help a lot in such cases.
  • Admin
    Admin over 12 years
    @hakre, you are correct, and all the IDEs are doing it wrong. I've wondered about that, too, but as you say: pedantic.
  • thevikas
    thevikas over 12 years
    netbeans does not support this example (thought it should) but does take types from phpdoc tags.
  • Jonathan Day
    Jonathan Day almost 12 years
    +1 for the hint about single asterisk. the double asterisk was breaking it for me. thx.
  • hakre
    hakre over 11 years
    @OZ_: I'm still missing the correct link from you to the Phpdoc standard for standard variables. The one you've given is for class variables only, which has not been asked about here.
  • MikeMurko
    MikeMurko about 11 years
    I think the trick is that you want to define this once in the container, not each time you use it - littering the code with phpdoc.
  • paul.ago
    paul.ago about 11 years
    The single asterisck syntax works on Eclipse PDT too, thank you!
  • rodrigo-silveira
    rodrigo-silveira over 10 years
    The only problem with this approach is that it's not object-oriented - it just uses classes... In your example, Container is not reusable, since you'll need to add/remove methods to it every time you have a new dependency. With Pimple, you just register new dependencies and never change the internals of the class like you do (classes should be closed to modifications).
  • David Harkness
    David Harkness almost 10 years
    @thevikas You need to use a single asterisk with NetBeans and put the name before the type.
  • marcovtwout
    marcovtwout over 9 years
    NetBeans example: /* @var $mailer YourClassType */
  • donquixote
    donquixote about 9 years
    In PhpStorm, the double asterisk works. /** @var MyService $service */.
  • donquixote
    donquixote about 9 years
    And for the @property docblock.. This can be used in combination with magic __get(). But does it also work with array access? I doubt it. (At least in PhpStorm)
  • David Harkness
    David Harkness about 9 years
    @donquixote No, @property is only for property access via ->. For array access you'll need to created accessor functions until a new annotation is created for PHPDoc and implemented by IDEs.
  • donquixote
    donquixote about 9 years
    @DavidHarkness Ok, that's what I thought. But the answer does not even mention magic __get(). Maybe it should be modified?
  • donquixote
    donquixote about 9 years
    dqxtech.net/blog/2014-06-13/… Not sure if Pimple also supports magic __get().
  • David Harkness
    David Harkness about 9 years
    @donquixote The second paragraph directly addresses properties exposed via __get, but I'll clarify it.
  • Andrew Plank
    Andrew Plank almost 8 years
    That is exactly what I was looking for. This changes everything. :D
  • Stephan-v
    Stephan-v over 7 years
    Just to make sure people don't take this in consideration, I would strongly advise against this. Basically what I being done here is creating a serviceprovider with a pre-configured dependency chain. Not maintainable.