Failing to pass a variable to a snipet

Found a lot of similar questions, but none of them seems to work in my case. I’m sure I’m overlooking something really simple, would be grateful if someone could point me in the right direction.

My snippet looks like this:

<?php foreach ($categories as $category): ?>
<section class="dishes">
  <h2><?= $category ?></h2>
  <?php foreach ($page->$category()->toStructure() as $dish): ?>
  <article class="dish">
    <h3 class="dish-name"><?= $dish->dish() ?></h3>
    <p class="dish-description"><?= $dish->description() ?></p>
    <p class="dish-price">€ <?= $dish->price() ?></p>
  </article>
  <?php endforeach ?>
</section>
<?php endforeach ?>

First tried without passing anything

<?php snippet('menu') ?>

Which gives me an error for the variable $category not being defined, so I figured passing the variable to the snippet would do it like so:

<?php snippet('menu', ['category' => $category]) ?>

But no luck :frowning:

The problem is this line i think…

<?php foreach ($page->$category()->toStructure() as $dish): ?>

Should probable be

<?php foreach ($category->nameofstucturefield()->toStructure() as $dish): ?>

You cant do $category(). That needs to be the name of the stucture field, and your also setting $category on the for each loop, which is what is coming out in your h2 tag, rather then what you passed through.

How are you setting $categories?

Hi, $categories is set in a controller like this:

<?php

return function () {

    $categories = [
        'Starters',
        'Pasta',
        'Meat',
        'Desert'
    ];

    return [
        'categories' => $categories
    ];

};

Everything works perfectly if in a page template, but moving it to a snippet doesn’t.

Ok so you have multiple structure fields on each page that match up with the $categories array set in the controller?

The names in the array should match up with the structure field names, which i think are case sensitive (i’ve run into case issues like this, even on different versions of linux).

Try this…

<?php foreach ($page->{$category}()->toStructure() as $dish): ?>

But i think there is probably a much better approach to doing this. I think i would probably collect up the contents of each field in the controller as an array to combine the structure fields under headings, and then loop through that in the snippet.

like @jimbobrjames said you need to use curly brackets to inline a variable into the method chain.

<?php foreach ($page->{$category}()->toStructure() as $dish): ?>

in snippet you say <?php foreach ($categories
so you need to do

$categories = ['a', 'b'];
snippet('menu', ['categories' => $categories]); // $categories not $category

or you can omit that and lazyload it in snippet like this

<?php if(!isset($categories)) { $categories = ['a', 'b']; }
<?php foreach ($categories as $category): ?>

I’m afraid this is touching topics that are too advanced for my php knowledge :frowning: 'm sure there is a better way of collecting the fields and looping them as @jimbobrjames suggested. I’ll see if I can find some tips on that. Anyway, I tried moving the $categories into the snippet and adding the curly brackets.

<?php $categories = ['Starters', 'Pasta', 'Meat', 'Desert']; ?>
<?php foreach ($categories as $category): ?>
<section class="dishes">
  <h2><?= $category ?></h2>
  <?php foreach ($page->{$category}()->toStructure() as $dish): ?>
  <article class="dish">
    <h3 class="dish-name"><?= $dish->dish() ?></h3>
    <p class="dish-description"><?= $dish->description() ?></p>
    <p class="dish-price">€ <?= $dish->price() ?></p>
  </article>
  <?php endforeach ?>
</section>
<?php endforeach ?>

Calling the snippet with:

<?php snippet('menu', ['categories' => $categories]); ?>

will still error out as Undefined variable: categories

I would probably fetch up the four structure fields into a multi dimensional array in the controller and loop through that instead, something like described here.

1 Like

Tanks, I’ll take a look. And thank you both for taking the time to help.

If the categories are defined in the controller and you pass the $categories to the snippet, everything should work fine, provided the snippet is called in the controller for the page where you call the snippet.

1 Like

Maybe you can post everything together, controller, template and snippet with their filenames and content.

And what Kirby version are you using?

Hi texnixe! Thanks for looking into this :smile: I’m using Kirby 3 and this repo as a starting point, a version of the starter kit with pretty much all the examples shown in the docs. What I’m trying to do is convert the restaurant-menu and events pages into snippets that could be pulled in to a template. All the code is identical, apart from the parts I posted in the thread earlier.

Ah, I think get why it’s not working. The controller and the page I’m trying to pull the snippet into have different names. Apparently they have to be the same?

Content file name, controller file name and template file name have to match.

E.g. example.txt will use example.php controller and example.php template.
E.g. default.txt will use default.php controller and default.php template.
etc.

If a template with the name of the text file doesn’t exist, Kirby will fall back to the default.php template.

Should have spotted that one, plunged straight into the deep end with kirby 3, and a bit out of my depth. Thank you again :smile: Can’t give enough praise on the level of support here, it’s absolutely amazing.

1 Like