在 PHPDoc 中记录数组选项的最佳方法?

Posted

技术标签:

【中文标题】在 PHPDoc 中记录数组选项的最佳方法?【英文标题】:Best way to document Array options in PHPDoc? 【发布时间】:2013-03-03 02:05:33 【问题描述】:

我正在努力编写可读且易于理解的文档来描述传递给函数的数组选项的多树结构。

这是一个示例数组结构。

$arr = [
   'fields' => [
       'title' => [
           'name'     => 'Document.title',
           'format'   => 'string',
           'readonly' => true
       ]
   ]
];

上面的数组有很多可能的选项,但它被用作理解该结构的函数的参数。

function doSomething(array $arr)  ... 

我想在 phpDoc 中记录数组的结构,但我不确定正确的方法是什么。

这是我现在拥有的。

/**
 * Holds configuration settings for each field in a model.
 * Defining the field options
 *
 * array['fields'] array Defines the feilds to be shown by scaffolding.
 * array['fields'][fieldName] array Defines the options for a field, or just enables the field if array is not applied.
 * array['fields'][fieldName]['name'] string Overrides the field name (default is the array key)
 * array['fields'][fieldName]['model'] string (optional) Overrides the model if the field is a belongsTo assoicated value.
 * array['fields'][fieldName]['width'] string Defines the width of the field for paginate views. Examples are "100px" or "auto"
 * array['fields'][fieldName]['align'] string Alignment types for paginate views (left, right, center)
 * array['fields'][fieldName]['format'] string Formatting options for paginate fields. Options include ('currency','nice','niceShort','timeAgoInWords' or a valid Date() format)
 * array['fields'][fieldName]['title'] string Changes the field name shown in views.
 * array['fields'][fieldName]['desc'] string The description shown in edit/create views.
 * array['fields'][fieldName]['readonly'] boolean True prevents users from changing the value in edit/create forms.
 * array['fields'][fieldName]['type'] string Defines the input type used by the Form helper (example 'password')
 * array['fields'][fieldName]['options'] array Defines a list of string options for drop down lists.
 * array['fields'][fieldName]['editor'] boolean If set to True will show a WYSIWYG editor for this field.
 * array['fields'][fieldName]['default'] string The default value for create forms.
 *
 * @param array $arr (See above)
 * @return Object A new editor object.
 **/

我的问题是,当生成 html 文档时,它的格式不是很好。另外,我不确定上面是否清楚地解释了数组结构。

有其他方法吗?

【问题讨论】:

看看这个公认的答案:***.com/a/2725073/1983684 @ChrisL 谢谢,我认为这也是我应该做的。 功能请求请见github.com/phpDocumentor/phpDocumentor2/issues/650 如果您需要数据结构如此具体,那么数组可能不是正确的数据类型?您是否考虑过使用 DTO 类(基本上只是一个具有一堆属性的类)? 你可能想看看Phan union types。 【参考方案1】:

这就是我的做法:

/**
 * Class constructor.
 *
 * @param array $params Array containing the necessary params.
 *    $params = [
 *      'hostname'     => (string) DB hostname. Required.
 *      'databaseName' => (string) DB name. Required.
 *      'username'     => (string) DB username. Required.
 *      'password'     => (string) DB password. Required.
 *      'port'         => (int) DB port. Default: 1433.
 *      'sublevel'     => [
 *          'key' => (\stdClass) Value description.
 *      ]
 *    ]
 */
 public function __construct(array $params)

认为它很干净,很容易理解$params应该是什么。

【讨论】:

您将如何记录示例中的“子级别”键?它没有自己的 cmets。仍然希望将其记录为我自己的代码的可选。 @JM-AGMS 我可能会做这样的事情:pastebin.com/0ebYpfpQ 我不认为在评论中包含评论看起来真的很好,但它可以让它从其他参数键中脱颖而出。 【参考方案2】:

我写了一个plugin for phpstorm,它允许像这样指定键:

(基本上只是@siannone 格式的稍微严格的版本)

/**
 * @param array $arr = [
 *     'fields' => [ // Defines the feilds to be shown by scaffolding
 *         $anyKey => [
 *             'name' => 'sale', // Overrides the field name (default is the array key)
 *             'model' => 'customer', // (optional) Overrides the model if the field is a belongsTo associated value.
 *             'width' => '100px', // Defines the width of the field for paginate views. Examples are "100px" or "auto"
 *             'align' => 'center', // Alignment types for paginate views (left, right, center)
 *             'format' => 'nice', // Formatting options for paginate fields. Options include ('currency','nice','niceShort','timeAgoInWords' or a valid Date() format)
 *             'title' => 'Sale', // Changes the field name shown in views.
 *             'desc' => 'A deal another person that results in money', // The description shown in edit/create views.
 *             'readonly' => false, // True prevents users from changing the value in edit/create forms.
 *             'type' => 'password', // Defines the input type used by the Form helper
 *             'options' => ['option1', 'option2'], // Defines a list of string options for drop down lists.
 *             'editor' => false, // If set to True will show a WYSIWYG editor for this field.
 *             'default' => '', // The default value for create forms.
 *         ],
 *     ],
 * ]
 */
