This question already has answers here:
Best way to document Array options in PHPDoc?
(9 answers)
Closed 1 year ago.
How can I specify an array index and sub-index type? Note: I will use it with PHPStorm.
Array example:
function name ($options) {
// $options['length'] => integer
// $options['more'] => array
// $options['more']['test1'] => boolean
// $options['more']['test2'] => boolean
}
Example (that not works):
/**
* #param array $options
* #var int $length
* #var array $more
* #var bool $test1
* #var bool $test2
*/
In general, PhpStorm only support simple syntax, just as Sam has stated, e.g.
/**
* #param string[] $options
*/
The code above described parameter which is array of strings.
Install Options completion plugin -- it supports new proposed syntax for hashes (describing array keys and its' types) in PHPDoc: https://github.com/phpDocumentor/fig-standards/blob/master/proposed/phpdoc.md#7-describing-hashes
This plugin will add code completion for array keys.
<?php
class Element {
/**
* 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())
{
// some code here
}
}
new Element(['label' => 'Bob', '|' ]);
// | Ctrl+Space will show supported attributes
NOTE: Main purpose of this plugin is to offer array keys completion -- I'm not sure how well it supports type resolutions for each of array elements (in case if they are different like in your example).
It looks like, according to the docs, that it's only possible to define an array as a set of one specific type (instead of setting a type for each index):
/**
* #param string[] $options
*/
The better solution would probably be to make $options a class, so length and test1 could be properties with default values and pre-defined types.
Related
There is still an open issue about how to annotate array keys with PhpDoc: https://github.com/phpDocumentor/phpDocumentor2/issues/650
I tried the following notations:
/**
* #return array<string, SomeClass>
* #return SomeClass[string]
*/
public function someMethod(): array { ... }
but PhpStorm seem to be unable resolve this appropriate, so that when using e.g.
foreach the inner object is unknown:
foreach($obj->someMethod() as $some) {
$some->methodOfSomeClass(); // PhpStorm -> Method not found
}
I know i can use the pipe operator:
#return array<string, SomeClass>|SomeClass[]
I also know that i can type hint variables:
/** #var SomeClass $obj */
$obj
But is there a way to configure PhpStorm to know the array value type without using the pipe?
In PHP you either have numeric indexed arrays which have integer keys or associative arrays with string keys. Due to the dynamic typing you can just mix these up and therefore can have both types.
Also in your example you are not using your key but the value, these are hinted with ClassName[].
/**
* #return Class[]
*/
function getClasses(): array {
return [new Class()];
}
With this typhinting PHPStorm will provide valid tooltips in forEach loops.
Otherwise you can use the inline #type comment.
foreach ($objs as $obj) {
/* #type Class $obj */
$obj->someMethod(); //Is hinted
}
PHPDoc is the adaptation of JavaDoc to PHP. With the correct syntax in comments, you can use it to document the types of things. Tools such as IDEs can then use that metadata.
Here's an example using a 'simple' array of strings.
/**
* #param string[] $strings This parameter is blah blah blah.
*/
public function foo($strings) {
// ...
}
But PHP "arrays" can also be used as maps (aka hash tables aka dictionaries.) Here's an example from the PHP documentation (http://php.net/manual/en/language.types.array.php):
$array = array(
"foo" => "bar",
"bar" => "foo",
);
Now assume we modify our function foo to take things like $array above: an array of string => string.
/**
* #param ??????? entries This parameter is blah blah blah.
*/
public function foo($entries) {
// ...
}
How should the type of $entries be represented in PHPDoc?
http://www.phpdoc.org/docs/latest/guides/types.html#arrays doesn't even mention such a construct existing in the language.
You can at least document that $entries should be an array of strings:
/**
* #param string[] entries
*/
public function foo($entries)
{
// ...
}
However, you could also modify the method signature to add a type-declaration for array:
/**
* #param string[] entries
*/
public function foo(array $entries)
{
// ...
}
And furthermore, you could guard against invalid values being passed in by either writing your own assertions, or using, for example, beberlei/assert:
use Assert\Assertion;
/**
* #param string[] entries
*
* #throws InvalidArgumentException
*/
public function foo(array $entries)
{
Assertion::allString($entries);
Assertion::allString(array_keys($entries));
// ...
}
This doesn't help a lot with the docblock, but it documents the requirements in regard to your parameters in the code itself.
I would recommend to avoid using arrays for data structures in PHP code. Classes with explicitly defined properties are much more suitable.
As a workaround you can use stub classes to describe array structure, though you'll need to cast array to object to benefit from this.
$array = array(
"foo" => "bar",
"bar" => "foo",
);
/**
* #property $foo
* #property $bar
*/
class MyStub {}
/** #var MyStub $object */
$object = (object)$array;
// IDE completion and inspections are now available
$object->foo .= $object->bar;
// optional casting back to array
$array = (array)$object;
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.
When creating form elements with Zend (using Zend Studio for Eclipse), I'd like some auto completion or hints. Here's what I'm thinking. I'm sure these exist, but I don't know how to get them.
I type createElement and auto-completes gives me the signature createElement($type, $name). Great, I select it.
but when I try to set the $type I don't get any hints like DateTextBox or ValidationTextBox. Being new, I see how this can be useful. What do you do to remember all the options?
for the array of attributes like require, invalidMessage, I'd like to get a list of those to choose from, and/or auto-complete when I start typing one.
// Date field
$date = $this->createElement('DateTextBox', 'date',
array('require' => 'true', 'invalidMessage' => 'Invalid date format')
);
$date->setLabel('date')->setRequired(true);
You have few options to help yourself, without waiting for any plugin:
learn it and remember ;)
extend your phpDoc blocks with all available options:
Example (to be honest I don't know if Eclipse supports html in phpDoc or even any text after variable name in #param, but it works fine in Netbeans):
/**
* [...]
* #param string $type Can be: <ul><li>DateTextBox</li><li>ValidationTextBox</li></ul>
* #param string $name Whatever
* #param array|Zend_Config $options Array with following keys: <ul><li>require</li><li>invalidMessage</li></ul>
* #return Zend_Form_Element
*/
public function createElement($type, $name, $options = null)
extend Zend class and create your own methods to simplify your work
Example:
class My_Zend_Form_Element extends Zend_Form_Element
{
public function createDateTextBox($name, $options = null)
{
return $this->createElement('DateTextBox', $name, $options);
}
}
declare some well named constants and provide some hint in phpDoc
Example: (type ZFE_OPTIONS and IDE should show hint with some constants to use as array keys)
/**
* Can be true or false
*/
define('ZFE_OPTIONS_REQUIRE','require');
create your own helper classes with methods to produce valid options array
Example:
class ZFE_Options
{
protected $opts = array();
/**
* #param bool $req
* #return ZFE_Options
*/
public function setRequired($req){
$this->opts['require'] = (bool)$req;
return $this;
}
/**
* #param string $txt
* #return ZFE_Options
*/
public function setInvalidMessage($txt){
$this->opts['invalidMessage'] = (string)$txt;
return $this;
}
/**
* #return array
*/
public function toArray(){
return $this->opts;
}
}
$zfe_options = new ZFE_Options();
$opts = $zfe_options
->setRequired(true)
->setInvalidMessage('Please provide valid email address')
->toArray();
That's not possible. It's not how autocompletion works. The hints you get are taken directly from ZF's code documentation. Nothing more, nothing less. Everything you see as hints is taken directly from the DocBlock and method signature, e.g.
/**
* Create an element
*
* Acts as a factory for creating elements. Elements created with this
* method will not be attached to the form, but will contain element
* settings as specified in the form object (including plugin loader
* prefix paths, default decorators, etc.).
*
* #param string $type
* #param string $name
* #param array|Zend_Config $options
* #return Zend_Form_Element
*/
public function createElement($type, $name, $options = null)
Eclipse can tell you to insert a string or an array and it will know that the method returns a Zend_Form_Element, but it cannot tell you what these strings should be.
The only place where I know something like what you describe exists is for CSS files. For some reason, when I type in display: it will give me an autocomplete box with possible values for this declaration. If you want more sophisticated autocomplete like this, consider filing this as a feature request to Zend.
The API gives the code as:
public function up()
{
$this->addColumn('table_name', 'column_name', 'string', $options);
}
but there's no documentation for what can be included in the options array.
http://www.doctrine-project.org/Doctrine_Migration_Base/1_2#method_addcolumn
For people coming in: it looks like this is really defined from the Data Access Layer. Here is the list of options for columns from the DBAL docs: http://docs.doctrine-project.org/projects/doctrine-dbal/en/latest/reference/schema-representation.html
The documentation is wrong. Looking in Doctrine/Migration/base.php, you can see the following function prototype:
/**
* Add a add column change.
*
* #param string $tableName Name of the table
* #param string $columnName Name of the column
* #param string $type Type of the column
* #param string $length Length of the column
* #param array $options Array of options for the column
* #return void
*/
public function addColumn($tableName, $columnName, $type, $length = null, array $options = array())
So to add the length, you give it as the 4th parameter. I'm ignoring the options for the moment.
Following the "browse code" link on the top, you can follow the code to $options['length'] in Doctrine_Migration_Base::column() and the second parameter in Doctrine_Migration_Base::_addChange(). Check out the source code from time to time, it gives you an overview :)