Is there a way to hint WebIDE that a variable has some type?
I have to iterate an array of objects, and there's no auto-completion available.
This helps in ZendStudio:
/* #var ClassName $object */
I know there's a feature in JetBrains to declare an array of objects:
/**
* #return ClassName[]
*/
But this works only with function's return type.
/* #var ClassName $object */ is a non-valid PHPDOC comment and is not parsed in the current version of Web IDE. Use double asterisks to make it work:
/** #var ClassName $object */
Also, you can annotate $array in foreach($array as $var) with /** #var ClassName[] $array */ and $var type will be deduced automatically.
As already pointed out, PhpStorm will use regular phpdoc blocks:
/** #var ClassName $object */
However, since 2.1 it also supports Netbeans/Eclipse/Zend #var annotations:
/* #var $object ClassName */
Please note the comment starts with /* rather than /** (thus it won't show up if you generate actual documentation with phpdoc). Also, the arguments are swapped, though PhpStorm accepts any order:
/* #var ClassName $object */
Last but not least, they can precede almost any arbitrary line of code (technically, phpdoc blocks are restricted to certain items).
Edit: as of 2019, Netbeans/Eclipse/Zend #var annotations seem to be mostly abandoned. NetBeans 11 no longer supports them and in general they aren't supported by other IDEs. I suggest to use the other syntax.
Related
In a post on the software engineering forum me and the community agreed that one of my architecture problems might be best solved using generics. Since in PHP generics are only supported via doc tags, my interface declarations always have two param types hinted: The #param tag and the PHP type declaration:
<?php
/**
* #template T of NodeInterface
*/
interface DirectedLinkInterface
{
/**
* #param T $startNode
*/
public function setStartNode(NodeInterface $startNode);
}
The problem is that whenever I use PHP's type declaration, PhpStorm ignores the more specific template variable.
Example:
I have a class that implements a specific version of the generic interface:
/**
* #template-implements DirectedLinkInterface<DrawActionNode>
*/
class DirectedImageProcessingLink implements DirectedLinkInterface, FollowLinkInterface
{
/**
* #param DrawActionNode $startNode
*/
public function setStartNode(NodeInterface $startNode): void
{
$this->startNode = $startNode;
}
}
But when I use this class incorrectly, PhpStorm doesn't find the error, UNLESS I remove the type declarations:
$node = new WhateverNodeInterface();
$link = new DirectedImageProcessingLink();
$link->setStartNode($node); //No error found by PhpStorm
The above code will only be considered as faulty when I remove the type declaration, which I don't really want since a missing type declaration looks kind of old school php hackish, even if the hinted type is more generic than the PHPDoc.
<?php
/**
* #template T of NodeInterface
*/
interface DirectedLinkInterface
{
/**
* #param T $startNode
*/
public function setStartNode(/*No type declaration here*/ $startNode);
//Removing the type declaration as done above makes PhpStorm use the actual template
//variable which, in the interface user's code, will be more specific and thus errors can be better found
}
Do you know any way to convince PhpStorm to use the #param tag even though there is a type declaration? Or do you think that type declarations aren't that necessary if you use #param tags in combination with generics?
I want to add a type of object in #property-read and also be able to access its attributes with PhpStorm suggestions.
Here's what I would like to do:
/**
* #property-read object{type: string, schema: string} $request_schema
* #property-read object{type: string, schema: string} $response_schema
*/
class ConfigApiRoutesSchema extends BaseSchema
{
...
}
The reason I'm doing this is because I want to access the attributes type and schema, like this:
$configApiRoutesSchema = new ConfigApiRoutesSchema();
$configApiRoutesSchema->request_schema->type // Here's the problem, type is not suggested
$configApiRoutesSchema->request_schema->schema // schema is also not suggested
This is exactly what I need, but unfortunately this doesn't work for some reason. One solution is to create two classes and specify them as types:
/**
* #property-read string $type
* #property-read string $schema
*/
class RequestSchema {}
/**
* #property-read string $type
* #property-read string $schema
*/
class ResponseSchema {}
/**
* #property-read RequestSchema $request_schema
* #property-read ResponseSchema $response_schema
* #
*/
class ConfigApiRoutesSchema extends BaseSchema {}
Now PhpStorm suggests both schema and type.
But it doesn't seem correct, since RequestSchema and ResponseSchema won't actually be used. So I wonder if there's any way of using annotation with objects without having to create a class to suggest its attributes.
Thank you.
Altho it is possible to specify the shape of arrays, for objects it is not possible to do so (yet). Such a syntax would have been be specified in PSR-5 and PSR-19, but this is not the case.
In the same manner it is not possible to specify the properties of a returned plain object from a method with the #return object annotion.
Apparently the syntax is supported by Psalm, but not in PhpStorm (at very least not yet).
Currently there is a public proposal on the PhpStorm YouTrack board. You might want to upvote that issue to increase it's chance of being included in the next PhpStorm version.
Is there a way to make NetBeans understand PHPDoc (and old PHPStorm) format of Type hinting?
PhpStorm is using regular phpdoc blocks:
/** #var ClassName $object */
Netbeans/Eclipse/Zend style (supported by PhpStorm since 2.1)
/* #var $object ClassName */
Differences
1) Comment starts with /* rather than /** (thus it does not follow phpdoc convention).
2) And the arguments are swapped (PhpStorm accepts any order)
/* #var ClassName $object */
Can anyone advise where in the PSR standards docs it documents that there should be nothing after the variable type in class member variables?
I used PHP CodeStyle Fixer by doing the following: php-cs-fixer fix MyConsoleCommand.php
...and it removed the variable from the docblock. I have been doing this for some time now and I believed this was correct and standards-compliant.
Can anyone confirm?
/**
- * #var SiteManager $siteManager
+ * #var SiteManager
*/
private $siteManager;
/**
- * #var Registry $doctrine
+ * #var Registry
*/
private $doctrine;
By default all the levels are on and this particulair behaviour comes from the sympfony standard
phpdoc_var_without_name [symfony]
#var and #type annotations should not contain the variable name.
see https://github.com/FriendsOfPHP/PHP-CS-Fixer and search for "phpdoc_var_without_name"
if you don't want to use the Symfony standard do
php php-cs-fixer.phar fix MyConsoleCommand.php --level=psr2
hope it helps
What I want is that when I declare a magic method with #method PHPDoc, can i use #see so that the magic method has the same PHPDoc as the method pointed via #see
Here is the code of what I have tried. But IDE did not recognize it. I am using Netbeans 7.3.1.
/**
* #method string my_method() #see _my_method()
*/
class Foo {
public __call($name, $args) {
$name = "_".$name;
$this->$name($args);
}
/**
* #return String
*/
protected _my_method() {
return "bar";
}
}
The exact parsing will depend on which IDE you're using, but the PHPDocumentor documentation for #see shows a couple of differences from your usage:
The #see tag is on its own line, not appended to the line before. #link has a separate "inline" syntax if you want to include a cross-reference inside a description ({#link http://example.com/my/bar}).
The "target" should be a fully qualified element name, not just the local method name, e.g. #see Foo::_my_method()
There is also a draft PSR to standardise the behaviour, with similar requirements.
I would like to create links to "other" methods to, and I tried #see, #link and lots of other stuff, without any helpfull results.
In phpstorm everything is yust displayed as text.
BUT:
I discovered, that you can write own html-code, so
e.g.
/**
* #method string my_method() see _my_method()
*/
class Foo {
}
would work to create links on external pages.
Unfortunally it only works for external links, and not for links to methods in your editor.