public static function processForm($arr)

    $fieldName = 'sale';
    $arr['fields'][$fieldName][''];

它也允许指定@return 键:

/**
 * @return array [
 *     'success' => true,
 *     'formObject' => new Form,
 *     'errors' => [],
 * ]
 */
public static function processForm($arr);

【讨论】:

非常好,我会在评论'name' => 'sale', // (string) Overrides... 中添加类型提示。 vscode 有类似的东西吗? 不,除非您愿意将扩展程序从 java 移植到 typescript。已经有related issue in intelephense,你可以试试顶一下。 这与 vimeo/psalm 兼容吗? 是的,它should understand psalm php doc 格式,包括@template。虽然如果你发现一些插件中无法使用的 psalm 功能,请随时file an issue,我很乐意更新它 @Alex 好消息,一位好人赞助了vscode version 的开发。希望在接下来的几周内实现基本功能。【参考方案3】:

只需添加一些表格就可以使它看起来很好并且易于理解

/**
 * Holds configuration settings for each field in a model.
 * Defining the field options
 *
 * array['fields']              array Defines the fields to be shown by scaffolding.
 *          [fieldName]         array Defines the options for a field, or just enables the field if array is not applied.
 *              ['name']        string Overrides the field name (default is the array key)
 *              ['model']       string (optional) Overrides the model if the field is a belongsTo associated value.
 *              ['width']       string Defines the width of the field for paginate views. Examples are "100px" or "auto"
 *              ['align']       string Alignment types for paginate views (left, right, center)
 *              ['format']      string Formatting options for paginate fields. Options include ('currency','nice','niceShort','timeAgoInWords' or a valid Date() format)
 *              ['title']       string Changes the field name shown in views.
 *              ['desc']        string The description shown in edit/create views.
 *              ['readonly']    boolean True prevents users from changing the value in edit/create forms.
 *              ['type']        string Defines the input type used by the Form helper (example 'password')
 *              ['options']     array Defines a list of string options for drop down lists.
 *              ['editor']      boolean If set to True will show a WYSIWYG editor for this field.
 *              ['default']     string The default value for create forms.
 *
 * @param array $arr (See above)
 * @return Object A new editor object.
 **/

嵌套列表方法:

<ul>
    <li>
        array['fields'] array Defines the fields to be shown by scaffolding.
        <ul>
            <li>
                [fieldName]             array Defines the options for a field, or just enables the field if array is not applied.
                <ul>
                    <li> ['name']       <i><u>string</u></i> Overrides the field name (default is the array key) </li>
                    <li> ['model']      <i><u>string</u></i> (optional) Overrides the model if the field is a belongsTo associated value.</li>
                    <li> ['width']      <i><u>string</u></i> Defines the width of the field for paginate views. Examples are "100px" or "auto"</li>
                    <li> ['align']      <i><u>string</u></i> Alignment types for paginate views (left, right, center)</li>
                    <li> ['format']     <i><u>string</u></i> Formatting options for paginate fields. Options include ('currency','nice','niceShort','timeAgoInWords' or a valid Date() format)</li>
                    <li> ['title']      <i><u>string</u></i> Changes the field name shown in views.</li>
                    <li> ['desc']       <i><u>string</u></i> The description shown in edit/create views.</li>
                    <li> ['readonly']   <i><u>boolean</u></i> True prevents users from changing the value in edit/create forms.</li>
                    <li> ['type']       <i><u>string</u></i> Defines the input type used by the Form helper (example 'password')</li>
                    <li> ['options']    <i><u>array</u></i> Defines a list of string options for drop down lists.</li>
                    <li> ['editor']     <i><u>boolean</u></i> If set to True will show a WYSIWYG editor for this field.</li>
                    <li> ['default']    <i><u>string</u></i> The default value for create forms.</li>
                </ul>
            </li>
        </ul>
    </li>
 </ul>

结果:

