How to make objects from arrays in PHP with hints?

When you are tired of remembering array keys and want to use the tips of your favorite code editor, PHPDoc comes to the rescue and a little ingenuity.

Recently, I got very close to TypeScript and learned the beauty of strong typing. How nice it is when the code editor tells you what fields are in the object and what you can do with them!

What is the problem?

I work with Bitrix CMS and I have to deal with arrays of various shapes and contents, memorize all the keys or look for them in the documentation. It takes precious time.

Solution:

The first thing that comes to mind is to use PHPDoc, but here comes the problem:

/**
 * int[]
 * array
 * array<string>
 */

You cannot write a multidimensional array in a way that the code editor prompts. All options I found do not work in VSCode and PhpStorm.

After some googling, I found an option that only worked in VSCode.

/**
 * @var array $arr $arr
 * @var array $arr['fields']
 * @var array $arr['fields']['fieldName']
 * @var array $arr['fields']['fieldName']['name']
 * @var array $arr['fields']['fieldName']['model']
 * @var array $arr['fields'][fieldName]['width']
 * @var array $arr['fields'][fieldName]['align']
 * @var array $arr['fields'][fieldName]['format']
 * @var array $arr['fields'][fieldName]['title']
 * @var array $arr['fields'][fieldName]['desc']
 * @var array $arr['fields'][fieldName]['readonly']
 * @var array $arr['fields'][fieldName]['type']
 * @var array $arr['fields'][fieldName]['options']
 * @var array $arr['fields'][fieldName]['editor']
 * @var array $arr['fields'][fieldName]['default']
 **/
$arr = [
    'fields' => [
        'fieldName' => []
    ]
];

In this case, the environment suggests which key you can choose:

There is a plugin for PhpStorm deep-assoc-completionit requires an array declaration in a specific format:

/**
 * @var array $arr = [
 *     'fields' => [ // Defines the feilds to be shown by scaffolding
 *         $anyKey => [
 *             'name' => 'sale', // Overrides the field name (default is the array key)
 *             'model' => string, // (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.
 *         ],
 *     ],
 * ]
 */
$arr=[
    'fields' => [
        '0' => [
            'model' => 2
        ]
    ]
];

In this case, the environment suggests the keys:

One problem remains, if we want such hints, we need to make a similar description in every file where our array is. This is especially true for Bitrix.

My decision:

The code editor indexes objects well, so why don’t we cast the array to the object and describe it?! But how to describe an object without a class, because PHPDoc is also a helper in this?

We can create a class in which we describe all the fields we need. And now our editor is already telling us.

Okay, what next? We can describe multidimensional arrays in the same way as we describe interfaces in TS. Or we move the nested array into a separate class:

Or we write in the constructor of the current class:

Please note that we make the constructor private so that it does not interfere with us, and we must create a description for the nested field. But PHPStorm will not understand it.

Summary

The option is certainly steamy, but people writing in TS have been doing this for a long time. If there’s a better option, I’d be happy to consider it. And most importantly, the point is not that this should always be done, but that if there are no other options (limited in time, etc., etc.), then this technology can be applied.

Similar Posts

Leave a Reply

Your email address will not be published. Required fields are marked *