I am new using PhpStorm. Previously I used Visual Studio Code and Sublime Text 3/4, however with PhpStorm it is much more convenient to work with PHP and I am happy with the IDE.
I have customized the style of the code according to my needs and the convention of the Framework I am working with. The problem arises when doing a cleanup and/or reformatting of the code: when this happens, the protected and public methods get mixed up. I will try to explain it as best as possible.
For example: if I have a protected method named getPath that is called in one or more public methods at the beginning of the class, by convention this method should be at the end of the class along with the private methods, but then if I set another public method that does not use the getPath method, getPath is placed on top of the new public method. I KNOW! It doesn't seem to be a problem, but when you follow strict convention rules of a framework or a personal convention, this ends up being very important.
In my case, I'm extremely clean and tidy in my code, but I haven't been able to configure the IDE to keep methods private and protected at the end of the class.
I would like to know if someone can help me configure the IDE to solve the problem and if possible I would like the magic methods (__call, __callStatic, __sleep, __get) to be kept at the end of everything.
I am using PhpStorm 2021.3.2.
Related
So this has been asked several times but I'm yet to find an answer that works.
I'm using PhpStorm - 2016.3.2 and Laravel 5.4
I have tried using https://github.com/barryvdh/laravel-ide-helper and also the Laravel plugin for PhpStorm.
I tried checking the option "Downgrade severity if_magic methods are present in class" - this didn't work.
The only thing I can do to solve this is to turn the warnings off completely for undefined methods, but turning features like this off defeat the point of using an IDE.
Has anyone found a way to solve this?
Sources:
https://laracasts.com/series/how-to-be-awesome-in-phpstorm/episodes/15
https://laracasts.com/discuss/channels/general-discussion/why-does-phpstorm-not-recognise-all-the-classes?page=1
PhpStorm laravel 5 method not found
https://github.com/barryvdh/laravel-ide-helper
PHPDoc blocks can come in handy for this.
You can add this PHP comment just before the statement return $query, inside the function
/** #var $query \Illuminate\Database\Query\Builder */
In this way PHPStorm will correctly recognize the method
The reason this is happening is because PHPStorm doesn't know what that variable is meant to be (it has nothing to be with Laravel). As far as PHPStorm knows it's just a param for a method.
As #LazyOne suggested, you can type hint the variable e.g.
public function scopeIncomplete(Builder $query)
Then at the top of the class just add the following use statement
use Illuminate\Database\Eloquent\Builder;
Alternatively, if you're using a OS X (I'm not sure of the shortcuts for Windows or Linux) you can move the caret in the Builder reference and then hit alt enter to import the class.
Hope this helps!
I use PhpStorm as my PHP IDE. It has a feature where it will issue a warning if it detects you using a non-existent method to a class. Usually it is a typo, but it could also be a method not yet created.
In cases where it does not detect a valid class, one can manually hint the IDE with an annotation similar to this.
/** #var MyClass $myClass **/
This would force the IDE to allow the variable $myClass-> to detect all available methods of MyClass.
I have come across a problem where I have a class that is being generated dynamically from a call to a third party SOAP service. PhpStorm is flagging a method call to this new class because the method I am calling is not part of the SoapClient class.
These are the two lines of code I am working with for this question. The warning comes on the second line, SendCharFax not found in \SoapClient
$client = new SoapClient("http://ws.interfax.net/dfs.asmx?wsdl");
$result = $client->SendCharFax($params);
I understand clearly why the IDE warning shows, but I want to know how I can eliminate the warning. I have spent a good deal of time searching SO and the Internet, and I cannot find any information to help me wth this problem.
How can I eliminate this IDE warning?
if you want full auto completion and dynamic variable hint, use a WSDL to php generator such as the PackageGenerator project.
I have been looking for a way to do this for months. I am one of those developers that loves autocompletion. For every Service Locator call in zend framework 2 I type hint with the following:
Without global hinting file
/** #var \Module\Service\SuperService $superService */
$superService => $this->getServiceLocator()>get('\Module\Service\SuperService');
$superService->coolFunction();
This works, but the code can get messy when you start getting 2-4 Services in a single Controller. I am trying to find a better way to use PHP Storm and type hinting for service locator calls
About a month ago PHP Storm released a new feature that allows for a static file to be used for type hinting. I personally use this just for the service locator but it can be used for many other things that PHP Storm can't follow because it's not magic.
With global hinting file
$superService = $this->getServiceLocator()->get('\Module\Service\SuperService');
$superService->coolFunction();
This does a few things for us as developers:
Teamwork (others will be able to see all services at once from all
modules)
Coding
Speed
Code neatness
Code Standards
Click to go to the class faster
What to do
In the project ROOT (same place as composer.json), there should (create if not) be a file called .phpstorm.meta.php This file contains the static hinting and which instance they use.
To add your own, simply toss it inside the existing file
WARNING - If you declare the wrong class, you will end up writing the code wrong, and confused... it has happened to me a bunch
I am including my current Config which is personal to my project but gives more of an understanding of what to do.
namespace PHPSTORM_META {
$STATIC_METHOD_TYPES = [
\Zend\ServiceManager\ServiceLocatorInterface::get('') => [
/**
* Common services
*/
'doctrine.entitymanager.orm_default' instanceof \Doctrine\ORM\EntityManager,
'Zend\Db\Adapter\Adapter' instanceof \Zend\Db\Adapter\AdapterServiceFactory,
/** Custom to Project */
'RiotAdapter' instanceof \GameService\Service\RiotAdapter,
'SmiteAdapter' instanceof \GameService\Service\SmiteAdapter,
'GameService' instanceof \GameService\Service\GameService,
],
];
}
If you would like more information on this, you can look # a confluence post from PHP Storm here
While this doesn't help you now, it's useful for you to know that we are close to supporting this out of the box, with a few provisos:
The container needs to implement the Container Interop project's Container\Interop\ContainerInterface which ZF2's ServiceManager already does.
You need to use the ::class super-global-hyper-magic-contant to name and retrieve your classes. In your case, simply replace the string in your get call with Module\Service\SuperService::class (available from PHP 5.4 and above).
I'm expecting this functionality to be available in our next release, PhpStorm 2016.2 which is due around the summer.
Gary
I'm developing an application with Yii 1.1 using the "PHPStorm" IDE (version 8.0.2). While it manages to find declarations of base Yii methods, it can't find implementations of methods declared in models of the application.
When I try to click on a function and choose "Go To... Implementations" in the context menu, they can not be discovered.
One of the examples:
I rightclick on a method implementation in a view and choose "go to the declaration". The IDE manages to correctly direct me to the method declaration in a model. At the same time, when I try to find implementations of the exact same method, the IDE fails to find them.
Am I doing something wrong?
I'm using NetBeans and as far as I know the Go to declaration depends on two things 1) to have added the framework files to project includes in case the files are outside 2) go to declaration will work based on the way you define the variables, and some of them might not work at all in case of magical methods.
But you could always declare the class of a variable by using some comments, for example:
$post=Post::model()->find();
$post->save();
If I click on save() might not work depending on what ::model() and find() return. But I could declare $post as Post with a comment:
/* #var $post Post */
That will let the IDE know that $post is of type Post. Then based on that it will know that it extends CActiveRecord and so it will locate the save() method and go to declaration will work.
Always make sure that either:
functions return a instanciated object, ej: $post=Post;
if not, at least specify in #return comment what type of object they return
and lastly if none of them, you can always use the commenting way above
So I want to be able to add/remove class methods at runtime. Before you tell me that's horrible pratice in oop, it might be, but I don't really care. The reason I want to be able to do this is because I want the application to be very modular, so some plugin could extend some base class and add methods to it without killing the the main app.
For example, say I have the following class:
class User {
protected $Id;
protected $Name;
protected $Password;
protected $PostsPerPage;
}
And say, some plugin adds the possibility for users to change their visibility settings, adding a $Visible property to the class. The class would become:
class User {
protected $Id;
protected $Name;
protected $Password;
protected $PostsPerPage;
protected $Visible;
}
This could be achieved via __get and __set, but the most common implementation is for getting and setting runtime generated properties, and it'd be a hassle to code pseudo getters and setters for each added property, as well as using __set is a no-no in my opinion.
The other idea I had was to store the user settings separately, in another array like $UserVisiblitySettings[userid], but that makes things not as OO as I would like them to be.
Next idea was to make a helper class, something like this:
class UserHelper {
public function SetVisiblity($user_object,value);
}
Then, I could use __get and __set to implement "friend" methods/classes, but that sounds too hackish. If I were to go that way might as well just overload __call, __get and __set. Also I'm not so sure this is good OOP pratice, and it'd look ugly too.
The last idea I had was to have some function to create classes dynamically on runtime by using eval() (this is the only valid use of eval I could come up with too). Basically, get the class definition from a file, do some simple bracket finding to find the class' opening and closing brackets and send it to eval.
Using runkit is out of question, as it is outdated and I'd rather not force the user to install some extension.
When I look up to my ideas, the simplest one and less cpu intensive seems to be to overload _call and add a way for methods to be registered in the class.
Please any thoughts that aren't "don't do this" are appreciated.
RunKit extension can do it (runkit_method_add(), etc.)
However it's an experimental extension and you're already aiming at your foot...
You have other options:
Emulate new fields and methods with __get() and __call()
Use subclassing and Factory pattern (class Plugin extends BaseImplementation and have factory instantiate Plugin instead of BaseImplementation). Zend Plugin Loader does something like this.
It's the solution with least overhead, but also is limited to one plugin extending one class.
Add hooks and use delegation (Strategy pattern) ($this->plugin->onFoo()). There's library for this.
PHP doesn't allow this. It may be a dynamic language in other respects, but the class system is deliberately restrictive. You can either install the runkit extension, which changes the language to allow mocking about with classes at runtime (But then you aren't using plain PHP anymore), or you can use the magic-methods to simulate it.
You can override the class, but I don't know if you can reload it in the same request.
some behavior change can be achieved with mediator design pattern (symfony event dispatcher) but you need to know the extension points in advance, and fire events/messages to be caught by an extending class in the future..
if you can wait for the next request, and clear cache if you have it. I made a tool that might help you.
SourceEditor
Here there are more answers to a similar question too, where I put code examples.
How to generate or modify a PHP class at runtime?