11

I have a Stripe subscription object that looks like this...

subscription: {
    items: {
        data: [
            plan: {
                id: 'my_plan_id'
            }
        ]
    }
}

What's the best way to safely retrieve the plan id? Currently I am doing the following.

'plan_id' => $subscription->items->data[0]->plan->id,

But, it looks like that will fail if items, data[0], or plan, is not set. I could do nest if statements like, if (isset($subscription->items) && isset(data[0]) ..., but I am not sure that is the best way.

Is there a PHP method or Laravel method that I can use to extract that property safely that would be cleaner than that?

Henry
  • 564
  • 3
  • 22

5 Answers5

21

If you're using PHP 7+, you can use the null coalesce operator:

'plan_id' => $subscription->items->data[0]->plan->id ?? $default,

This will evaluate the value if it's available, otherwise it will use the default, without generating any warnings or errors.

Example:

$foo = new stdClass();
var_dump($foo->bar->baz->data[0]->plan->id ?? null);

Output:

NULL
Alex Howansky
  • 50,515
  • 8
  • 78
  • 98
  • 1
    But if `items` is null, wouldn't the entire thing break with an error, `Error: trying to get property of non-object`? – Henry Jun 30 '17 at 14:04
  • 1
    Nope. It won't even break if `$subscription` is a non-object. – Alex Howansky Jun 30 '17 at 14:06
  • Cool, I am using PHP 7, so it looks like this is the best answer. Thanks! – Henry Jun 30 '17 at 14:07
  • 6
    This only works if you're accessing properties of a class/array. When using the same semantics but with methods PHP will throw. (Just a heads up for OO devs) – Tez Dec 04 '18 at 06:18
4

You can use an isset function over the entire selector:

isset($subscription->items->data[0]->plan->id) ? $subscription->items->data[0]->plan->id : null;
Jerodev
  • 32,252
  • 11
  • 87
  • 108
  • This appears to be the same as @Alex's answer, but without using the null coalesce operator. I prefer his, as it is cleaner IMO. But, thanks! – Henry Jun 30 '17 at 14:08
4

in PHP version 8

you should use Nullsafe operator as follow:

'plan_id' => $subscription?->items?->data[0]?->plan->id,
Ali_Hr
  • 4,017
  • 3
  • 27
  • 34
0

A rather cumbersome but generic method to access nested structures by a list of keys; can be made into a reusable function easily:

$id = array_reduce(['items', 'data', 0, 'plan', 'id'], function ($o, $k) {
    if (!$o) {
        return null;
    } else if (is_array($o) && isset($o[$k])) {
        return $o[$k];
    } else if (isset($o->$k)) {
        return $o->$k;
    }
}, $subscription);
deceze
  • 510,633
  • 85
  • 743
  • 889
0

you can take help of ternary condition to check if the value is set or not. If set then put that value otherwise put default as

$id=isset($subscription->items->data[0]->plan->id) ? $subscription->items->data[0]->plan->id : $your_dafault_value;

If the value is set then the $id looks like

$id='my_plan_id';//In most cases we should consider null as a default value

If the value is not set then the $id looks liks

 $id='your_dafault_value';
RAUSHAN KUMAR
  • 5,846
  • 4
  • 34
  • 70