How i can create a PHPDoc block for an declarative array?.
For example, let's say that i have the next function:
/**
* #return ??????????
*/
function dummy() {
$x1=array("key1"=>"hello","ke2"=>"world");
return $x1;
}
// ... later
$x1=dummy();
echo $x1["key1"];
I want to be explicit in the array result, instead of use #return array.
(i also tried) I also know that i can return an array of object with #return Class[] but in this case, im not using classes.
Thanks.
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
}
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.
I want to fetch a method's comments,take below method for example:
/**
* Returns the regex to extract all inputs from a file.
* #param string The class name to search for.
* #return string The regex.
*/
public function method($param)
{
//...
}
the result should be
Returns the regex to extract all inputs from a file.
#param string The class name to search for.
#return string The regex.
the way I find is use a function like file_get_content to get file content -> filter the method I want -> fetch the comment use regexp
it seems a bit complicated , is there any convenient way to archive this?
actually you can get a method's doc comments with getDocComment
$ref=new ReflectionMethod('className', 'methodName');
echo $ref->getDocComment();
If you want to use the comment in PHP for something check out getDocComment in php's reflection api
PHP Doc. Like Java Doc.
For a method dump I use this little function I composed.
It fetches all methods from provided class that are public(and thus of use to you).
I personally use a dump() method to nicely format the outputted array of method names and descriptions, but that's not needed if you wish to use it for something else :-)
function getDocumentation($inspectclass) {
/** Get a list of all methods */
$methods = get_class_methods($inspectclass);
/** Get the class name */
$class =get_class($inspectclass);
$arr = [];
foreach($methods as $method) {
$ref=new ReflectionMethod( $class, $method);
/** No use getting private methods */
if($ref->isPublic()) {
$arr[$method] = $ref->getDocComment();
}
}
/** dump is a formatting function I use, feel free to use your own */
return dump($arr);
}
echo getDocumentation($this);
I'm looking at the PHP Manual, and I'm not seeing a section on data structures that most languages have, such as lists and sets. Am I just blind or does PHP not have anything like this built in?
The only native data structure in PHP is array. Fortunately, arrays are quite flexible and can be used as hash tables as well.
http://www.php.net/array
However, there is SPL which is sort of a clone of C++ STL.
http://www.php.net/manual/en/book.spl.php
PHP offers data structures through the Standard PHP Library (SPL) basic extension, which is available and compiled by default in PHP 5.0.0.
The data structures offered are available with PHP 5 >= 5.3.0, and includes:
Doubly Linked Lists
A Doubly Linked List (DLL) is a list of nodes linked in both directions to each others. Iterator’s operations, access to both ends, addition or removal of nodes have a cost of O(1) when the underlying structure is a DLL. It hence provides a decent implementation for stacks and queues.
SplDoublyLinkedList class
SplStack class
SplQueue class
Heaps
Heaps are tree-like structures that follow the heap-property: each node is greater than or equal to its children, when compared using the implemented compare method which is global to the heap.
SplHeap class
SplMaxHeap class
SplMinHeap class
SplPriorityQueue class
Arrays
Arrays are structures that store the data in a continuous way, accessible via indexes. Don’t confuse them with PHP arrays: PHP arrays are in fact implemented as ordered hashtables.
SplFixedArray class
Map
A map is a datastructure holding key-value pairs. PHP arrays can be seen as maps from integers/strings to values. SPL provides a map from objects to data. This map can also be used as an object set.
SplObjectStorage class
Source: http://php.net/manual/en/spl.datastructures.php
PHP 7 introduced an extension called ds providing specialized data structures as an alternative to the array.
The ds,
uses the Ds\ namespace.
has 3 interfaces namely,Collection, Sequence and Hashable
has 8 classes namely, Vector, Deque,Queue, PriorityQueue, Map, Set, Stack, and Pair
For more information checkout the Manual and also This blog post has some awesome information including benchmarks.
The associative array can be used for most basic data structures hashtable, queue, stack. But if you want something like a tree or heap I don't think they exist by default but I'm sure there are free libraries anywhere.
To have an array emulate a stack use array_push() to add and array_pop() to take off
To have an array emulate a queue use array_push() to enqueue and array_shift() to dequeue
An associative array is a hash by default. In PHP they are allowed to have strings as indexes so this works as expected:
$array['key'] = 'value';
Finally, you can kind of emulate a binary tree with an array with the potential to have wasted space. Its useful if you know you're going to have a small tree. Using a linear array, you say for any index (i) you put its left child at index (2i+1) and right child at index (2i+2).
All of these methods are covered nicely in this article on how to make JavaScript arrays emulate higher level data structures.
PHP has arrays, which are actually associative arrays and can also be used as sets. Like many interpreted languages, PHP offers all this under one hood instead of providing different explicit data types.
E.g.
$lst = array(1, 2, 3);
$hsh = array(1 => "This", 2 => "is a", 3 => "test");
Also, take a look in the manual.
PHP's array doubles as both a list and a dictionary.
$myArray = array("Apples", "Oranges", "Pears");
$myScalar = $myArray[0] // == "Apples"
Or to use it as an associative array:
$myArray = array("a"=>"Apples", "b"=>"Oranges", "c"=>"Pears");
$myScalar = $myArray["a"] // == "Apples"
I think you might want to be a bit more specific, when you say data structures my mind goes in a few directions...
Arrays - They are certainly well documented and available in. (http://us.php.net/manual/en/book.array.php)
SQL Data - Depends on the database you are using, but most are available. (http://us.php.net/manual/en/book.mysql.php)
OOP - Depending on the version objects can be designed and implemented. (http://us.php.net/manual/en/language.oop.php) I had to search for OOP to find this on the php site.
Of course PHP has data structures. The array in php is incredibly flexible. Some examples:
$foo = array(
'bar' => array(1,'two',3),
'baz' => explode(" ", "Some nice words")
);
Then you have an absolute plethora of array functions available to map/filter/walk/etc the structures, or convert, flip, reverse, etc.
You can always create your own if you don't feel PHP includes a specific type of data structure. For example, here is a simple Set data structure backed by an Array.
class ArraySet
{
/** Elements in this set */
private $elements;
/** the number of elements in this set */
private $size = 0;
/**
* Constructs this set.
*/
public function ArraySet() {
$this->elements = array();
}
/**
* Adds the specified element to this set if
* it is not already present.
*
* #param any $element
*
* #returns true if the specified element was
* added to this set.
*/
public function add($element) {
if (! in_array($element, $this->elements)) {
$this->elements[] = $element;
$this->size++;
return true;
}
return false;
}
/**
* Adds all of the elements in the specified
* collection to this set if they're not already present.
*
* #param array $collection
*
* #returns true if any of the elements in the
* specified collection where added to this set.
*/
public function addAll($collection) {
$changed = false;
foreach ($collection as $element) {
if ($this->add($element)) {
$changed = true;
}
}
return $changed;
}
/**
* Removes all the elements from this set.
*/
public function clear() {
$this->elements = array();
$this->size = 0;
}
/**
* Checks if this set contains the specified element.
*
* #param any $element
*
* #returns true if this set contains the specified
* element.
*/
public function contains($element) {
return in_array($element, $this->elements);
}
/**
* Checks if this set contains all the specified
* element.
*
* #param array $collection
*
* #returns true if this set contains all the specified
* element.
*/
public function containsAll($collection) {
foreach ($collection as $element) {
if (! in_array($element, $this->elements)) {
return false;
}
}
return true;
}
/**
* Checks if this set contains elements.
*
* #returns true if this set contains no elements.
*/
public function isEmpty() {
return count($this->elements) <= 0;
}
/**
* Get's an iterator over the elements in this set.
*
* #returns an iterator over the elements in this set.
*/
public function iterator() {
return new SimpleIterator($this->elements);
}
/**
* Removes the specified element from this set.
*
* #param any $element
*
* #returns true if the specified element is removed.
*/
public function remove($element) {
if (! in_array($element, $this->elements)) return false;
foreach ($this->elements as $k => $v) {
if ($element == $v) {
unset($this->elements[$k]);
$this->size--;
return true;
}
}
}
/**
* Removes all the specified elements from this set.
*
* #param array $collection
*
* #returns true if all the specified elemensts
* are removed from this set.
*/
public function removeAll($collection) {
$changed = false;
foreach ($collection as $element) {
if ($this->remove($element)) {
$changed = true;
}
}
return $changed;
}
/**
* Retains the elements in this set that are
* in the specified collection. If the specified
* collection is also a set, this method effectively
* modifies this set into the intersection of
* this set and the specified collection.
*
* #param array $collection
*
* #returns true if this set changed as a result
* of the specified collection.
*/
public function retainAll($collection) {
$changed = false;
foreach ($this->elements as $k => $v) {
if (! in_array($v, $collection)) {
unset($this->elements[$k]);
$this->size--;
$changed = true;
}
}
return $changed;
}
/**
* Returns the number of elements in this set.
*
* #returns the number of elements in this set.
*/
public function size() {
return $this->size;
}
/**
* Returns an array that contains all the
* elements in this set.
*
* #returns an array that contains all the
* elements in this set.
*/
public function toArray() {
$elements = $this->elements;
return $elements;
}
}
PHP can also have an array of arrays which is called a "multidimensional array" or "matrix". You can have 2-dimensional arrays, 3-dimensional arrays, etc.