Laravel-ide-helper: Allow custom text to be added into phpstorm.meta.php during/after generation.

Created on 27 Mar 2016  路  16Comments  路  Source: barryvdh/laravel-ide-helper

Hello Barry, thanks for this wonderful project.

Was wondering if it is possible, or if not would you be amenable to allowing custom factories to be added to the .phpstorm.meta.php file when it's being generated?

For example. I've a custom GoogleAPI wrapper that creates the required Google_Service when a string is passed to the makeService() method. eg:

$google = new GoogleAPI();

$calendar = $google->makeService('Calendar'); //Returns Google_Service_Calendar class.

All I need to add to the phpstorm.meta.php to get full autocomplete is:

        \App\Service\Google\GoogleApi::makeService('') =>[
            '' == 'Google_Service_@',
        ],

This is working fine for me at the moment, but I have to manually add it eveytime the phpstorm.meta.php file gets created. Any workaround?

stale

Most helpful comment

If you register your service in the container, the command should find it and add it to the meta file.

If you have your own Container, just add the file to your own package. You can have multiple files, it works from the vendor dir also.

All 16 comments

I'm voting for this too. I add custom items to the container with a different convention, it would really be helpful if we could append custom stuff to the meta file.

@jonnywilliamson : I don't know how Google Service there works, but I know if you create your services extending Laravel's service container, app() and other Laravel stuff get autocompleted via this package automatically. What I mean is, if you can get your service be called via, let's say app('google') then the rest should work.

@shehi I'm really sorry I just can't understand your comment there.

Even if what you suggest works and you can get full autocomplete from your method, the point of this request is to allow us to add some custom data to phpstorm.meta.php because at the moment it is completely generated automatically, and you can't add anything to it.

@jonnywilliamson : Do you know how to create services and service providers in Laravel? If so, they all are auto-included when .phpstorm.meta.php is generated. Otherwise I can't see how some resource not being part of Laravel's internals can be recognized by this package. By creating a Laravel service, you will have your own thing as part of its internals, and through that, this package will discover your services.

Have you even checked the source code of this tool?

If you register your service in the container, the command should find it and add it to the meta file.

If you have your own Container, just add the file to your own package. You can have multiple files, it works from the vendor dir also.

OK guys go easy on me, we're not all geniuses!

So I'll break it down in steps I've done, then you can point out the better and easier method I should do.

So I am using a service provider, and of course I have looked at the source code!

I want to use this php google api package (from google themselves).

**Please note, in the code below I've removed unneeded methods and doc blocks to make things clearer. If I have made a typo, please take it as a typo and not a functional issue as the code is currently working.

1) It's in a laravel project, and has been included with composer.

2) There are many google services that can be created with this library. Everyone of them needs a $client object, passed to it. Eg.

$client = new Google_Client();
$client->setApplicationName("Client_Library_Examples");
$client->setDeveloperKey("YOUR_APP_KEY");

$booksService = new Google_Service_Books($client);
$calendarService = new Google_Service_Calendar($client);

3) So I want to be able to create a goggle service object quickly, so I could do something like this:

$googleApi = app('GoogleApi::class');
$calendar = $googleApi->make('calendar');

4) With this code above, I will get no autocomplete in my IDE because it has no idea what type of object is returned from ->make() method. Unless I manually add a doc block comment like

    /** @var Google_Service_Calendar $calendar */

I need to start making my service provider.....so:

5) I created a service provider to generate the client for me automatically, using values from a google config file I have saved in the Laravel config directory:

<?php

namespace App\Providers;

use Auth;
use Google_Client;
use Illuminate\Support\ServiceProvider;

class GoogleApiServiceProvider extends ServiceProvider
{
    protected $defer = true;

    public function boot()
    {

    }

    public function register()
    {
        $this->app->singleton(Google_Client::class, function () {
            $client = new Google_Client(config('google'));
            $client->setScopes(config('google.scopes'));

            return $client;
        });

        $this->app->bind(GoogleApi::class, function () {
            return new GoogleApi(app(Google_Client::class));
        });
    }

    public function provides()
    {
        return [Google_Client::class, GoogleApi::class];
    }

}

6) Now I also write my API wrapper to implement the make method I want to use:

<?php

namespace App\Service\Google;

use Google_Client;
use Google_Service;
use InvalidArgumentException;

class GoogleApi
{

    /**
     * @var Google_Client
     */
    protected $client;

    /**
     * @var Google_Service[]
     */
    protected $service = [];

    public function __construct(Google_Client $client)
    {
        $this->client = $client;
    }

    /**
     * Create any type of GoogleService.
     *
     * @param string $service
     *
     * @throws InvalidArgumentException
     * @return object
     */
    public function make($service)
    {
        $service = 'Google_Service_'.ucfirst($service);
        if (class_exists($service)) {
            $class = new \ReflectionClass($service);

            return $this->service[$ucService] = $class->newInstance($this->client);
        }
        throw new InvalidArgumentException($service);
    }

}

7) So now things are working.If I make a GoogleApi object and call ->make('calendar') I WILL get a Google_Service_Calendar object back that works when I make calls to Google's servers.

However, there's still no autocomplete if I try:

$googleApi = app(GoogleApi::class);
$books = $googleApi->make('books');

$books-><NO AUTOCOMPLETE>.

