Fetching content by tag from structure with multiple items across multiple pages

So I have multiple pages, each with multiple videos, each with their own tags. Right now I have the videos in the blueprint as a structure, and each video gets its own tags. What I’m trying to do is have a master video page where all the videos from the respective pages can be filtered by tag. Is this possible?

Any advice on the template code for this?

right now the structure I have looks like this:

videos:
    label: Videos
    type: structure
    entry: >
      {{url}}<br />
      {{title}}<br />
      {{decription}}<br />
      {{tags}}
    fields:
      url:
        label: Video URL
        type: url
      title:
        label: Title
        type: text
      description:
        label: Description
        type: textarea
      tags:
        label: Tags
        type: tags

You can use something similar as proposed in this topic. Basically you would filter by the template that contains videos and then iterate through all items in the structure field.

If you need help with the specific code, please let me know.

Well, but I think you need to collect all structure field items of all subpages into one collection first, so that you can filter by tag afterwards. If you use the toStructure() method, this should work.

Cool, I didn’t know about toStructure(), that’s very useful.

I’m having trouble getting the template code to work however, it breaks the page.

  <ul>
  <?php foreach($pages->find('modules')->children()->videos()->toStructure() as $vid): ?>
    <li><?php echo $vid->url() ?></li>
  <?php endforeach ?>
  </ul>

(not tackling the tags just yet, just trying to get a list of urls)
Am I missing something? (I didn’t try anything from the first reply, it’s a bit over my head, but I’m willing to.)

By using $pages->find('modules')->children(), you are getting a list of all the children pages. You can’t access the videos field directly on that collection, but you can use the following code:

<ul>
  <?php foreach($pages->find('modules')->children() as $p): ?>
    <?php foreach($p->videos()->toStructure() as $vid): ?>
      <li><?php echo $vid->url() ?></li>
    <?php endforeach ?>
  <?php endforeach ?>
</ul>

I’m sorry about that. My phrasing was a bit too complex. :smiley:

One more thing: Because videos() is a native Kirby page method, you need to use

<?php foreach($p->content()->videos()->toStructure() as $vid): ?>

(or use another field name)

1 Like

Cool, this is all good. I have part of it working:

  <?php foreach($pages->find('modules')->children() as $p): ?>
    <?php foreach($p->videosection()->toStructure() as $vid): ?>
      <figure class="vid">
        <?php echo embed::youtube($vid->url(), $attr = array('width'=>'100%','height'=>'315','frameborder'=>'0')) ?>
        <h3><?php echo $vid->title() ?></h3>
        <caption>
          <?php echo $vid->description()->kirbytext() ?>
        </caption>
        <div class="tags">
          <?php  echo $vid->tags()->kirbytext() ?>
        </div>
      </figure>
    <?php endforeach ?>
  <?php endforeach ?>

The tags there aren’t interactive, it just displays a list for now. I tried to get a list of all the tags below, but it seems the $tags array returns every item from the $vid structure instead of just the tags. What’s going on here? Thanks so much!
Edit: it does the same thing (returns every item) when I only have pluck(’’) with nothing inside…

    <?php foreach($pages->find('modules')->children() as $p): ?>
      <?php foreach($p->videosection()->toStructure() as $vid): ?>
        <?php $tags = $vid->pluck('tags', ',', true); ?>
        <ul class="tags">
          <?php foreach($tags as $tag): ?>
          <li>
              <?php echo html($tag) ?>
          </li>
          <?php endforeach ?>
        </ul>
      <?php endforeach ?>
    <?php endforeach ?>

And just for reference, this is what my blueprint looks like (hasn’t changed much):

  videosection:
    label: Videos
    type: structure
    entry: 
      {{url}}<br />
      {{title}}<br />
      {{description}}<br />
      {{tags}}
    fields:
      url:
        label: URL
        type: url
      title:
        label: Title
        type: text
      description:
        label: Video Description
        type: textarea
      tags:
        label: Tags
        type: tags
        lower: true

Try this:

  <?php foreach($pages->find('modules')->children() as $p): ?>
    <?php foreach($p->videosection()->toStructure() as $vid): ?>
      <figure class="vid">
        <?php echo embed::youtube($vid->url(), $attr = array('width'=>'100%','height'=>'315','frameborder'=>'0')) ?>
        <h3><?php echo $vid->title() ?></h3>
        <caption>
          <?php echo $vid->description()->kirbytext() ?>
        </caption>
          <?php $tags = $vid->tags()->split() ?>
            <ul class="tags">
              <?php foreach($tags as $tag): ?>
                <li>
                  <?php echo html($tag) ?>
                </li>
             <?php endforeach ?>
            </ul>
      </figure>
    <?php endforeach ?>
  <?php endforeach ?>

1 Like