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?
4 Answers
Absolutely, just add the app directory as a external library.
- Double click on the 'external libraries'.
- Add the interpreter
- Include the path to the 'app' directory

- 2,336
- 14
- 27
-
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 Jul 28 '14 at 18:40
-
Typo, I will correct it. – Jason McCallister Jul 28 '14 at 18:41
-
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 Jul 28 '14 at 19:09
-
Is this supposed to work for third-party plugins' services? I'm not able to get that working. – Tyler Willingham Jul 30 '14 at 20:17
-
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 Jul 30 '14 at 21:21
-
@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 Jul 31 '14 at 16:03
-
@TylerWillingham Done! – Brad Bell Jul 31 '14 at 16:54
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).
<?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()->$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.
- 167
- 7
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.
- 67,440
- 6
- 73
- 143
-
I've added it to my WebApp.php file and autocomplete still doesn't find my plugin service. Any ideas? – Sandy D. Oct 22 '15 at 15:13
-
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 Oct 22 '15 at 15:19
-
-
-
1@SandyD. This is now fixed on the EAP build of PHPStorm! Link to EAP build – Merlin Mar 07 '16 at 15:02
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
protectand 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.
- 1,623
- 11
- 12