Use tags parameter in JSON fetch

Hi,

For a project I need to use the content representations to fetch a json file. But in order to avoid a big load of every data in that json, I want to be able to filter its data by a tag.

I saw in the documentation, the possibility to fetch a specific pagination:

fetch('/blog.json/page:2')

so I was wondering if that would be possible to do it with any tags like:

fetch('blog.json/tag:2020')

Thank you in advance for your time.

Should work, but in your representation controller, you would of course have to filter by that tag.

Thanks for your quick reply. I see, that makes sense, I didn’t have time to try properly yet, just a nasty manual test, but no luck yet, I will try to provide a clean source code tomorrow.

I could run another test now, I’m close to achieving what I want but there is still a problem with the output of the JSON and the URL.

So my posts have a structural data, inside there are dates (starting date and ending date), I’m using the last date as a ‘date indicator’. This allow me to have every posts shown in an ordered year (until 2016).

<?php
// current year
$current_year = date('Y');
$first_year = (int)$current_year - 1;
$last_year = 2016;
for ($i = $first_year; $i >= $last_year; $i--) {
  // get all yearly posts
  $past_collection = $page
    ->children()
    ->filter(function ($page) use ($i) {
      $seance_date = $page->practical_information()->toStructure()->last()->date_start();
      return $seance_date->toDate('%Y') == $i;
    });
  // Sorting the posts by date
  $sorted_collection = $past_collection->sortBy(function ($page) {
    return $page->practical_information()->toStructure()->last()->date_start()->toDate();
  }, 'asc');

  $json = [];
  $json['data']  = [];
  $json['year']  = $i;

  foreach ($sorted_collection as $article) {
    $json['data'][] = array(
      'month' => (string)$article->practical_information()->toStructure()->last()->date_start()->toDate('%B'),
      'url'   => (string)$article->url(),
      'title' => (string)$article->title(),
      'image' => (string)$article->images()->filterBy('template', 'gallery')->first()
    );
  }
  echo json_encode($json);
}

The problem is that the JSON output has then multiple root elements and the URL ‘…/films.json/year:2019’ or any other year returns the same.

{
   "data":[
      {
         "month":"janvier",
         "url":"http:\/\/localhost:8888\/cinedoc\/films\/la-cordillere-des-songes",
         "title":"La Cordill\u00e8re des songes",
         "image":"&lt;img alt=\"\" src=\"http:\/\/localhost:8888\/cinedoc\/media\/pages\/films\/la-cordillere-des-songes\/a6cabcc262-1596520669\/cordillera_04.jpg\"&gt;"
      },
      {
         "month":"octobre",
         "url":"http:\/\/localhost:8888\/cinedoc\/films\/diego-maradona",
         "title":"Diego Maradona",
         "image":""
      },
      {
         "month":"novembre",
         "url":"http:\/\/localhost:8888\/cinedoc\/films\/madame",
         "title":"Madame",
         "image":"&lt;img alt=\"\" src=\"http:\/\/localhost:8888\/cinedoc\/media\/pages\/films\/madame\/215893de06-1596519745\/madame_still_01.jpg\"&gt;"
      }
   ],
   "year":2019
}{
   "data":[
      {
         "month":"janvier",
         "url":"http:\/\/localhost:8888\/cinedoc\/films\/la-cordillere-des-songes-old",
         "title":"Old - La Cordill\u00e8re des songes",
         "image":"&lt;img alt=\"\" src=\"http:\/\/localhost:8888\/cinedoc\/media\/pages\/films\/la-cordillere-des-songes-old\/26f08b0a7a-1596525247\/cordillera_04.jpg\"&gt;"
      },
      {
         "month":"novembre",
         "url":"http:\/\/localhost:8888\/cinedoc\/films\/madame-old",
         "title":"Old - Madame",
         "image":"&lt;img alt=\"\" src=\"http:\/\/localhost:8888\/cinedoc\/media\/pages\/films\/madame-old\/88df414c05-1596543653\/madame_still_01.jpg\"&gt;"
      }
   ],
   "year":2018
}

Somehow this looks overly complicated and I’m not sure what you are trying to achieve here and where the tags filter comes into play?

Actually I wanted first to try without the tag, thus the above code. But from what I understood if I want to use something else than “/page(:num)” or “/tag(:any)” I would have to add some new routes to the config.php. Which is becoming a bit too complicated.

So at the end, I manually add a year with a tag:

<?php
$tag = param('tag');
// get all yearly posts
$past_collection = $page
  ->children()
  ->filterBy('season', $tag, ',');
// Sorting the posts by date
$sorted_collection = $past_collection->sortBy(function ($page) {
  return $page->practical_information()->toStructure()->last()->date_start()->toDate();
}, 'asc');

$json = [];
$json['data']  = [];
$json['tag']  = $tag;

foreach ($sorted_collection as $article) {
  $json['data'][] = array(
    'month' => (string)$article->practical_information()->toStructure()->last()->date_start()->toDate('%B'),
    'url'   => (string)$article->url(),
    'title' => (string)$article->title(),
    'image' => (string)$article->images()->filterBy('template', 'gallery')->first(),
    'tag' => (string)$article->season()->value()
  );
}
echo json_encode($json);

With this I can use the “film.json/tag(:num)”.

Sorry for the confusion with my 3rd post and thank you for your time!

If you want to filter conditionally, depending on whether or not the parameter is set, you can do it like here: https://getkirby.com/docs/cookbook/content/filtering-with-tags#blog-controller.

On a side note, you don’t need to collection variable but can chain the sorting to the rest:

$past_collection = $page
  ->children()
  ->filterBy('season', $tag, ',')->sortBy(function ($page) {
  return $page->practical_information()->toStructure()->last()->date_start()->toDate();
}, 'asc');

Note that your sorting code will throw an error if the structure field is empty and there is therefore no last() element.

Thank you for the more elegant chaining method, regarding the last(), I made the structure field mandatory so there will always be a value there.

Regarding the controllers, so in theory if I want to have any other parameter filter in the URL I could simply pass it with the controller method without altering any route in the config.php?

To filter by tags or any other parameters, you don’t need any routes at all.

1 Like

Thank you so much for enlightening this!