Only first array item is defined when passing array/object as data to snippet

I am trying to use snippets with more complicated schema, such as

$result = snippet('path/to/snippet', ['a' => $a, 'b' => $b], true);

where

$a = 'string';

$b = [
   'string',
   'string',
   'string'
];

$a is valid and usable from within the snippet, but $b gives error Undefined variable: b

I am 100% sure $b is defined as print_r($b) just before calling the snippet outputs what I expect…

Any ideas? Am I doing something stupid?

Is this typo while posting here or actual code? Should be 'b' => $b instead = sign

Sorry. Yes, typo just on here. Correct in my actual code.

Could you post your snippet? May be you missing something.

And how is $b actually defined? Maybe post the context in which the snippet is called

Here is the context. There is route which calls this snippet:

$b = (object) [
  'c' => null,
  'p' => null,
  'r' => null
];

// $x is passed from the route as GET parameter, and is valid and correct at this point

if ($x) {
  $x = autoid($x);
  if ($x) {
    if ($x->x_excl_cats()->isNotEmpty()) {
      $b->c = Str::split($x->x_excl_cats());
    }
    if ($x->x_excl_products()->isNotEmpty()) {
      $b->p = Str::split($x->x_excl_products());
    }
    if ($instance->x_excl_ranges()->isNotEmpty()) {
      $b->r = Str::split($x->x_excl_ranges());
    }
  }
}

// $b and $b->c is valid and correct at this point, but undefined in the snippet
// $a is passed from the route as GET parameter and is correct and usable within the snippet

$categories  = snippet('products/categories', ['a' => $a, 'b' => $b->c], true);

Within the snippet, $a (equal to $a string) is correct, and $b (equal to $b->c array) is undefined.

Have also tried passing 'b' => $b->c as a string, and it’s still undefined.

In any case, your variable will be undefined if $x is not valid, so you have to initialize $b before your conditions.

Yeah, that’s fine - the snippet can handle $b being null, but the issue is it being undefined inside the snippet when it’s definitely not when I pass it in.

Can you just confirm that theoretically Kirby should be fine with the following arrangement?

$data = [
  'a' => 'string 1',
  'b' => ['string 2', 'string 3', 'string 4']
];

$result = snippet('path/to/snippet', $data, true);

Yes, that should work.

Strange. How do you access $b within your snippet? You can perhaps try

<?php
$a = $a ?? "";
$b = $b ?? []; // or ?? null
?>
<?php /* Your snippet code goes here. $b should definitely be defined by now. */ ?>

You can then try to figure out why the real value of $b does not make its way into the snippet. Maybe there’s a name clash anywhere else. Using one-letter variable names can be prone to such effects.

If I am doing this in a template:

  <?php
    $a = 'A';
    $b = (object) ['c' => 'C','d' => 'D'];
    print_r($b);
    snippet('test',['a' => $a,'b' => $b->c]);
  ?>

and the test.php snippet just contains this:

<?php
  print_r($a);
  print_r($b);
?>

I get this on the page:

  stdClass Object
(
    [c] => C
    [d] => D
)
AC

which is what I expect. So something else must be at odds with your code.