Как использовать phpDoc с перегруженными методами?

Допустим, у меня есть класс PHP с именем Color, его конструктор принимает различные параметры.

// hex color
$myColor = new Color('#FF008C');

// rgb channels
$myColor = new Color(253,15,82);

// array of rgb channels
$myColor = new Color(array(253,15,82));

// X11 color name
$myColor = new Color('lightGreen');

Как мне использовать phpDoc для создания документации API для конструктора и других подобных методов?

Как использовать phpDoc с перегруженными методами?

class Color {

    /**
     * Constructor
     * what should be here?
     */
    public function __construct() {
        /* CODE */
    }

}

person Tom Pažourek    schedule 28.08.2009    source источник


Ответы (4)


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

Я бы просто перечислил разрешенные аргументы как параметры.

/**
 * @param mixed $arg1 ... description
 * @param mixed $arg2 ... description
 * @param mixed $arg3 ... description
 */
 public function __construct() {}

Или я бы просто дал объяснение с некоторыми примерами.

/**
 * Explanation of different expected argument combinations.
 */
public function __construct() {}

Другой альтернативой, поскольку только один из примеров имеет более одного аргумента, было бы просто определить аргументы в сигнатуре метода, сделав последние 2 необязательными. Как это:

/**
 * @param mixed $arg1 ...
 * @param int $arg2 ...
 * @param int $arg3 ...
 */
public function __construct($arg1, $arg2 = null, $arg3 = null) {}
person Steven Surowiec    schedule 28.08.2009
comment
Я буду использовать второе решение, один параметр с описанием (от одного до трех параметров и различных форматов) и несколько тегов @see для примеров. - person Tom Pažourek; 29.08.2009
comment
Это старо, но просто чтобы предложить альтернативу для справки — вы также можете просто сказать @param mixed $args ... Variable number of arguments representing blah blah - person Brian Lacy; 28.09.2011

Это просто моя точка зрения, но в первую очередь у вас не должно быть нескольких конструкторов - ваш конструктор будет полон лестниц if/else, что на самом деле не очень хорошая идея, особенно для чего-то легкого, такого как представление Цвет.

Я настоятельно рекомендую вам попробовать что-то вроде этого:

class Color
{
    protected function __construct($r, $g, $b)
    { ... }

    public static function fromHex($hex) {
        return new Color(...);
    }

    public static function fromRGB($r, $g, $b) { ... }

    public static function fromArray(array $rgb) { ... }

    ...
}

Теперь в потребительском коде вместо несколько загадочных и неоднозначных вызовов конструктора, подобных этим:

$a = new Color(0,0,0);
$b = new Color('#000000');

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

$a = Color::fromRGB(0,0,0);
$b = Color::fromHex('#000000');

Это, вероятно, имеет больше смысла для тех, кто читает потребительский код, он устраняет логику, необходимую для работы неоднозначного конструктора, и в качестве бонуса (если вы используете IDE, такую ​​​​как PhpStorm), вы можете пройти все свои проверки. Если вы используете генератор документации, это также гарантирует, что все параметры задокументированы по отдельности, а не объединены в словесное описание.

Обратите внимание, что я объявил конструктор protected - это личное предпочтение, но если я собираюсь иметь несколько статических фабричных методов, я предпочитаю видеть те, которые постоянно используются в потребительском коде, а не иногда видеть Color::fromRGB(...), а иногда new Color(...).

person mindplay.dk    schedule 28.06.2013
comment
Ты прав. Решение со статическими фабричными методами приводит к гораздо более ясному коду. - person Tom Pažourek; 10.08.2013
comment
Этот ответ заслуживает гораздо большей похвалы, поскольку он продвигает лучшие методы программирования. - person kwah; 09.09.2013
comment
Тем не менее, я понимаю, что это не дает строгого ответа на исходный (довольно старый) вопрос. Лично я вижу это как объяснить, как использовать отвертку, чтобы забить гвоздь, говоря, почему бы просто не использовать молоток?. - person kwah; 09.09.2013
comment
Я говорю, что отвертка — неподходящий инструмент для забивания гвоздей — теперь, даже если это не тот ответ, которого вы хотели, это правильный ответ, если только вы не садистски одержимы сгибанием гвоздей и забиванием себя пальцами. - person mindplay.dk; 09.09.2013

Я думаю, что лучше использовать аннотацию @method для класса/интерфейса, которая объявляет методы перегрузки. Этот вопрос меня тоже интересует.

 /**
  * @method void setValue(int $value)
  * @method void setValue(string $value)
  * @method void setValue(string $value, int $startFrom)
  */
 class Example
 {
     public function setValue($arg1, $arg2)
     {
        // ...
     }
 }

См. http://phpdoc.org/docs/latest/references/phpdoc/tags/method.html

person Roman Shamritskiy    schedule 27.02.2014
comment
Я лично работаю над одним и тем же и предпочитаю использовать ваш подход. Это ясно, полезно и интеллектуально работает очень хорошо. Я использую метод __Call, чтобы сопоставить правильные параметры и вызвать частную функцию или void для завершения моей логики. Однако разработчик php должен позаботиться об улучшении перегрузки, чтобы обеспечить более надежный способ использования этого типа реализации, который действительно полезен. В .NET (откуда я родом) это обычная практика перегрузки метода/функции, и это очень мощная штука. - person makemoney2010; 05.08.2016
comment
Я попробовал это недавно, и моей среде IDE (PhpStorm/IntelliJ IDEA) это не понравилось; он показал предупреждение о повторяющихся объявлениях, не смог правильно выделить синтаксис и позже отказался предлагать повторяющиеся методы. - person Christian; 22.07.2021

Я не знаю элегантного способа сделать это с помощью phpDoc. Форматирование комментариев/API phpDoc основано на формате Javadoc. В Javadoc нет набора функций для поддержки этого, потому что в java, если вы хотите, чтобы метод имел переменное количество аргументов, вы повторно объявляете прототип метода для каждого варианта.

public double foo() {
}

public double foo(double my_param) {        
}

Итак, мое предпочтение производительности - сделать что-то вроде

/**
 * My General description
 * 
 * Here explain what each argument combination can do
 * @param mixed $arg1 can be array, string, hex as string, or int 
 * @param int $arg2 if arg1 is int, then this is etc, otherwise optional 
 * @param int $arg3 if ar1 is int, then this is etc, otherwise optional
 */

но это может не очень хорошо сочетаться с различными инструментами автодокументации.

Согласно Хойлу способ сделать это можно найти в phpDoc. сайт.

person Alan Storm    schedule 28.08.2009