问题
I am trying to figure out if it is possible to use PHPdoc to define the object properties being returned by a function or a object method.
Say I have the following class:
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
Now, it is easy enough to define input parameters.
/**
* Get Staff Member Details
*
* @param string $id staff id number
*
* @return object
*/
class SomeClass {
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
The question is is there a similar thing for defining properties of the output object (of a stdClass) returned by the method in question. So that another programmer does not have to open this class and manually look into the method to see what the return object is returning?
回答1:
Here it is 4 years later, and there still does not appear to be a way to annotate the properties of a stdClass object as originally described in your question.
Collections had been proposed in PSR-5, but that appears to have been shot down: https://github.com/php-fig/fig-standards/blob/211063eed7f4d9b4514b728d7b1810d9b3379dd1/proposed/phpdoc.md#collections
It seems there are only two options available:
Option 1:
Create a normal class representing your data object and annotate the properties.
class MyData
{
/**
* This is the name attribute.
* @var string
*/
public $name;
/**
* This is the age attribute.
* @var integer
*/
public $age;
}
Option 2:
Create a generic Struct
type class as suggested by Gordon and extend it as your data object, using the @property annotation to define what generic values are possible to access with __get
and __set
.
class Struct
{
/**
* Private internal struct attributes
* @var array
*/
private $attributes = [];
/**
* Set a value
* @param string $key
* @param mixed $value
*/
public function __set($key, $value)
{
$this->attributes[$key] = $value;
}
/**
* Get a value
* @param string $key
* @return mixed
*/
public function __get($key)
{
return isset($this->attributes[$key]) ? $this->attributes[$key] : null;
}
/**
* Check if a key is set
* @param string $key
* @return boolean
*/
public function __isset($key)
{
return isset($this->attributes[$key]) ? true : false;
}
}
/**
* @property string $name
* @property integer $age
*/
class MyData extends Struct
{
// Can optionally add data mutators or utility methods here
}
回答2:
You have only two way to document the structure of the result class.
1.One can describe the structure in a comment text. For example:
class SomeClass
{
/**
* Getting staff detail.
* Result object has following structure:
* <code>
* $type - person type
* $name - person name
* $age - person age
* </code>
* @param string $id staff id number
*
* @return stdClass
*
*/
public function staffDetails($id){
$object = new stdClass();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
2.One can create a data type that will inheritance stdClass and it will have an annotation of a result object. For example:
/**
* @property string $type Person type
* @property string $name Person name
* @property integer $age Person age
*/
class DTO extends stdClass
{}
And use it in your other classes
class SomeClass {
/**
* Getting staff detail.
*
* @param string $id staff id number
*
* @return DTO
*
*/
public function staffDetails($id){
$object = new DTO();
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
In my opinion, this way is better than a description in the text comment because it makes the code more obvious
回答3:
With for example json_decode
it's harder to use own classes instead of stdClass
, but in my case I just created dummy file with class definitions, which really isn't loaded and I'm adding own classes as @return
(works for intelephense on vscode).
PHPdocObjects.php
/**
* class only for PHPdoc (do not include)
*/
class Member {
/** @var string */
public $type;
/** @var string */
public $name;
/** @var string */
public $age;
}
/**
* Other format
*
* @property string $type;
* @property string $name;
* @property string $age;
*/
class MemberAlt {}
SomeClass.php
/**
* Get Staff Member Details
*
* @param string $id staff id number
*
* @return Member I'm in fact stdClass
*/
class SomeClass {
public function staffDetails($id){
$object = json_decode('{"type":"person","name":"dave","age":"46"}');
return $object;
}
}
回答4:
If you are using PHP 7, you can define anonymous class.
class SomeClass {
public function staffDetails($id){
$object = (new class() extends stdClass {
public /** @var string */ $type;
public /** @var string */ $name;
public /** @var int */ $age;
});
$object->type = "person";
$object->name = "dave";
$object->age = "46";
return $object;
}
}
It is working for my IDE (tested in NetBeans)
来源:https://stackoverflow.com/questions/12435623/phpdoc-defining-object-properties-for-an-object-of-stdclass