<p>Absolutely, just add the app directory as a external library.</p>

<ol>
<li>Double click on the 'external libraries'.</li>
<li>Add the interpreter</li>
<li>Include the path to the 'app' directory</li>
</ol>

<p><img src="https://i.sstatic.net/ZUoBy.png" alt="enter image description here"></p>

CC BY-SA 3.0
2014-07-28T18:40:38.963Z
Is this the only solution for getting this to work? Additionally, I'm a little confused. In your first sentence you said the "app" directory and that's what appears to be illustrated in your screenshot but in your numbered instructions you say the "craft" directory.
Tyler Willingham
CC BY-SA 3.0
2014-07-28T18:41:49.457Z
Typo, I will correct it.
Jason McCallister
CC BY-SA 3.0
2014-07-28T19:09:17.447Z
Also, to enable phpstorm to auto complete - you have to reference the library (craft) so it knows where to load the code from.
Jason McCallister
CC BY-SA 3.0
2014-07-30T20:17:02.770Z
Is this supposed to work for third-party plugins' services? I'm not able to get that working.
Tyler Willingham
CC BY-SA 3.0
2014-07-30T21:21:28.270Z
I'm actually not sure how that would work for a plugin. It works in Craft by defining the property in the PHPDoc in WebApp.php.  So @property AssetsService $assets, lets PHPStorm know that there exists an AssetsService object off of craft()->assets.  And it's not like we can add a hook for the PHPDoc.  Maybe through some crazy reflection magic, but it'd be super hackey.
Brad Bell
CC BY-SA 3.0
2014-07-31T16:03:48.107Z
@BradBell Can you make that an answer so I can select it as correct? Jason's answer was correct per my original title but incorrect per the description (I recently corrected the title).
Tyler Willingham
CC BY-SA 3.0
2014-07-31T16:54:50.820Z
@TylerWillingham Done!
Brad Bell
CC BY-SA 3.0
2014-07-28T17:17:40.797Z
2014-07-28T18:42:06.360Z
2014-07-28T18:42:06.360Z
Jason McCallister
<p>I handled it by adding a global function and singleton object similar to Craft's WebApp. All of my plugin's services are access from my custom global function myPlugin() while Craft's services continue to be started from the craft() global function. In the doc block for the new object, I specify properties for each service. Each new service must be added by hand, but all members of that service are recognized by the IDE. </p>

<p>This should work across all IDEs (including PHPStorm where this was developed). </p>

<pre class="lang-php prettyprint-override"><code>&lt;?php
namespace Craft;
/**
 * Class MyPlugin
 * @package Craft
 */

/**
 * @property MyPlugin_CategoriesService $categories MyPlugin Categories Service
 * @property MyPlugin_TriviaService     $trivia     MyPlugin Trivia Service
 */
class MyPlugin {

    public function __get($memberName)
    {
        $craftName = 'myPlugin_' . strtolower($memberName);
        return craft()-&gt;$craftName;
    }

    /**
     * Return singleton instance of the rantAPI service manager
     * @return MyPlugin
     */
    public static function app()
    {
        static $inst = null;
        if ( $inst === null) {
            $inst = new MyPlugin();
        }
        return $inst;
    }
}


/**
 * Returns the myPlugin equivalent to webApp class that serves up all the services.
 *
 * @return MyPlugin
 */
function myPlugin()
{
    return MyPlugin::app();
}
</code></pre>

<p>In my controller, I reference my services and craft's services in the following way.</p>

<pre class="lang-php prettyprint-override"><code>$parentEntry = craft()-&gt;entries-&gt;getEntryById(999);
$triviaToAdd = myPlugin()-&gt;trivia-&gt;getByKeyword('nerds');
</code></pre>

<p>In the example above, both entries and trivia are recognized as valid objects and their methods are available for intelligent code completion. </p>

CC BY-SA 3.0
2014-08-05T20:10:17.323Z
Nice and clever!
Brad Bell
CC BY-SA 3.0
2014-08-05T18:45:09.673Z
2014-08-05T20:00:03.887Z
2014-08-05T20:00:03.887Z
Dan Eichholz
<p>I'm kinda late to the party here but Brandon suggested I add the technique I use to this thread.</p>

<p>What I do in order for PHPStorm to resolve my own <code>craft()-&gt;myService</code> is to not use that at all because you can't type hint services that get created at runtime. What I do instead, is to declare a function with the name of my plugin that is properly type hinted.</p>

