15

I'm using PHP Storm as my IDE, but I believe that other IDE's such as Netbeans will have the same issue as I'll explain below.

When using a framework like Symfony2, we have the wonderful world of Dependency Injection added. So objects can simply be instantiated using code like the following snippet:

$myThingy = $this->get('some_cool_service');

This is very handy, as objects are already configured beforehand. The one problem is, that auto-completion breaks entirely in basically any PHP IDE, as the IDE does not know what type the get() method is returning.

Is there a way to preserve auto-completion? Would creating for example an extension of Controller be the answer? For example:

class MyController extends Controller {
    /**
     * @return \MyNamespace\CoolService
     */
    public getSomeCoolService() {
        return new CoolService();
    }
}

and then for application controllers, specify MyController as the base class instead of Controller?

What about using a Factory class, or any other possible methods?

hakre
  • 193,403
  • 52
  • 435
  • 836
josef.van.niekerk
  • 11,941
  • 20
  • 97
  • 157
  • Is the problem that it doesn't know it is an object, or that it doesn't know it is an object of a specific class? If it's the former, can't you just cast $myThingy as an object? `$myThingy = (object) $this->get('some_cool_service');` – DaveRandom Aug 27 '11 at 12:12
  • True, but even casting to an object will still leave the IDE clueless as to what the instances class type is, meaning...still no auto-completion sadly. :( – josef.van.niekerk Aug 27 '11 at 12:38
  • Same stuff as i had: http://stackoverflow.com/questions/21936380/best-practise-including-code-completion-in-zf2, same solutions but all need extra work. – Gizzmo Nov 24 '14 at 18:09

5 Answers5

15

It is more involving, but you can still do this with eclipse PDT:

$myThingy = $this->get('some_cool_service');
/* @var $myThingy \MyNamespace\CoolService */

UPDATE: The example on this page shows you may also use the other way round with phpStorm:

$myThingy = $this->get('some_cool_service');
/* @var \MyNamespace\CoolService $myThingy */
greg0ire
  • 22,714
  • 16
  • 72
  • 101
  • @gilden : I'm used to doing this without namespaces, I'm not 100% sure it works, but if definitely should. – greg0ire Aug 27 '11 at 12:21
  • Just tried it again and yeah...doesn't work for me. I can Ctrl+click on the annotation to open the corrent file though. I really wish it worked. – kgilden Aug 27 '11 at 12:28
  • It seems It's the inverted convetion for phpstorm : http://www.jetbrains.com/phpstorm/whatsnew/index.html – greg0ire Aug 27 '11 at 12:31
  • This will only work if the variable is defined at class scope, but would be useless inside a method. – josef.van.niekerk Aug 27 '11 at 12:35
  • One more thing : I think I got this to work with eclipse after removing the first backslash... – greg0ire Aug 27 '11 at 12:36
  • @josef.van.niekerk: this provides auto-completion on $myThingy in the current scope. The scope can be a method, no need for the variable to be a member of the class. – greg0ire Aug 27 '11 at 12:38
  • @greg0ire: Well, I've tried all ways and still couldn't get it working. I've seen this method being used on some other projects so clearly it works for some. It's probably my Eclipse doing tricks. – kgilden Aug 27 '11 at 12:38
  • @gilden: too bad, make sure you're using the latest version (I installed using a PDT all-in-one I think) – greg0ire Aug 27 '11 at 12:39
  • 1
    Hang on, this works for PHPStorm, but it's actually: /* @var \MyNamespace\CoolService $myThingy */ – josef.van.niekerk Aug 27 '11 at 12:41
  • @josef.van.niekerk: which means you can't benefit from your coworker's annotations if one is using eclipse and the other is using phpStorm... this sucks so much! – greg0ire Aug 27 '11 at 12:45
  • In PhpStorm any annotation will do: variable name first and then type or other way around -- both works fine for me (not a Symfony project, but nevertheless). It also supports normal PHP style comment `/* ... */` as well as PHPDoc style comments: `/** ... */` – LazyOne Aug 28 '11 at 07:32
  • @LazyOne: really? Does it work with regardless of whether if it uses the namespaces notation? You may edit my answer if you want (and can) – greg0ire Aug 28 '11 at 20:07
  • @greg0ire I'm not using namespaces in my projects yet (2-years old custom framework, PEAR/ZF style classes) and order (`$name type` or `type $name`) does not matter here. **For namespaces** I have created 2 simple namespaces (1 class with few differently named functions etc) -- and my tests show that it works fine there as well -- both of these provide proper code completion hints: `/* @var $b \LazyOne\AnotherSimpleClass */` and `/* @var \LazyOne\AnotherSimpleClass $b */`. Maybe it is because the test project is so simple? I don't think so -- I'm following their bug tracker. – LazyOne Aug 28 '11 at 20:38
  • @LazyOne : then it must be a difference between your version of PHPStorm and josef.van.niekerk's ... I'm editing my answer – greg0ire Aug 28 '11 at 21:22
  • @greg0ire Latest EAP build: PhpStorm v2.1.3 (PS-107.515). – LazyOne Aug 28 '11 at 21:25
  • @josef.van.niekerk: you may want to try LazyOne's version :) – greg0ire Aug 28 '11 at 21:40
7

You could define private properties in your controllers

class MyController extends Controller
{
    /**
     * @var \Namespace\To\SomeCoolService;
     */
    private $my_service;

    public function myAction()
    {
        $this->my_service = $this->get('some_cool_service');
        /**
         * enjoy your autocompletion :)
         */
    }
}
greg0ire
  • 22,714
  • 16
  • 72
  • 101
kgilden
  • 10,336
  • 3
  • 50
  • 48
6

I use base Controller class for bundle. You need to annotate the return in method. At least that works on Eclipse.

/**
 * Gets SomeCoolService
 *
 * @return \Namespace\To\SomeCoolService
 */
protected function getSomeCoolService()
{
    return $this->get('some_cool_service');
}

I don't like /*var ... */, because it gets too much into code. I don't like private properties, because you can wrongly assume that services are already loaded.

Marius Balčytis
  • 2,601
  • 20
  • 22
  • Agreed on this answer, I've found it to be the cleanest solution for cases where you need the dependency in the class more than 1 time. – Inoryy Jul 16 '12 at 10:33
1

I use Komodo Studio, and tagging variables with @var, even inside methods, preserves auto completion for me.

namespace MyProject\MyBundle\Controller;

use Symfony\Component\DependencyInjection\ContainerAware;
use Symfony\Component\HttpFoundation\Request;

class WelcomeController extends ContainerAware
{
    public function indexAction()
    {
        /*@var Request*/$request = $this->container->get('request');
        $request->[autocomplete hint list appears here]
    }
}
tuxedo25
  • 4,798
  • 1
  • 16
  • 12
0

working with netbeans IDE 7.1.2 PHP

belhassine
  • 151
  • 1
  • 4