PHPDoc - Different objects with different class within an array - php

Let's say that I have a function that returns array $data with a User object $user and a Car object $car
function my_function(){
return array(
new User(),
new Car()
);
}
What should I use for my #return parameter for the function documentation?

I Would do it this way
/**
* #return User[]|Car[]
*/
General | means or and SomeType[] means there is an array of SomeType
Are you Sure, you did not want this?
/**
* My Parent Object
*/
class SomeClass {
/**
* The User
* #var User
*/
public $User;
/**
* The Car
* #var Car
*/
public $Car;
}
The good (evil) thing about PHP is, you can mix array types. In a strong Typed Language (for reason) you can not. Here we use Interfaces and something like this. What we try with PHPDoc is to strong type PHP. So you should play the rules of a strong typed language.

Related

Get the object of Child type instead of parent from MongoDB

I am trying to retrieve the object from MongoDB but I am facing an issue that it is returning the element of base type instead of child and it is causing trouble, I figured out that it is somehow dependent on a property's value.
/**
* #MongoDB\Document(
* collection="zoo",
* repositoryClass="ZooRepository",
* )
*/
class Zoo
{
/**
* #MongoDB\ReferenceMany(targetDocument="Animal", inversedBy="zoo", strategy="addToSet")
* #var \Doctrine\Common\Collections\ArrayCollection
*/
protected $animals;
/**
* #return mixed
*/
public function getAnimals()
{
return $this->animals->toArray();
}
//Some more code
}
/**
* #MongoDB\Document(
* repositoryClass="AnimalRepository",
* collection="animals"
* )
* #MongoDB\InheritanceType("SINGLE_COLLECTION")
* #MongoDB\DiscriminatorField("discriminator")
* #MongoDB\DiscriminatorMap({
* "animal"="Animal",
* "birds"="Bird",
* "mamals"="Mamals"})
*/
class Animal
{
/**
* #MongoDB\ReferenceMany(targetDocument="Location", mappedBy="animals", simple=true, cascade={"persist"})
*
* #Assert\Count(min="0", max="1")
*/
protected $locations;
}
/**
* #MongoDB\Document(repositoryClass="AnimalRepository")
*/
class Bird extends Animal
{
}
/**
* #MongoDB\Document(repositoryClass="AnimalRepository")
*/
class Mamals extends Animal
{
}
The problem is: when I call getAnimals() from ZooHandler it returns the object of type Animal. What I want is the type of Mamals or Bird.
The strange thing is, if I have an element in Animals->location then I got it right (Mamal/Bird) and if it does not have the element then I got the base type.
If I get the list of all Animals directly from AnimalRepository in AnimalHandler, I am getting the objects of Mamals/Bird accordingly.
EDITED:
Zoo object
> db.zoo.findOne()
{
"_id" : ObjectId("5822bd23085f753b5a5a2408"),
"name" : "Zoo 2",
"active" : true,
"archived" : false,
"animals" : [
DBRef("animals", ObjectId("556cc7adec045b1a0c8b4567"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" }),
DBRef("animals", ObjectId("556cb3b0ec045bbf068b4582"),{ "$db": "tester", "discriminator": "Test\\Bundle\\Core\\Document\\Animal" })
]
}
For sure there are some more properties that are not shown, as they're irrelevant.
If I understand your issue correctly, you need PHP's built-in get_class() or get_called_class() functions.
Note : Objects themselves shouldn't forget which class they belong to, even if they are being returned by a function/method that only "knows" they are returning some instance of the superclass or one of its subclasses. So you should always be able to query which class an instance belongs to, via the get_class($instance) function.
I figured out that if I save an entity as a base class object than it will returns the object of base class and so in the above example if I need to get the desired results, I have to save it appropriately.

PhpStorm: how to tell the var type of an array member?

I use PhpStorm 2016.2.1 IDE. I have a typed array (all members will be of the same, known class) and I'd like the IDE to know the type so I it can help me out with autocomplete/intellisense.
class MyClass{
/**
* #var array
*/
public $userArray;
public addUser($uid){ $this->$userArray[$uid] = new User($uid); }
public processUser($uid){
$oUser = $this->$userArray[$uid];
//since the PHP array can contain anything, the IDE makes
//no assumption about what data type $oUser is. How to let it
//know that it's of type User?
}
}
I have tried...
/**
* #var User
*/
public $oUser = ...;
And also
/**
* #type User
*/
public $oUser = ...;
So far, the only thing I've gotten to work is to use getter functions:
/**
* #return User
*/
function getUser($uid){ return $this->$userArray[$uid]; }
function processUser($uid){
//now the IDE knows the type of $oUser
$oUser = $this->getUser($uid);
}
But slowing down the script with unneeded function calls just to get better IDE support seems like a bad idea.
Any idea how I can let PhpStorm know the type of a variable? Or even better: how to tell it which type an array will contain in the PHPDoc metadata for that array?
For class variables, as you know, you can simply do
#var User
For local variables, it's not officially a supported format, but you must also specify the variable name:
#var User $oUser
Specific to PHPStorm, you'll need to use double asterisks (I think it's the only IDE that needs it, please consider that):
/** #var User $oUser */
See the PHPDoc manual for more info

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.

Is there a PHP equivalent to the C# summary tag?

Is there anyway to give text editors summary information in a tooltip for custom functions/classes etc. in the way that they can do for standard libraries while coding?
Failing this what is the standard way to highlight the purpose, required params etc. for a function/class in PHP.
Check out PHPDocumentor.
An example would be:
/**
* Set the data
*
* #access public
* #param string $field
* #param mixed $value
*/
public function __set($field, $value)
{
$this->_data[$field] = $value;
}
/**
* Get the data
*
* #access public
* #param string $field
* #return mixed
*/
public function __get($field)
{
return isset($this->_data[$field]) ? $this->_data[$field] : NULL;
}
As the comments self-explain, you use #access to show the visibility of the method (if the code being summarized is a method, of course), #paramto show each parameter, and #return to show the type of the data being returned. There are many different tags to document many different aspects of the code.
You can use the PHPDoc standard for letting your IDE give you hints about, for example, a function.
Just before a function declaration you could have:
/**
* This is a DocBlock comment
*/
function foo(){
//....
}
I've used it in Netbeans and can say that it works quite nicely.

Auto-completion for Zend Form Elements

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.

Categories