<p>Let's say that I have a plugin called <code>PatrolPlugin</code> with a service called <code>PatrolService</code> which has a method called <code>protect()</code>. If I want to navigate to the method definition/declaration for <code>PatrolService.protect()</code>, I would do something like this.</p>

<ol>
<li>Create a properly type hinted service getter, this can be a global function or a static method in your plugin class.</li>
</ol>

<pre class="lang-php prettyprint-override"><code>/**
 * Tells PHPStorm or any other smart IDE that patrol() returns my service
 *
 * @return PatrolService
 */
function patrol()
{
    return Craft::app()-&gt;getComponent('patrol');
}
</code></pre>

<ol start="2">
<li>Call that function/method instead of using <code>craft()-&gt;patrol</code></li>
</ol>

<pre class="lang-php prettyprint-override"><code>patrol()-&gt;protect()
</code></pre>

<ol start="3">
<li>Place the cursor inside <code>protect</code> and go to definition.</li>
</ol>

<p>That's what I do anyways, and it works for me.</p>

<hr>

<p>If I had other services that I wanted type hinted, I can just add them as properties of the main service.</p>

<pre class="lang-php prettyprint-override"><code>/**
 * @property Patrol_OtherService $other
 */
class PatrolService extends BaseApplicationComponent
{
    public $other;

    public function init()
    {
        $this-&gt;other = Craft::app()-&gt;getComponent('patrol_other');
    }
}
</code></pre>

<p><strong>Note:</strong> I'm using <code>Craft::app()-&gt;getComponent('service')</code> because it is a bit faster than <code>craft()-&gt;service</code> but they are basically the same.</p>

CC BY-SA 3.0
2014-12-18T21:27:59.927Z
2014-12-18T21:27:59.927Z
Selvin Ortiz
<p>I'm actually not sure how it would work if you're trying to reference another plugin's services.</p>

<p>It works in Craft by defining the property in the PHPDoc in <code>WebApp.php</code>.</p>

<pre><code>@property AssetsService $assets
</code></pre>

<p>That lets PHPStorm know that there exists an AssetsService object off of <code>craft()-&gt;assets</code>.</p>

<p>And it's not like we can add a hook for the PHPDoc so plugins can inject their own... maybe through some crazy reflection magic, but it'd be super hackey.</p>