8) If I add this line to the phpstorm.meta.php:

        \App\Service\Google\GoogleApi::make('') =>[
            '' == 'Google_Service_@',
        ],

I instantly get autocomplete.

Now I don't know where to go from here. How do I make this work with the service provider?

Shouldn't the line saying

$googleApi = app('GoogleApi::class');

actually be

$googleApi = app(GoogleApi::class);

? Notice you added string-quotes around a property, which shouldn't be there. GoogleApi::class will return the class name which also is the binding key your service provider uses.

You might have missed the note:

**Please note, in the code below I've removed unneeded methods and doc blocks to make things clearer. If I have made a typo, please take it as a typo and not a functional issue as the code is currently working.

Of course you are right, but that is a typo. Please read the code as a 'high level' overview of what i am trying to do, and not run it as production code...it's been heavily reduced to keep it easy to follow in this thread.

@jonnywilliamson : :) No, I am not missing anything. Look, when you create a service provider, you bind certain service/class/whatever to Laravel's service-container, using certain key. Usually that key is the class's FQNS (fully qualified namespace). Sometimes it's just a readable string. Doesn't matter, in all cases, it's a string. Then when you need that service, you call it either by app('service-string-goes-here') or app()->make('service-string-goes-here'). This IDE-helper understands it and auto-completion works just fine.

In your case you have done that via class names. So when you "make" an instance, let's say of GoogleApi class, you should do so via:

$myGoogleApi = app(GoogleApi::class);

and it will work. It also will autocomplete.

Remember you bound your service like this:

$this->app->bind(GoogleApi::class, function () {
    return new GoogleApi(app(Google_Client::class));
});

See there? You used GoogleApi::class, not 'GoogleApi::class'. ::class property always returns that class's FQNS.

And make sure you also have added your service provider to config/app.php file as well (under providers). That way application will identify its providers, and so will IDE-helper. Ok? Remember: add your provider to that file!!! If you don't, not only IDE-helper will fail, but so will your app: it will not be able to understand what provider that is.

And make sure you are not on PhpStorm 2016 - autocompletion doesn't work it, due to a bug in Phpstorm. See #340

I'm not using Phpstorm 2016, only v10

@shehi Look thank you for commenting and looking at this, I do appreciate it, however I think we are arguing about different things.

You keep mentioning the typo I make when using app(), please be assured I have no problems using the ::class syntax.

Just so you are not confused with what I am saying, I have no problems getting autocomplete for any method in my GoogleAPI class.

So for example,

$googleApi = app(GoogleApi::class);

$googleApi-><I **WILL** GET AUTOCOMPLETE HERE. NO PROBLEM>


//Now if I continue
$books = $googleApi->make('books');

$books-><I GET NO AUTOCOMPLETE HERE BECAUSE THE IDE HAS NO IDEA WHAT OBJECT WAS RETURNED FROM MAKE METHOD>.

If I wanted to bind 'calendar' in my service provider I could.

Then I could bind Books.
Then I could bind AdExchangeBuyer
Then I could bind Analytics
Then I could bind Blogger
Then I could bind Dataflow
Then I could bind Youtube

and so on and so on.....over 200 services can be returned from the google api package.

But I don't want to.

I want to use the clever ability of Phpstorm to be able to read what a factory can create and then provide autocomplete. It can do it! I only need that small line placed into the phpstorm.meta.php file.

I just don't know how to do that automatcially, or how to let this amazing package scan and do it for me.

https://confluence.jetbrains.com/display/PhpStorm/PhpStorm+Advanced+Metadata

Oh... But that would be almost impossible to achieve with this package. You see, this package translates Laravel services (which are dynamic) TO Phpstorm Metadata. What you want is translation of GoogleApi services (dynamic) TO Laravel services (again dynamic) TO Phpstorm Metadata. Its like nesting IDE-helper with itself :)

Even if you removed Laravel as a "middleware" (middleware in general sense) and translated Google Services TO Phpstorm Metadata, then you would have to create a tool similar to this one, but instead of reading Laravel resources and populating them into phpstorm.meta.php, it'd need to read GoogleApi resources and populate/append accordingly. But rest assured, this package can't scan custom code for that purpose, as it's specifically was created for Laravel. You could fork it and add your own modifications, which could scan any codebase you desire.

Now I understand what you want. And I greatly doubt that task is in the scope of this package. Of course final verdict is @barryvdh 's.

So finally after this exhausting exchange we come back to the original request of this issue (from post 1)

Was wondering if it is possible, or if not would you be amenable to allowing custom factories to be added to the .phpstorm.meta.php file when it's being generated?

Which I could now reword slightly to:

@barryvdh Would you amenable to allowing the ability to add custom text to the phpstorm.meta.php file during/after it has been generated?

I don't need help on WHAT to insert into the file, I just would like an automatic way of including it during/after it is being generated.

@briedis Thought you might be interested in this I've just discovered in the past few days

https://github.com/barryvdh/laravel-ide-helper/issues/469

For anyone following along, here are some further results that may help you out. Using uptodate versions of phpstorm

https://github.com/barryvdh/laravel-ide-helper/issues/469#issuecomment-291265821

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If this issue is still present on the latest version of this library on supported Laravel versions, please let us know by replying to this issue so we can investigate further.
Thank you for your contribution! Apologies for any delayed response on our side.

Was this page helpful?
0 / 5 - 0 ratings