Best way to document Array options in PHPDoc?

89,994

Solution 1

Just adding some tabulation will make it look good and easy to understand

/**
 * 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.
 **/

A nested list approach:

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

Result:

  • 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.

If you want it to look fancy, with a bit of Css it will make wonders! xd

Solution 2

This is how I do it instead:

/**
 * 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){}

Think it's quite clean and easy to understand what $params should be.

Solution 3

I wrote a plugin for phpstorm that allows specifying keys like this:

(basically just a slightly more formalized version of @siannone's format)

/**
 * @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][''];
}

enter image description here

It allows to specify @return keys as well:

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

enter image description here

Solution 4

Among widely accepted key type documenting formats, I'd like to mention few popular ones here:

Psalm/PHPStan/phan format

/** @param array{foo: string, bar: int} $args */

as a bonus, can also be used for static code analysis with their tools

Wordpress format

/**
 * @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.
 * }
 */

and both are supported by deep-assoc-completion plugin

Solution 5

Can you use objects instead of arrays? That would make documentation easy.

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

    //...
}

Then you can use a type hint where the class is required.

/**
 * Do something.
 * @param FieldList $field_list The field.
 */
function doSomething(FieldList $field_list) {...}
Share:
89,994

Related videos on Youtube

Reactgular
Author by

Reactgular

I'm a Front-End Developer in Toronto, Canada with 10+ years experience in software development. I have a passion for helping people on Stack Overflow, and I like to build websites in my spare time. Checkout a live demo of my Angular bookmark manager and you can also download the source code.

Updated on July 08, 2022

Comments

  • Reactgular
    Reactgular almost 2 years

    I'm struggling to write readable and easy to understand documentation that describes the multi-tree structure for Array options that are passed to a function.

    Here is an example array structure.

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

    There are many possible options for the above array, but this is used as a parameter to a function that understands that structure.

    function doSomething(array $arr) { ... }
    

    I'd like to document how the array should be structured in PHPDoc, but I'm not sure what the correct approach is.

    Here is what I have now.

    /**
     * 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.
     **/
    

    My problem is that when the HTML document is generated, it's not formatted very nicely. Additionally, I'm not sure the above is clearly explains the array structure.

    Is there an alternative approach?

    • Chris L
      Chris L over 11 years
      Take a look at this accepted answer: stackoverflow.com/a/2725073/1983684
    • Reactgular
      Reactgular over 11 years
      @ChrisL Thanks, I think that is what I should do as well.
    • Ben Creasy
      Ben Creasy over 7 years
    • GordonM
      GordonM about 6 years
      If you need the structure of your data to be so specific then maybe arrays aren't the right datatype? Have you considered using DTO classes (basically just a class with a bunch of properties) instead?
    • MAChitgarha
      MAChitgarha about 5 years
      You might want to take a look at Phan union types.
  • Reactgular
    Reactgular over 11 years
    The indentation is removed when the documentation is converted to HTML. :(
  • aleation
    aleation over 11 years
    They shouldn't be gone in the source code of the html. If you intend to show them on the html rendering then I suggest you to use a table maybe, or even a nested Unsorted List, the possibilities are infinite, didn't know you wanted an html output
  • Reactgular
    Reactgular over 11 years
    wow, thanks :) I think that with a mix of <code> samples will do the trick.
  • aleation
    aleation over 11 years
    Yes from there on if you add any CSS it will make it look very pro! Good luck with your project :D
  • Joey T
    Joey T over 9 years
    Must +1 this and add, please do consider moving to a predefined public class with declared public variables as an alternative to an associative array. Not only is it faster and uses less memory with very large sets, you can use phpdoc comments and tags on the class and properties to generate some nice documentation.
  • NDM
    NDM over 7 years
    Field[] is the correct notation instead of array[Field]
  • Barry Staes
    Barry Staes over 7 years
    Also +1 because it allows the IDE to understand it for autocompletion, warnings, etc. Other answers here dont afaik.
  • Alex
    Alex over 5 years
    Very nice, I would add type hinting in the comment 'name' => 'sale', // (string) Overrides.... Something similar for vscode?
  • Klesun
    Klesun over 5 years
    Nope, unless you are willing to port an extension from java to typescript. There is already a related issue in intelephense, you could try bumping it.
  • JM-AGMS
    JM-AGMS over 4 years
    How would you document the 'sublevel' key in your example? It does not have its own comments. Would still like to document it as optional for my own code.
  • siannone
    siannone over 4 years
    @JM-AGMS I would probably do something like this: pastebin.com/0ebYpfpQ I don't think it looks really nice having a comment inside a comment but it allows it stand out from the other parameter keys.
  • Henk Poley
    Henk Poley over 4 years
    Is this compatible with vimeo/psalm ?
  • Klesun
    Klesun over 4 years
    Yes, it should understand psalm php doc formats, including @template. Though if you find some psalm feature that does not work in plugin, feel free to file an issue, I'll gladly update it
  • Klesun
    Klesun about 4 years
    @Alex good news, one good man sponsored the start of development of the vscode version. Hopefully will implement base functionality in following few weeks.
  • Alex
    Alex about 4 years
    @ArturKlesun thanks for the update, I will follow the project, maybe in the future I will also be able to help
  • kmoney12
    kmoney12 over 3 years
    Great plugin. Is it possible to autofill the entire default $config array instead of one key at a time? So when calling processForm, it recommends processForm(['fields'=>['anykey'=>[...]]])
  • Klesun
    Klesun over 3 years
    If I understand correctly, no, there is no such feature currently. You can try to describe/discuss it in a more detail by filing an issue, if it's something that would improve the coding experience, I'll add it.
  • thelr
    thelr almost 3 years
    This is compatible with VS Code (maybe specific to PHP Intelephense?)