CC BY-SA 3.0
2015-10-22T15:13:11.370Z
I've added it to my WebApp.php file and autocomplete still doesn't find my plugin service. Any ideas?
Sandy D.
CC BY-SA 3.0
2015-10-22T15:19:42.023Z
If you're on the latest version of PhpStorm, there is a bug preventing most autocompletion. https://youtrack.jetbrains.com/issue/WI-28394
Brad Bell
CC BY-SA 3.0
2015-10-22T15:22:36.320Z
I am using the latest version. =(
Sandy D.
CC BY-SA 3.0
2015-10-22T16:15:25.140Z
Me too. :(  Feel free to leave a comment on that bug report. :)
Brad Bell
CC BY-SA 3.0
2016-03-07T15:02:26.037Z
@SandyD. This is now fixed on the EAP build of PHPStorm! [Link to EAP build](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program)
Merlin
CC BY-SA 3.0
2014-07-31T16:54:37.437Z
2014-07-31T16:54:37.437Z
Brad Bell
<p>It would make my day to be able to have PHPStorm recognize third-party services. Has anyone figured out how to get this working yet?</p>

<plugin-development>
Has anyone been able to get auto-complete working with plugins + PHPStorm?
# Has anyone been able to get auto-complete working with plugins + PHPStorm?

(Asked by: username_0 on 2014-07-28)

It would make my day to be able to have PHPStorm recognize third-party services. Has anyone figured out how to get this working yet?

**Tags:** plugin-development

---

## 4 answers

### Answer by username_2 on 2014-07-31. Score: 5 | Accepted answer

I'm actually not sure how it would work if you're trying to reference another plugin's services.
It works in Craft by defining the property in the PHPDoc in WebApp.php.
@property AssetsService $assets

That lets PHPStorm know that there exists an AssetsService object off of craft()->assets.
And it's not like we can add a hook for the PHPDoc so plugins can inject their own... maybe through some crazy reflection magic, but it'd be super hackey.

> **Comments:**
> **username_5**: I've added it to my WebApp.php file and autocomplete still doesn't find my plugin service. Any ideas?  
> **username_2**: If you're on the latest version of PhpStorm, there is a bug preventing most autocompletion. https://youtrack.jetbrains.com/issue/WI-28394  
> **username_5**: I am using the latest version. =(  
> **username_2**: Me too. :(  Feel free to leave a comment on that bug report. :)  
> **username_6**: @SandyD. This is now fixed on the EAP build of PHPStorm! [Link to EAP build](https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Early+Access+Program)  

---

### Answer by username_1 on 2014-07-28. Score: 6

Absolutely, just add the app directory as a external library.

1. Double click on the 'external libraries'.
2. Add the interpreter
3. Include the path to the 'app' directory

![enter image description here](https://i.sstatic.net/ZUoBy.png)

> **Comments:**
> **username_0**: Is this the only solution for getting this to work? Additionally, I'm a little confused. In your first sentence you said the "app" directory and that's what appears to be illustrated in your screenshot but in your numbered instructions you say the "craft" directory.  
> **username_1**: Typo, I will correct it.  
> **username_1**: Also, to enable phpstorm to auto complete - you have to reference the library (craft) so it knows where to load the code from.  
> **username_0**: Is this supposed to work for third-party plugins' services? I'm not able to get that working.  
> **username_2**: I'm actually not sure how that would work for a plugin. It works in Craft by defining the property in the PHPDoc in WebApp.php.  So @property AssetsService $assets, lets PHPStorm know that there exists an AssetsService object off of craft()->assets.  And it's not like we can add a hook for the PHPDoc.  Maybe through some crazy reflection magic, but it'd be super hackey.  
> **username_0**: @BradBell Can you make that an answer so I can select it as correct? Jason's answer was correct per my original title but incorrect per the description (I recently corrected the title).  
> **username_2**: @TylerWillingham Done!  

---

### Answer by username_3 on 2014-08-05. Score: 6

I handled it by adding a global function and singleton object similar to Craft's WebApp. All of my plugin's services are access from my custom global function myPlugin() while Craft's services continue to be started from the craft() global function. In the doc block for the new object, I specify properties for each service. Each new service must be added by hand, but all members of that service are recognized by the IDE. 
This should work across all IDEs (including PHPStorm where this was developed). 
$craftName;
    }

    /**
     * Return singleton instance of the rantAPI service manager
     * @return MyPlugin
     */
    public static function app()
    {
        static $inst = null;
        if ( $inst === null) {
            $inst = new MyPlugin();
        }
        return $inst;
    }
}


/**
 * Returns the myPlugin equivalent to webApp class that serves up all the services.
 *
 * @return MyPlugin
 */
function myPlugin()
{
    return MyPlugin::app();
}

In my controller, I reference my services and craft's services in the following way.
$parentEntry = craft()->entries->getEntryById(999);
$triviaToAdd = myPlugin()->trivia->getByKeyword('nerds');

In the example above, both entries and trivia are recognized as valid objects and their methods are available for intelligent code completion.

> **Comments:**
> **username_2**: Nice and clever!  

---

### Answer by username_4 on 2014-12-18. Score: 3

I'm kinda late to the party here but Brandon suggested I add the technique I use to this thread.
What I do in order for PHPStorm to resolve my own craft()->myService is to not use that at all because you can't type hint services that get created at runtime. What I do instead, is to declare a function with the name of my plugin that is properly type hinted.
Let's say that I have a plugin called PatrolPlugin with a service called PatrolService which has a method called protect(). If I want to navigate to the method definition/declaration for PatrolService.protect(), I would do something like this.

Create a properly type hinted service getter, this can be a global function or a static method in your plugin class.

/**
 * Tells PHPStorm or any other smart IDE that patrol() returns my service
 *
 * @return PatrolService
 */
function patrol()
{
    return Craft::app()->getComponent('patrol');
}


Call that function/method instead of using craft()->patrol

patrol()->protect()


Place the cursor inside protect and go to definition.

That's what I do anyways, and it works for me.

If I had other services that I wanted type hinted, I can just add them as properties of the main service.
/**
 * @property Patrol_OtherService $other
 */
class PatrolService extends BaseApplicationComponent
{
    public $other;

    public function init()
    {
        $this->other = Craft::app()->getComponent('patrol_other');
    }
}

Note: I'm using Craft::app()->getComponent('service') because it is a bit faster than craft()->service but they are basically the same.


---

