Optional nullable parameters in PHPDoc - php

Imagine that we have method with optional nullable argument (PHP 7.0) like in this example:
/**
* #param Type1 $foo
* #param Type2 $bar
*/
function myFunction(Type1 $foo, Type2 $bar = null)
{
}
Unfortunately it's not clear from the PHPDoc documentation, what is the right way to mark the second argument optional and nullable.
Typically I use "Type2|null" notation:
/**
* #param Type1 $foo
* #param Type2|null $bar
*/
function myFunction(Type1 $foo, Type2 $bar = null)
{
}
Actually this is my preferable way, because it explicitly describes all the possible types. But I heard complaints that is not obvious from the doc if the parameter is optional or not.
I'm aware of, seams like, unofficial convention "(optional)"
/**
* #param Type1 $foo
* #param Type2 $bar (optional)
*/
function myFunction(Type1 $foo, Type2 $bar = null)
{
}
I don't like this approach, because, technically, you can explicitly provide NULL as a second argument. And it's not clear from the phpdoc.
Generally speaking, I can even use them together:
* #param Type2|null $bar (optional)
But it doesn't look nice, IMHO.
Could you provide me some feedback or, even better, some links to corresponding coding standards / style guides?

#param Type2|null $bar
is the proper way, from the perspective of phpDocumentor... see the last three arguments of the getOption() method as shown here.

Related

Code Inspection in PhpStorm

PhpStorm does not detect undefined variables, when they are passed to a function by reference.
func1($a);
func2($a);
function func1(&$a) {
}
function func2($a) {
}
In this example, only the variable $a in the invocation of func2 is highlighted.
How can I change that?
Put under function func1 something like this:
/**
* func1
*
* #param string $a
* #return mixed
*/
Its better to describe all methods and properties by PHP Annotations. And change string if it is another type.

PHPStorm Type hinting array of different types

Is it possible in PHPStorm to type hint an array with different object types, ie:
public function getThings()
{
return array (new Thing(), new OtherThing(), new SomethingElse());
}
Even declaring them separately before building the array doesn't seem to work.
you can use phpdocs in order for phpstorm to accept an array of multiple types like so:
/**
* #return Thing[] | OtherThing[] | SomethingElse[]
*
*/
public function getThings()
{
return array (new Thing(), new OtherThing(), new SomethingElse());
}
This technique will make phpstorm think that the array could contain any of those objects and so it will give you type hinting for all three.
Alternatively you can make all of the objects extend another object or implement an interface and type hint that once object or interface like so:
/**
* #return ExtensionClass[]
*
*/
public function getThings()
{
return array (new Thing(), new OtherThing(), new SomethingElse());
}
This will give you type hints for only what the classes extend or implement from the parent class or interface.
I hope this helped!
This is described in the PHPDoc standards
https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#713-param
/**
* Initializes this class with the given options.
*
* #param array $options {
* #var bool $required Whether this element is required
* #var string $label The display name for this element
* }
*/
public function __construct(array $options = array())
{
<...>
}
In PHP, I've seen a very nice way of doing this:
#return array<Thing,OtherThing,SomethingElse>
IDEs like PHPStorm and VSCode understand this syntax pretty well. Hope this helps.

Documenting groups of class constants with phpDocumentor

Let's say I've got a method that has a parameter, whose valid values are declared as class constants (think PGSQL_ASSOC/PGSQL_NUM/PGSQL_BOTH). And there's another method, with a similar parameter, using another set of class constants. Is there a way to describe to phpDocumentor that each set of constants as belonging to a logical group of alternatives? It would be useful to have them documented in groups, and being able to refer to the specific groups in the method documentation. Using docblock templates doesn't cut it, as the template's short description is ignored (adding useless clutter), while the long description of the template is appended to the constant-specific description, resulting in kind-of backwards wording (e.g. "BAR_MODE_1 does this and that. Operation modes for Foo::bar()", instead of "Operation modes for Foo::bar(): BAR_MODE_1 does this and that.").
Example:
class Foo {
// this group of constants are valid modes for the bar() method
const BAR_MODE_1 = 1;
const BAR_MODE_2 = 2;
const BAR_MODE_3 = 3;
/**
* #param int see Foo::BAR_MODE_* constants
*/
public function bar($mode) { ... }
// this group of constants are valid modes for the baz() method
const BAZ_MODE_1 = 1;
const BAZ_MODE_2 = 2;
const BAZ_MODE_3 = 3;
/**
* #param int see Foo::BAZ_MODE_* constants
*/
public function baz($mode) { ... }
}
Another style may be to use the PHPDocumentor DocBlock Templates
/**##+
* This comment applies to each in the block
*
* #var varType
*/
protected $_var1 = 1;
protected $_var2 = 2;
/**##-*/
see: http://manual.phpdoc.org/HTMLSmartyConverter/HandS/phpDocumentor/tutorial_phpDocumentor.howto.pkg.html#basics.docblock
First thing which comes to my mind is the #see - Tag, it display a link to the documentation for an element.
/**
* #param int
* #see Foo::BAR_MODE_* constants
*/
public function bar($mode) { ... }
More details can be found here in the manual.

