My code review was refused by my co-worker, because of an unnecessary phpdoc on a local array ($params in bottom example) in a function. See the example:
/**
* comment...
*
* #return int
*/
public function testFunction()
{
/** #var string[] $params */
$params = ['string1', 'string2'];
etc...
return 0;
}
Can someone explain to me why defining phpdocs on local arrays is unnecessary? I got an explanation from my co-worker that we don't need to write phpdocs on local arrays. We are using PhpStorm and Doctrine.
Thanks for your time.
Writing a phpdoc like string[] for an array is useful when the array is a parameter or a return value, so you can specify what types of values the array should contain. But in that case it's an array of string literals defined right there. The phpdoc isn't telling you anything you can't know just by looking at it.
Technically #var is intended to document class properties, but in some cases it can be useful inside a function to help the IDE when it's unable to determine the type of a variable. That's not really needed here either, though.
I can't know for sure if that's exactly why your co-worker thought it was unnecessary, but I don't see another logical explanation for it.
Related
an old fashioned example:
/**
* #param string $a - test parameter
*/
public function test($a)
{
}
but now that Php has types, I would write:
/**
* #param $a - test parameter
*/
public function test(string $a)
{
}
since it has a parameter, so adding "string" to phpdoc is verbose.
"Necessary" depends on what you're using to parse the annotation (if anything)*
If this is PHPDocumentor itself, you'll want to stick with the standard that it prescribes. Even if it works without the type now, there's no guarantee that a future version will, and as mentioned in Alex Howansky's answer, the type is currently defined as mandatory. From their manual:
With the #param tag it is possible to document the type and function of a single argument of a function or method. When provided it MUST contain a Type to indicate what is expected; the description on the other hand is OPTIONAL yet RECOMMENDED in case of complicated structures, such as associative arrays.
PHPStorm (at least the version I have in front of me) acts a bit strangely if you leave out the type-hint in a parameter. If I use
* #param $a Some useful comment about my parameter
then I get a warning about Undefined class Some. Apparently it's taking the first word other than the #param annotation and the variable name, and assuming that's the type. I can't find a reference to this behaviour in the phpdoc manual (providing the type after the variable), so that could itself be non-standard. Interestingly, if the first character after the variable name is a hyphen (as in the example in your question), then the warning is supressed.
I've seen a lot of code recently that leaves out the annotations entirely, and relies on the language's internal type-hinting (both parameter and return) to do the job. This is perfect, as long as you don't need to add a description to any of them. PHPStorm will warn you about missing parameter annotations the moment you provide any (but not all) of them, which means if you want to provide a comment for one then you'll need to add the rest, commented or not.
You mention verbosity in your question, and if all you're concerned about is human readability then by all means leave out the type. Phpdoc itself has a standard, but you're absolutely not bound by it. It's your code, ultimately. But if you're shipping a package that other developers might use, or if any of your toolchain (from IDE, through static analysis, to documentation generation itself) aren't happy with the non-standard usage, then you'll have to weigh up the decision again. Either way it comes down to whether you're the only one (person or machine) reading your code; if you're not, then stick with the standards, even if it means typing a few extra characters.
--
* This can include things that actually do affect the way the code runs - PHP allows you to fetch these annotations with the getDocComment methods in the Reflection API. Use-cases for this tend not to include #param annotations (more often it'll be something package specific like Doctrine's ORM annotations), which are almost exclusively used for documentation, but I don't want to over-generalise and say that this can't have an effect on your code's actual functionality.
The phpDocumentor docs state that the Datatype field is required for #param. Those docs are quite old, but I would expect apps which consume tags to still abide by that requirement. Lately, I've tended to skip the #param tag completely when I have an explicit typehint present.
PHPCS will alert if you leave it out but have a typehint, like in your example:
/**
* #param $arg The arg.
*/
public function foo(int $arg) {
PHPStan will alert if you have a #param tag type and a typehint that don't match, like this:
/**
* #param string $arg The arg.
*/
public function foo(int $arg) {
PHP 5 can do some (limited) type hinting, however, it seems to me that in real-world projects, types are usually described in doc comments. For example, instead of this:
/**
* Test method
*/
function test(SomeType $param1) {
...
}
there will more commonly be
/**
* Test method
*
* #param SomeType param1
*/
function test($param1) {
...
}
What are the advantages and disadvantages of the two approaches? And if I'm right in the assumption that the PhpDoc method is more common, why is that? Why don't people utilize the built-in language feature more?
Edit: the third option is to use both approaches combined:
/**
* Test method
*
* #param SomeType param1
*/
function test(SomeType $param1) {
...
}
However, I personally haven't seen this used too often (looked at libraries like Symfony or PHPUnit) and this also seems like doing some work for not much additional benefit to be honest. Maybe that's why it isn't seen more often.
First thing: PHP typehints have different ability to hint than PHPDoc. Differences are (at least):
Scalar types. Before PHP 7.1, you can not hint scalar types, while nothing prevents you from hinting
/**
* #param string $param Param description
*/
Array of hinting. In PHPDoc you can hint, that parameter (or return value) is array of something. It would be:
/**
* #param ClassName[] $param Param description
*/
and meaning of this is - array of instances of ClassName. This is extremely useful when it comes to return type (because IDE then may do substitutions for methods on iteration of that array, and, therefore, you'll know that you're doing correct thing or not). However, in PHP you can only typehint it as
function functionName(array $param) { /*...*/ }
so it won't be possible to realize what are actual elements of array. For your information there is a corresponding RFC for typehinting as array of some elements, which is currently rejected - but may be in future such possibility will appear in PHP.
But, on the other hand, using PHP typehints is still different thing and normally you should do both - so, if it's possible to hint somehow in PHP (like for array sample above) - do it, and add PHPDoc block as well. PHP typehint allows you to enforce behavior on language level, while PHPDoc is only "information" source, it serves only information goal and can not prevent of passing illegal argument type.
Personally I would use both.
First option is good for controling what objects are you passing to the method. Second usually can be added automaticaly by any modern IDE and it makes your code more readable.
I don't know if it's a IDE question or if there's a way to do this with PHP configuration or something.
I want to know if it's possible to create a autocomplete/intellisense feature for a parameter. For example:
function sayALetter($letter){
echo $letter;
}
Now when I call this function, I want to have some autocomplete options for the $letter parameter. (a, b, c, d). In other words, I want to control which values this parameter can receive.
It's possible or I'm talking crazy?
It's been a while, but there is a way (sort of). The thing you need is an IDE that can give hints (eg. PhpStorm). It does not prevent passing on different values tho:
function letters($letters = "ab"|"ad"|"bf"|"ah"|"bj"|"al"|"cn"|"oc") {
return $letters;
}
There are IDEs that give you hints as to what parameters a function expects. This is done via a special comment format just before the function.
Even when writing your own functions, if you stick to the format, the documentation of a function's parameters is done in seconds, and it will instantly be visible to you when you type in the name of the function in another part of the code.
They also have autocomplete, filling in the function's parameter variable names from the definition of your function.
If you type in /** on a line and hit return on a line just before your function definition, your IDE should fill in the skeleton for your function documentation (parameters and return types).
/**
* This function bars foos
* it returns an array in some cases
* otherwise it returns FALSE.
* #param string foo being barred
* #return mixed array of barred foos or FALSE
*/
public function foobar($foo)
{....
This is very useful, since your IDE can now give you hints inside the function regarding the parameters, i.e. what methods/properties are available for the parameter.
However, since php doesn't really have types, you'll still need to make sure that you're getting what you're expecting inside your function.
This is just your IDE helping you out, PHP itself doesn't care.
It should be a triviality, but I haven't found the right syntax for typecasting class variables in PHP. I've tried like this:
public int $approved;
and
public (int) $approved;
but both ways the script does not run. I have lots of names, so seeing the data type visually in the code would help distinction. Is there any way?
PHP has no syntax to accomplish what you want in the class declaration itself. However, the community is coalescing to a large degree around the documentation specs laid out by phpDocumentor. In your case, you would use a #var keyword in the property's doc block.
/**
* #var int
*/
public $approved;
/**
* #var int
*/
protected static $othervar;
If you'd like to see an example of well-documented code using this method, I would recommend looking over the Symfony Framework codebase (although they may not always document class properties).
You won't be able to coerce the type to int when writing to the properties, unless you made them private and created a setter to coerce them via __set(). That that's inflexible because you would need to account for lots of different types. PHP is dynamically typed; most attempts to make it behave otherwise are likely to be fraught with frustration.
Yeah no, PHP does not have strong typing (it will convert any variable into what it's used like).
All you can do is write
public $approved;
and remember that you want to store numeric values in it (when they're coming from a database, PHP might even store the value as a string and implicitly convert to int as soon as you're starting to calculate with it).
Some editors support phpdoc-like hints that can help you remember which variable is which type like:
/**
* #var int
*/
public $approved;
But this is not standard behaviour.
In any way, there is no way of consistently forcing PHP into using only one type on a variable.
In addition to what everybody has said, I would like to add this:
In you really need a true INT (no a string representing a number) then you can make use of intval
What does the #param mean when creating a class? As far as I understand it is used to tell the script what kind of datatype the variables are and what kind of value a function returns, is that right?
For example:
/**
* #param string $some
* #param array $some2
* #return void
*/
IsnĀ“t there another way to do that, I am thinking of things like: void function() { ... } or something like that. And for variables maybe (int)$test;
#param doesn't have special meaning in PHP, it's typically used within a comment to write up documentation. The example you've provided shows just that.
If you use a documentation tool, it will scour the code for #param, #summary, and other similar values (depending on the sophistication of the tool) to automatically generate well formatted documentation for the code.
As others have mentioned the #param you are referring to is part of a comment and not syntactically significant. It is simply there to provide hints to a documentation generator. You can find more information on the supported directives and syntax by looking at the PHPDoc project.
Speaking to the second part of your question... As far as I know, there is not a way to specify the return type in PHP. You also can't force the parameters to be of a specific primitive type (string, integer, etc).
You can, however, required that the parameters be either an array, an object, or a specific type of object as of PHP 5.1 or so.
function importArray(array $myArray)
{
}
PHP will throw an error if you try and call this method with anything besides an array.
class MyClass
{
}
function doStuff(MyClass $o)
{
}
If you attempt to call doStuff with an object of any type except MyClass, PHP will again throw an error.
I know this is old but just for reference, the answer to the second part of the question is now, PHP7.
// this function accepts and returns an int
function age(int $age): int{
return 18;
}
PHP is entirely oblivious to comments. It is used to describe the parameters the method takes only for making the code more readable and understandable.
Additionally, good code practice dedicates to use certain names (such as #param), for documentation generators.
Some IDEs will include the #param and other information in the tooltip when using a hovering over the relevant method.
#param is a part of the description comment that tells you what the input parameter type is. It has nothing to do with code syntax. Use a color supported editor like Notepad++ to easily see whats code and whats comments.