Custom category title

Hello,
I would like to display a title defined according to the selected category.
I use a structure field to create the categories in panel [blog.yml]:

categories:
	label: Catégories
	type: structure
	fields:
		name:
			label: Nom de la catégorie
			type: text
		title:
			label: Titre de la catégorie
			type: text

Then in my template I use this to display the articles of the selected category [blog.php]:

<?php if (empty($categories) === false): ?>
<header class="h1">
	<h1><?= $categories->title() ?></h1> <!-- <= Custom title -->
	<div>
		<small>Catégorie:</small> <?= html($categories) ?>
		<a href="<?= $page->url() ?>">&times;</a>
	</div>
</header>
<?php else: ?>
	<?php snippet('intro') ?>
<?php endif ?>

How can I do to retrieve the title of the category?
because <?= $categories->title() ?> does not work.

You need ->toStructure() method for structure field:

How is $categories defined? I would expect this to be either a structure or an array, in which case you would have to loop through the items, calling name and title on each item.

I’m not sure I fully understand.
I just used the starterkit “tags” code.

Then I simply change the: type: tags field to: type: structure.

The problem is that I don’t know how to display only the title of the selected category… (I still have to learn)

I can’t see where and how you defined the $categories variable in your template/controller?

Your code should look something like this:

<?php 
$categories = $page->categories()->toStructure();
if ($categories->isNotEmpty()) :
  foreach ($categories as $category) : ?>

    <header class="h1">
	  <h1><?= $category->title() ?></h1> <!-- <= Custom title -->
	  <div>
		<small>Catégorie:</small> <?= html($category) ?>
		<a href="<?= $page->url() ?>">&times;</a>
	  </div>
    </header>
  <?php endforeach ?>
<?php endif ?>

Sorry,
I am using a controller:

return function ($page) {

    $categories = urldecode(param('categories'));
    $articles = collection('articles');

    if (empty($categories) === false) {
        $articles = $articles->filterBy('categories', $categories);
    }

    return [
      'categories' => $categories,
      'articles' => $articles->paginate(6)
    ];

};

Ok, you are getting the category from the URL. But this category then is just a string with no relation to your structure field and you first have to get the relevant entry from that field.

Example code (not tested):

return function ($page) {

   $articles = collection('articles');
   $categories = page('blog')->categories()->toStructure();
   if ( $category = urldecode(param('categories')) {
       $articles = $articles->filterBy('categories', $category);
       $categoryItem = $categories->findBy('name', $category);
   }
  

    return [
      'articles' => $articles->paginate(6),
      'categoryItem' => $categoryItem ?? null,
    ];

};

Then in your template:

<?php if ($categoryItem): ?>
<header class="h1">
	<h1><?= $categoryItem->title()->html() ?></h1> <!-- <= Custom title -->
	<div>
		<small>Catégorie:</small> <?= $categoryItem->name()->html()) ?>
		<a href="<?= $page->url() ?>">&times;</a>
	</div>
</header>
<?php else: ?>
	<?php snippet('intro') ?>
<?php endif ?>