How to use phpDoc with overloaded methods?

Let's say I have a PHP class called Color, it's constructor accepts various params.
// hex color
$myColor = new Color('#FF008C');
// rgb channels
$myColor = new Color(253,15,82);
// array of rgb channels
$myColor = new Color(array(253,15,82));
// X11 color name
$myColor = new Color('lightGreen');
How should I use phpDoc to create API documentation for constructor and other methods like this?
How to use phpDoc with overloaded methods?
class Color {
/**
* Constructor
* what should be here?
*/
public function __construct() {
/* CODE */
}
}
Just my point of view, but you should not have multiple constructors in the first place - your constructor is going to be full of if/else-ladders, which really isn't a good idea, especially for something lightweight like a representation of a Color.
I strongly encourage you to try something like this instead:
class Color
{
protected function __construct($r, $g, $b)
{ ... }
public static function fromHex($hex) {
return new Color(...);
}
public static function fromRGB($r, $g, $b) { ... }
public static function fromArray(array $rgb) { ... }
...
}
Now, in consumer code, instead of somewhat mysterious and ambiguous constructor calls like these:
$a = new Color(0,0,0);
$b = new Color('#000000');
Instead you can have more legible and semantic consumer code, like this:
$a = Color::fromRGB(0,0,0);
$b = Color::fromHex('#000000');
This probably makes more sense to somebody reading the consumer code, it eliminates the logic required to make the ambiguous constructor work, and as a bonus (if you're using an IDE such as PhpStorm) you can have all your inspections pass. If you're running a documentation generator, this also ensures that all the options are documented individually, rather than lumped together in a verbal description.
Note that I declared the constructor protected - this is a personal preference, but if I'm going to have multiple static factory-methods, I prefer to see those consistently used in consumer code, rather than sometimes seeing Color::fromRGB(...) and other times new Color(...).
I think that is better to use #method annotation for class/interface, which declares overloading methods. This question is interesting for me too.
/**
* #method void setValue(int $value)
* #method void setValue(string $value)
* #method void setValue(string $value, int $startFrom)
*/
class Example
{
public function setValue($arg1, $arg2)
{
// ...
}
}
See http://phpdoc.org/docs/latest/references/phpdoc/tags/method.html
Because you allow variable length arguments there are two ways I would do this.
I would simply list the allowed arguments are parameters.
/**
* #param mixed $arg1 ... description
* #param mixed $arg2 ... description
* #param mixed $arg3 ... description
*/
public function __construct() {}
Or I would simply provide an explanation with some examples.
/**
* Explanation of different expected argument combinations.
*/
public function __construct() {}
Another alternative, since only one of the examples has more than one argument, would be to simply define the arguments in the method signature making the last 2 optional. Like this:
/**
* #param mixed $arg1 ...
* #param int $arg2 ...
* #param int $arg3 ...
*/
public function __construct($arg1, $arg2 = null, $arg3 = null) {}
I know of no elegant way to do this with phpDoc. The phpDoc comment/api formatting is based on a the Javadoc format. Javadoc doesn't have a feature set to support this because in java, if you want a method to have a variable number of arguments you re-declare the method prototype for each variation.
public double foo() {
}
public double foo(double my_param) {
}
So, my performance preference is to do something like
/**
* My General description
*
* Here explain what each argument combination can do
* #param mixed $arg1 can be array, string, hex as string, or int
* #param int $arg2 if arg1 is int, then this is etc, otherwise optional
* #param int $arg3 if ar1 is int, then this is etc, otherwise optional
*/
but this may not play nice with the various auto-documentation tools.
The according to Hoyle way to accomplish this can be found at the phpDoc site.

PHPDoc for variable-length arrays of arguments

Is there a syntax for documenting functions which take a single configuration array, rather than individual parameters?
I'm thinking specifically of CodeIgniter-style libraries, which use a mechanism similar to this:
<?php
//
// Library definition
//
class MyLibrary {
var $foo;
var $bar;
var $baz;
// ... and many more vars...
/* Following is how CodeIgniter documents their built-in libraries,
* which is mostly useless. AFAIK they should be specifying a name
* and description for their #param (which they don't) and omitting
* #return for constructors
*/
/**
* #access public
* #param array
* #return void
*/
function MyLibrary($config = array()) {
foreach ($config as $key => $value) {
$this->$key = $value;
}
}
}
//
// Library usage:
//
// Iniitialize our configuration parameters
$config['foo'] = 'test';
$config['bar'] = 4;
$config['baz'] = array('x', 'y', 'z');
$x = new MyLibrary($config);
?>
So my question is, is there some supprted way of documenting the configuration array beyond just the purely textual description? Actually specifying a proper #param [type] [name] [desc] that allows PHPDoc to parse out useful values?
As an aside, CodeIgniter really does just overwrite it's own values with those passed in via the $config array as above, effectively allowing you to clobber private members. I'm not a fan, but I'm stuck with it.
I've never seen any "good" way of documenting this -- and I've never seen anything that could be used by IDEs (such as Eclipse PDT) for parameters hinting either :-(
I would have said "do like your framework does", but as you said, what it does, here, is not quite good enough...
Maybe a quick/sort list of possible keys might be better than nothing, though ; a bit like this :
#param array $config [key1=>int, otherKey=>string]
Not sure how it would be interpreted by phpDocumentor or an IDE... But might be worth a try ?
This is, btw, one reason why I tend to avoid that kind of way of passing parameters -- at least when there are not too many (optional) parameters to a method.
The correct array #param notation for arrays is as specified in PHPlint
You can use it to document a config array in a useful manner:
Example:
/**
* Does stuff
*
* #param array[int|string]array[string]Object $config
*
* #return array[int]string
*/
public function foo(array $config)
{
// do stuff here
return array('foo', 'bar', 'baz');
}
You can do this:
/**
* #param array $param1
* #param string $param1['hello']
*/
function hey($param1)
{
}
and netbeans will pick it up but phpdoc messes up the documentation
I always use <pre> tags in situations like this. Ex.:
/**
* #param array $ops An array of options with the following keys:<pre>
* foo: (string) Some description...
* bar: (array) An array of bar data, with the following keys:
* boo: (string) ...
* far: (int) ...
* baz: (bool) ...
* </pre>
*/
Most IDEs and documentation generators I have used seem to render this in a reasonable way, though of course they don't provide any type checking or inspection of the array parameters.
There is currently no "official" (as in 'supported by multiple tools') way to do this.
The PHP FIG is discussing it at the moment at https://groups.google.com/d/topic/php-fig/o4ko1XsGtAw/discussion
A text description, to whatever degree of completeness you want, is really your only option. You can make it as legible as you want, but code analysis tools (phpDocumentor, IDE support) have no way to know how your $array is actually structured at runtime.
I agree with the many commenters that writing code this way exchanges coding convenience for code legibility.
I've used classes.
<?php
class MyLibrary {
var $foo;
var $bar;
var $baz;
/**
* #param MyLibraryConfig|null $config
*/
function MyLibrary( $config = null ) {
if ( isset( $config->foo ) ) {
$this->foo = $config->foo;
}
if ( isset( $config->baz ) ) {
$this->baz = $config->baz;
}
if ( isset( $config->bar ) ) {
$this->bar = $config->bar;
}
}
}
/**
* #property string $foo
* #property int $bar
* #property array $baz
*/
class MyLibraryConfig {
}
It works fairly well, main problem is that the code becomes littered with specific classes. They can be nested so parts of configuration can be reused.

Categories