I've created new project using PhalconPHP 3.1.2. Everything works fine, but I have problem with IDE. In PhpStorm I've added ide/stubs/Phalcon from phalcon-devtools 3.1.2 as external libraries to dispose of warnings and errors.
But there is still one problem: in app/config/router.php (standard catalog structure created by devtools) I got line $router = $di->getRouter(); (also created by devtools) with warning: Method getRouter not found in Phalcon\Di\FactoryDefault.
There is no method in this class indeed: https://github.com/phalcon/phalcon-devtools/blob/3.1.x/ide/stubs/Phalcon/di/FactoryDefault.php -> https://github.com/phalcon/phalcon-devtools/blob/3.1.x/ide/stubs/Phalcon/Di.php
Now I don't have autocomplete of router's methods and this is problem for me. Did I do something wrong?
First of all -- I'm not familiar with Phalcon. These are my comments based on general PHP/PhpStorm experience.
So .. if you look at that PHPDoc in the last link you gave (stubs for Di.php) you will notice the code example there that has $request = $di->getRequest();.
If you just copy-paste that whole sample you will get the same "method not found" error ... as getRquest() is transformed at run time via magic __get() method.
The possible solution here is to create your own stub for your $di:
Create new class that will extend original Di, e.g.
class MyDi extends \Phalcon\Di
Add all those getRoute() / getRequest() etc methods there (could be real methods with empty bodies as in Phalcon's stub files .. or via #method PHPDoc tag)
Place such file anywhere in the project -- it will be used by IDE only.
When you are using your $di -- typehint it with your class, e.g.
/** #var \MyDi $di */
$di = new Di();
In the above code during runtime $di will be an instance of Di but for PhpStorm during development it will be MyDi so all type hints are in place.
As possible alternative -- instead of using magic via $di->getRoute() .. try $di->getShared('route') or similar.
If you use PhpStorm's Advanced Metadata functionality it will allow to get correct type based on parameter value.
$di->getRouter() is magic method, Phalcon\Di implements __call method and it gets router service this way if you use getRouter().
If you want you can use PHPStorm metadata and use $di->get() https://www.google.pl/search?client=opera&q=phpstorm+metadata&sourceid=opera&ie=UTF-8&oe=UTF-8
Related
I'm developing a PHP (v7.0.33) project using VScode (v1.56). I recently installed the VSCode's extension Intelephense (v1.7.1) and started to clean my code following Intelephense suggestions.
A set of classes inside my project has the following structure (function names are not real, but just to let you see that for each sublcass I have some function overrided from the superclass (those with the prefix baseFunction) and new functions specific for that subclass (those with the class acronym like fdmSpecificFunction):
According to the diagram, each DocumentSaver has an instance of a DocumentManager.
The code where I create an instance of, for example, FatturaVenditaDocumentSaver is
$documentManager = new FatturaVenditaDocumentManager();
$documentSaver = new FatturaVenditaDocumentSaver($documentManager);
$documentSaver->baseFunction1();
Consider the following code inside FatturaVenditaDocumentSaver:
public function baseFunction1() {
parent::baseFunction1();
$this->documentManager->fvdmSpecificFunction1();
}
This is a common implementation in OOP, using polymorphism and dynamic binding: having created the instance of FatturaVenditaDocumentSaver with a document manager instantiated from FatturaVenditaDocumentManager, the call $documentSaver->baseFunction1() will execute the code implemented in FatturaVenditaDocumentSaver and, inside it, will correctly execute the code inside fvdmSpecificFunction1() implemented in FatturaVenditaDocumentManager.
The problem is that Intelephense, as fvdmSpecificFunction is not defined in BaseDocumentManager, gives me the error "Undefined method 'fvdmSpecificFunction1'. Intelephense (1013)".
Is there a way to let Intelephense understand the real implementation of my code (considering that Intelephense parse all my PHP code)? I'd like to avoid to disable the Intelliphense's "undefined method" check and I don't like to add an empty fvdmSpecificFunction1 in BaseDocumentManager as is not consistent with the project's logic.
Thank you in advance for your help.
Solution found!
I had just to add the #property hint before the class block, specifying the type of the object $documentManager.
/**
* #property FatturaVenditaDocumentManager $documentManager
*/
class FatturaVenditaSaver extends FatturaSaver {
public function baseFunction1() {
parent::baseFunction1();
$this->documentManager->fvdmSpecificFunction1();
}
}
In this way, Intelephense understands the real class related to that object.
The issue
I have an unexpected warning from PHPStorm when I try to set a new value in a PHP-DI container.
Given the following code:
function inject(Psr\Container\ContainerInterface $container){
$container->set(RandomClass::class, new RandomClass());
}
$container = new DI\Container(); class is instantiated
inject($container);
The following warning is triggered
Potentially polymorphic call. does not have members in its hierarchy
I understand what the warning means, but I do not see why it pops up, especially since I have not found any occurrences of this situation while looking on Google and SO and the documentation does not mention it.
Is there something I am missing, or is this a "false positive" ?
The set() method is not part of Psr\Container\ContainerInterface.
If you want to use that method, you can't typehint against the interface because your code explicitly needs a PHP-DI instance.
Your code doesn't have to be generic, don't overthink things too much. The PSR is useful mostly for frameworks and libraries (who need to be compatible with multiple containers), not for end-users.
The day you switch container library you will have many more complex things to do than just replacing the set() call.
The reason behind the issue
Given the following code (which is very similar to the one I use)
function inject(Psr\Container\ContainerInterface $container){
$container->set(RandomClass::class, new RandomClass());
}
$container = new DI\Container(); class is instantiated
inject($container);
The $container->set(...) call is going to trigger the following warning
Potentially polymorphic call. does not have members in its hierarchy
This is to be expected as Psr\Container\ContainerInterface only contains definitions for the following methods
get($id)
has($id)
The solution
Two possible solutions for this issue:
Type the methods directly with the container, making sure to not use the FQN of the class but only use Container and "use the namespace", it will make changing to a new container package easier (because this is still the goal behind PSRs, being able to almost hot-swap packages).
Create a custom interface based on Psr\Container\ContainerInterface and add the required methods to it.
Or, eventually, you can try to make PHP-FIG extend the PSR-11 standard to include a standard set($id, $value) method.
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'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
Sorry for the bad title, but I had no idea to give a good title for my problem.
I created a package with the workbench. And now I have a package. Let's say strernd/mypkg
Inside the workbench directory Strernd/Mypkg I've got following code:
http://laravel.io/bin/oNzoa
Why does Mypkg::test()work and $mypkg = new Mypkg(); $mypkg->test(); not? (Inside my app)
The error is
Call to undefined method Strernd\Mypkg\Facades\Mypkg::test()Call to undefined method Strernd\Mypkg\Facades\Mypkg::test()
I think I'm not understanding some basic principles of PHP here. I'm more like a copy&paste / try&error "developer", but it works out well in most cases.
When using it the 'static' way, Laravel is accessing the facade you wrote and instantiating the underlying class, then calling the method on that instance. When you are calling the test method with new Mypkg, you are actually instantiating the facade class, and not the underlying class. That facade class does not have a test method on it, hence the error.
Try it like this:
use Strernd\Mypkg as MypkgActual;
$mypkg = new MypkgActual;
$mypkg->test();
I believe that, because your facade and actual class implementation have the same exact class name, you're running in to a pseudo-class name conflict with Laravel's facade system winning out. You can also try changing the name of your facade to MypkgFacade.