array['fields'] array 定义要通过脚手架显示的字段。 [fieldName] 数组 定义字段的选项,或者如果未应用数组,则仅启用该字段。 ['name'] string 覆盖字段名(默认为数组键) ['model'] string(可选)如果字段是 belongsTo 关联值,则覆盖模型。 ['width'] string 定义分页视图的字段宽度。例如“100px”或“auto” ['align'] string 分页视图的对齐类型(左、右、中) ['format'] string 分页字段的格式选项。选项包括('currency','nice','niceShort','timeAgoInWords' 或有效的 Date() 格式) ['title'] string 更改视图中显示的字段名称。 ['desc'] string 编辑/创建视图中显示的描述。 ['readonly'] boolean True 可防止用户更改编辑/创建表单中的值。 ['type'] string 定义表单助手使用的输入类型(例如'password') ['options'] array 定义下拉列表的字符串选项列表。 ['editor'] boolean 如果设置为 True,将为此字段显示 WYSIWYG 编辑器。 ['default'] string 创建表单的默认值。

如果你想让它看起来很漂亮,用一点 Css 就会创造奇迹! xd

【讨论】:

文档转换为 HTML 时,缩进被移除。 :( 它们不应该出现在 html 的源代码中。如果您打算在 html 渲染中显示它们,那么我建议您使用表格,甚至是嵌套的未排序列表,可能性是无限的,不知道您想要一个 html 输出 哇,谢谢 :) 我认为混合使用 样本就可以了。 是的,如果你添加任何 CSS,它会让它看起来非常专业!祝你的项目好运:D【参考方案4】:

在广泛接受的密钥类型文档格式中,我想在这里提几个流行的:

Psalm/PHPStan/phan格式

/** @param arrayfoo: string, bar: int $args */

作为奖励,也可以用他们的工具用于static code analysis

Wordpress 格式

/**
 * @param array $args 
 *     Optional. An array of arguments.
 *
 *     @type type $key Description. Default 'value'. Accepts 'value', 'value'.
 *                     (aligned with Description, if wraps to a new line)
 *     @type type $key Description.
 * 
 */

两者都被deep-assoc-completion插件支持

【讨论】:

【参考方案5】:

你可以使用对象而不是数组吗?这将使文档变得容易。

class Field 

    /**
     * The name of the thing.
     * @var string
     */
    protected $name;

    protected $model;
    protected $width;
    //...

    public function getName() ...
    public function setName() ...
    //...


class FieldList implements SomeKindOfIterator 

    /**
     * Some fields.
     * @var Field[]
     */
    protected $fields = array();

    /**
     * ...
     */
    public function push(Field $field) 
         $this->fields[] = $field;
    

    //...

然后你可以在需要类的地方使用类型提示。

/**
 * Do something.
 * @param FieldList $field_list The field.
 */
function doSomething(FieldList $field_list) ...

【讨论】:

必须 +1 并添加,请考虑移动到带有声明的公共变量的预定义公共类作为关联数组的替代方案。对于非常大的集合,它不仅速度更快并且使用更少的内存,您还可以在类和属性上使用 phpdoc cmets 和标签来生成一些不错的文档。 Field[] 是正确的表示法,而不是 array[Field] 也是 +1,因为它允许 IDE 理解它以进行自动完成、警告等。这里的其他答案不知道。【参考方案6】:

Markdown Syntax for Object Notation (MSON) 可能是更好的选择。

例子

/**
 * @param array $config
 *   + app (string, required) - app directory name
 *   + view (string, required) - view directory name
 *   + type (enum[string]) - site type
 *     + pc - PC version
 *     + wap - mobile version
 *     + other - other, default value
 *   + table_prefix (string) - database table prefix
 */

【讨论】:

这与 VS Code 兼容(可能特定于 PHP Intelephense?)【参考方案7】:

我更喜欢这个:

 * @param array $doc
 *          'type'=>Doc::MY_DOC_TYPE,
 *          'created'=>$now,
 *          'modified'=>$now

我只是将代码从它初始化的地方粘贴进去,快速而简单。

【讨论】:

【参考方案8】:

PHP 中的数组实际上更像是匿名结构。

对于任意数据结构,有许多模式验证器,但不幸的是,它在类型提示中并未得到广泛支持。也许一些常见的方案有插件?问题是事情只在一个或几个地方工作。您可能会为您的 IDE 找到正确的东西,但运行静态分析可能会陷入困境。

需要注意将事物分开,以便在可能的情况下,其他不支持方案的工具(例如通过插件)将直接忽略它。

PHPDoc 往往在所有地方都受到支持,但也非常有限。

经常有提案,但没有真正好的标准。大多数解决方案都是非标准的、没有得到广泛支持的、有限制的部分破解或纯粹肤浅的(文档)。

在特定的地方有特定的实现,但没有广泛和专用于 PHP 本身。尽管您可以在 PHP IDE 中创建自己的架构,但往往缺乏体面的代码桥,即使是那些名称中有 PHP 的架构。

您应该单独定义字段结构。您的外部数据结构是伪代码@key fields field[],而不是表示为多维数组。从概念上讲,您可以做到以下几点:

