Count number of posts based on category

Hi there!
I’m a beginner so please bear with me.

I would like to count blogpost and display its post number based on a stucture field entry.

For example:
I have a post that belongs to structure field A and a post that belongs to structute field N and I would like to have two separate counters.

Right now it looks like this:
N1
A2

What I would like to do is:
N1
A1

Here is a screenshot:

Somehow I think (based on my research), the best way to go, is to create a group A and a group N and then count the post in those groups.
But I can’t figure out how to do this.

Any help is greatly appreciated!

Cheers,
Alessandro

Would be helpful to have your blueprint with the structure field…

The basic procedure would be to map a value to each structure item:

Assuming a structure field like this:

      articles:
        type: structure
        fields:
          category:
            type: text # This would be the field with A, N etc.
          pages:
            type: pages
            max: 1
            query: site.find('notes').children.listed

The template code would look like this:

$articles = $page->articles()->toStructure();
$articles = $articles->map(function($item) use($articles){
  $items = $articles->filterBy('category', $item->category()->value());
  $item->counter = $item->indexOf($items) + 1;
  return $item;
});

foreach ($articles as $article) {
  echo $article->category() . ' ' . $article->counter();
}

Thank you a lot for your help.
Maybe I should give a littel more context.

I tried to implement your solution but as far as I understand, this gives each category a fixed number.
A1, B2, C3… maybe I did it wrong :roll_eyes:

(Sorry if I repeat myself)
What I would like to do, is have a structure item of Category A and one of Category N and so on.
And then I would like to assign lets say 5 posts (or subpages) to A and count how many A posts I have and output each number like so: A1, A2, A3, A4, A5

My blueprint right now looks like this:

postTypes:
    type: structure
    label: Post categories
    help: Add new categories and specify abbreviation
    fields:
      postCategory:
        label: Category
        type: text
      abbreviation:
        label: Abbreviation
        type: text

And here my template where the Post-Number is missing:

<div class="content">

  <?php foreach ($page->grandChildren()->listed()->sortBy('date', 'desc') as $section): ?>
    <section>
      <h3><span class="type"><?= $section->postCategory() ?><?= 'Post-Number?' ?></span></h3>

    <?php if ($section->date()->isNotEmpty()): ?>
      <h3 class="date"><?= $section->date()->toDate('d.m.y') ?></h3>
    <?php endif ?>

    <details>
      <summary><h2><?= $section->title()?></h2></summary>

      <div class="text"><p><?= $section->text()->kirbytext()?></p></div>

      <?php if ($section->contact()->isNotEmpty()): ?>
        <div class="contact">
          <h3>Contact information</h3>
          <p class="notes"><?= $section->notes()->kirbytext()?></p>
          <p class="name"><?= $section->name()->kirbytext()?></p>
          <p class="email"><a href="mailto:<?= $section->email()?>?subject=contact"><?= $section->email()?></a></p>
          <p class="phone"><?= $section->phone()?></p>
        </div>
      <?php endif ?>
    </details>
  </section>
<?php endforeach ?>
</div>

I have a page named Actueel and there I define my structure fields along with a subpage named 2020. 2020 has also children (blogposts) and for each of those children you can choose one of the different categories (A, N or B and so on) in the structure field.

Am I overthinking things?
I know it would probably be easier to just have pages named A, B, C and then create subpages.

Thank you for your time @texnixe :pensive:

Ah, then the structure field is only for defining the possible categories, but the categories itself are assigned to each blog post via a select field, right? so the structure field is not relevant for what you want to achieve at all.

But the general procedure would be the same, only we don’t use a structure field as basis for the mapping but the posts.

<?php
$articles = $page->grandChildren()->listed()->sortBy('date', 'desc');
$articles = $articles->map(function($item) use($articles){
  $items = $articles->filterBy('postCategory', $item->postCategory()->value());
  $item->counter = $item->indexOf($items) + 1;
  return $item;
});
?>
<div class="content">

  <?php foreach ($articles as $section): ?>
    <section>
      <h3><span class="type"><?= $section->postCategory() ?><?= $section->counter() ?></span></h3>

    <?php if ($section->date()->isNotEmpty()): ?>
      <h3 class="date"><?= $section->date()->toDate('d.m.y') ?></h3>
    <?php endif ?>

    <details>
      <summary><h2><?= $section->title()?></h2></summary>

      <div class="text"><p><?= $section->text()->kirbytext()?></p></div>

      <?php if ($section->contact()->isNotEmpty()): ?>
        <div class="contact">
          <h3>Contact information</h3>
          <p class="notes"><?= $section->notes()->kirbytext()?></p>
          <p class="name"><?= $section->name()->kirbytext()?></p>
          <p class="email"><a href="mailto:<?= $section->email()?>?subject=contact"><?= $section->email()?></a></p>
          <p class="phone"><?= $section->phone()?></p>
        </div>
      <?php endif ?>
    </details>
  </section>
<?php endforeach ?>
</div>

Hi @texnixe
and again, thank you a lot.

Unfortunately this still doesn’t count the posts of each individual category but instead counts all posts in all categories. (Which is still more, than I could achieve :sweat_smile: )

Hm, I tested this in a Starterkit and it works as expected :thinking:

I’m using the PlainKit but this is probably not relevant.

Maybe it’s because of how I assign the categories to each blog?

              postCategory:
                width: 1/4
                label: Post category
                help: wow
                type: select
                options: query
                query:
                  fetch: site.find('actueel').postTypes.toStructure
                  text: "{{ structureItem.postCategory }}"
                  value: "{{ structureItem.abbreviation }}"

I use the second column (abbreviation) of my structure field as value.

No, that doesn’t matter because we filter by value stored in the post, as I said above, the structure field is completely irrelevant for the output here as its only purpose is to define your categories.

But I wonder why your output is the wrong way round, anyway, as if you change the order again. Could you please post the final code or send me the project.

Ah yes, already forgot that :sweat_smile:

I sent you my project via private message.
You are awesome!

We have to make two changes:

from

$item->counter = $item->indexOf($items) + 1;

To:

$item->counter = $items->indexOf($item) + 1;

And you use the wrong field name, change abbreviation to postCategory in this line:

$items = $articles->filterBy('abbreviation', $item->abbreviation()->value());

But I haven’t found out why the example worked in my test but not in your installation…

OMG, it works :heart_eyes_cat:

Thank sooo much for your patience and support!!

You are very welcome!

FYI:

This didn’t work in your project because your are still on Kirby 3.3.4 and I tested my code with 3.3.5.