skip to Main Content

I have some template files that have default arguments defined at the top of each file. I can’t get type hinting for these values to work correctly; it just says there is no reference. I am including the WordPress core files in Intelephense, so it understands what a WP_Post is, I just can’t get it to understanding typing on a multidimensional aray.

I found this GitHub issue which discusses a similar problem, and includes some suggestions on things to try. No matter which method I used, all I can get it to respond with for $args["post"] is `No references found for ‘post’".

Eventually, I found this WordPress forums thread discussing a similar issue, and links to this WordPress core file which includes the "WordPress-y" way to do document multidimensional arrays, but even this still results in the same message.

That’s how I’ve gotten to this point, but this doesn’t seem to be working correctly either, because the reference pop-up looks quite odd (screenshot below), and doesn’t seem to do anything for type hinting.

<?php
/**
 * @var array $args {
 *     @type WP_Post $post,
 *     @type string  $class,
 *     @type bool    $light,
 *     @type string  $title,
 *     @type bool    $meta,
 *     @type string  $content,
 * }
 */
$args = array_merge([
    "post"    => null,
    "class"   => "",
    "light"   => false,
    "title"   => "",
    "meta"    => null,
    "content" => "",
], $args);

/**
 * Retrieve values based on `$post` if set
 */
if ($args["post"] instanceof WP_Post) {
    /**
     * Set title
     */
    if ($args["title"] === "") {
        $args["title"] = apply_filters("the_title", $args["post"]->post_title, $args["post"]->ID);
    }

    /**
     * Set meta based on post type
     */
    if ($args["meta"] === null && $args["post"]->post_type === "post") {
        $args["meta"] = true;
    }

    /**
     * Set content
     */
    if ($args["content"] === "") {
        $args["content"] = apply_filters("the_content", $args["post"]->post_content);
    }
}
?>

reference pop up showing contents of the comment at the top of previous code block

reference pop up for $args["post"] showing "No references found"

Also, I understand that perhaps a class structure would be better, and I will look in to that, but that entails retooling our templating system, so that will take time. For now, I’d like to get type hinting working in this use if at all possible.

2

Answers


  1. First, you can always convince most of the linters what the variable type is by use of @var annotation:

    /** @var array $foo */
    $foo = $bar->get();
    

    BUT before you so, please ensure WHY it sees null|string[]|string|false and not object in the first place. It might be a bug indication or incorrect PHPDocs elsewhere, but usually if Intelisense cannot tell what it is precisely, it would show mixed – your is more precise, so check why. But that is for linter only and makes no difference at runtime. Also, if it is null by default typehinting as object would be incorrect. It’s ?object then.

    As for accessing $args["post"] – there’s no fancy magic you can pull – you either check for null prior calling, or use ?-> syntax to not call on null (if you use PHP that supports that).

    Login or Signup to reply.
  2. I’m not sure what the support is like in Intelephense but you could try using array shapes which are widely supported by tools like Psalm, PHPStan, Phan and PhpStorm.

    Example:

    /** @var array{ post: ?WP_Post, class: string, light: bool, title: string, meta: ?bool, content: string } $args */
    $args = array_merge([
        "post"    => null,
        "class"   => "",
        "light"   => false,
        "title"   => "",
        "meta"    => null,
        "content" => "",
    ], $args);
    

    More info here: https://phpstan.org/writing-php-code/phpdoc-types#array-shapes

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search