Search code examples
phpphpstormphp-8

PhpStorm hint ArrayShape?


I'm defining a class as follow, using the suggestion from https://blog.jetbrains.com/phpstorm/2020/10/phpstorm-2020-3-eap-4/#arrayshape to define the array shape as a constant so that it can be used around the project:

<?php

namespace my\namespace\Api;

use JetBrains\PhpStorm\ArrayShape;

class CheckoutSessionLineItemMetadata implements MetadataInterface {

  /**
   * The ArrayShape of toArray().
   */
  public const ARRAY_SHAPE = [
    'order_item_id' => "string",
    'order_id' => "string",
    'product_variation_id' => "string",
  ];

  /**
   * Constructs a new object.
   *
   * @param string $order_item_id
   * @param string $order_id
   * @param string $product_variation_id
   */
  public function __construct(
    private string $order_item_id,
    private string $order_id,
    private string $product_variation_id) {
  }

  /**
   * {@inheritDoc}
   */
  #[ArrayShape(self::ARRAY_SHAPE)] public function toArray(): array {
    return [
      'order_item_id' => $this->order_item_id,
      'order_id' => $this->order_id,
      'product_variation_id' => $this->product_variation_id,
    ];
  }

}

This is being used to help me pass some data to the Stripe API when creating a transaction.

There's somewhere else where I'm looping over data provided by a separate Stripe API response which includes a metadata element with that structure. I'd like to hint that the data takes on this array shape, but I'm not really sure how (or if) I can do it.

foreach ($data->display_items as $line_item) {
  /** @var $metadata CheckoutSessionLineItemMetadata::ARRAY_SHAPE */
  $metadata = $line_item->metadata;
  // Ideally I'd get hinting that the associated keys are on this element.
}

Is this possible? I should note that I am using this plugin: https://github.com/klesun/deep-assoc-completion/issues/63, so I could duplicate the structure with that, but it'd be a shame since it's already defined elsewhere.


Solution

  • Okay, after posting an edit with the deep-assoc-completion link I figured out how to do this. This does what I wanted.

       foreach ($data->display_items as $line_item) {
          /** @var $metadata = CheckoutSessionLineItemMetadata::ARRAY_SHAPE */
          $metadata = $line_item->metadata;
        }