Phpdoc - определение переменных возвращаемого объекта для метода

Я искал это некоторое время, и либо я не использую правильные условия поиска, либо что-то не хватает.

Я пытаюсь выяснить, можно ли использовать PHPdoc для определения переменных, возвращаемых объектом.

Скажем, у меня есть следующий класс:

class SomeClass {
    public function staffDetails($id){

        $object = new stdClass();
        $object->type = "person";
        $object->name = "dave";
        $object->age = "46";        

        return $object;
    }
}

Теперь достаточно легко определить входные параметры.

 /**
 * 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;
    }
}

Вопрос в том, есть ли аналогичная вещь для определения выходных переменных объекта, возвращаемого рассматриваемым методом, чтобы другой программист не должен был открывать этот класс и вручную заглядывать в метод, чтобы увидеть, что возвращается возвращаемый объект

Ответ 1

Здесь 4 года спустя, и, похоже, не существует способа аннотировать свойства объекта stdClass, как это было описано в вашем вопросе.

Коллекции были предложены в PSR-5, но, похоже, они были сбиты: https://github.com/php-fig/fig-standards/blob/211063eed7f4d9b4514b728d7b1810d9b3379dd1/proposed/phpdoc.md#collections

Кажется, доступно только два варианта:

Вариант 1:

Создайте нормальный класс, представляющий ваш объект данных, и аннотируйте его.

class MyData
{
    /**
     * This is the name attribute.
     * @var string
     */
    public $name;

    /**
     * This is the age attribute.
     * @var integer
     */
    public $age;
}

Вариант 2:

Создайте общий тип типа Struct, предложенный Gordon и расширьте его как свой объект данных, используя @property аннотация, чтобы определить, какие общие значения доступны для доступа с помощью __get и __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

У вас есть только два способа документировать структуру класса результата.

1. Один может описать структуру в тексте комментария. Например:

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. Один может создать тип данных, который будет наследовать stdClass, и он будет иметь аннотацию объекта результата. Например:

/**
 * @property string $type Person type
 * @property string $name Person name
 * @property integer $age Person age
 */
class DTO extends stdClass
{}

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;
    }
}

На мой взгляд, этот способ лучше, чем описание в текстовом комментарии, потому что это делает код более очевидным

Ответ 3

Например, с помощью json_decode сложнее использовать собственные классы вместо stdClass, но в моем случае я просто создал фиктивный файл с определениями классов, который действительно не загружен, и я добавляю собственные классы как @return (работает для intelephense в 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;
    }
}