@start struct custom
@key \stdClass *
@end struct

@start struct fields
@key string hostname
@key string databaseName
@key string password
@key int port=1433
@key custom|undefined sublevel
@end struct

@start struct connection
@key fields fields
@end struct

或者从 C 中窃取然后发明一种语言...

struct connection 
    struct fields 
        string hostname;
        string databaseName;
        string password;
        int port = 1433;
        custom optional sublevel 
            stdClass *;
        ;
    ;
;

您可以创建基于结构的模式以允许平面和嵌套。嵌套应该是默认设置,事物只应被定义为可访问,以便重用。

一种不寻常的方法是使用对象。这不一定需要使用诸如数组访问之类的接口。在 PHP 中,对象为属性包装了一个数组。可以将数组转换为对象(无需实现,只有属性)并返回。

如果您将对象用作关联数组($array[$key] 与 $object->$key),那么您可以制作虚拟对象以至少欺骗 IDE...

final class PersonStruct 
    /** @var int */
    public $x;

    /** @var int $y */

    public int $z;

这三个选项中可能起作用也可能不起作用取决于所使用的工具。

然后你就可以撒谎了……

/** @var PersonStruct $ps */
$ps = (object)['x' => 0, 'y' => 1, 'z' => 2];

/**
 * @param PersonStruct $ps
 * @return PersonStruct
 */
function f(object $ps):object 
    return $ps;


/**
 * @param PersonStruct $ps
 * @return PersonStruct
 */
function f(stdClass $ps):stdClass 
    return $ps;

问题在于它意味着将数组转换为对象。这既有性能影响,也有通过值传递到引用传递的变化。哪个更快是有争议的。理论上数组应该更快,尽管对象在默认情况下具有引用的好处,并且与 PHP 不同,JSON 将对象与数组分开可以更好地工作。

对象也不支持在类型提示方面可能设置得不好的属性,即使对象中的属性只是一个 PHP 数组(使用-&gt;key 而不是[key])。还有可能发生其他奇怪的事情。

如果性能是一个真正的问题,您可以将 PHP 变成一种编译语言。以同样的方式,您可以扩展接口以使对象可编译,您可以对可能使用 OOP 和自动完成做所有事情的地方做同样的事情,但然后可以通过指定它包装的属性来执行内联类的等效操作,然后使用反射几乎可以用匹配方法的内容替换使用,需要一些额外的位(标记要内联或转换为程序的内容、要包装的单个属性或多个属性等)。

这个概念类似于装箱和拆箱。如果您真的对 SA 支持和对 IDE(自动完成、检查等)、分析器、工具等的广泛支持感到疯狂,那么这可能是唯一的方法。

【讨论】:

【参考方案9】:

由于这纯粹是显示而不是指令,并且应该在文档中保留空格格式,我倾向于使用缩进而不是字符墙来提高可读性:

 * array['fields'] array Defines the feilds to be shown by scaffolding.
 *           [fieldName] array Defines the options for a field, or just enables
 *                             the field if array is not applied.
 *                 ['name'] string Overrides the field name (default is the
 *                                  array key)
 *                 ['model'] string (optional) Overrides the model if the field is
 *                                  a belongsTo assoicated value.
 *                 ['width'] string Defines the width of the field for paginate
 *                                  views.
 *                                  Examples are "100px" or "auto"
 *                 ['align'] string Alignment types for paginate views (left, 
 *                                 right, center)
 *                 ['format'] string Formatting options for paginate fields.
 *                                   Options include 'currency', 'nice',
 *                                  'niceShort', 'timeAgoInWords' or a valid 
 *                                  Date() format)
 *                 ['title'] string Changes the field name shown in views.
 *                 ['desc'] string The description shown in edit/create views.
 *                 ['readonly'] boolean True prevents users from changing the
 *                                 value in edit/create forms.
 *                 ['type'] string Defines the input type used by the Form helper
 *                                  (example 'password')
 *                 ['options'] array Defines a list of string options for drop-
 *                                  down lists.
 *                 ['editor'] boolean If set to True will show a WYSIWYG editor
 *                                  for this field.
 *                 ['default'] string The default value for create forms.

虽然使用带有缩进的实际 PHP 数组定义更加简洁

【讨论】:

以上是关于在 PHPDoc 中记录数组选项的最佳方法?的主要内容,如果未能解决你的问题,请参考以下文章

phpDoc 有没有办法将对象数组记录为参数?

用于可变长度参数数组的 PHPDoc

PHPDoc:用可变数量的参数记录函数

什么是 PHPDoc Eclipse 多类型:以及如何使用它?

在 PHP 中删除数组项的最佳方法是啥?

如何使用带有重载方法的phpDoc?