Skip to content
Grav 2.0 is officially stable. Read the announcement →

Community guidelines

Please keep discussions civil and on-topic. Repeated violations may lead to a temporary ban.

General

Find all pages with a custom header field

Solved by pamtbaau View solution

Started by lilive 6 years ago · 2 replies · 871 views
6 years ago

Hello,

I want to find all the pages with a custom variable in the frontmatter, in php.

Here's some pages frontmatters:

YAML
---
news:
    location:
        - New York
    link: http://kufhlskjflkdjfhls
---
YAML
---
news:
    location:
        - New York
        - Chicago
    link: http://klmlmlmlkkkkmkmk
---
YAML
---
news:
    location:
        - Amsterdam
    link: http://qsssssszzszszszszszs
---

I want to find the pages where "New York" is a location.

Have you got an idea ?

I can do something like that

PHP
$collection = new Collection();
foreach( $all_pages as $p )
{
    $header = $p->header();
    if(
       $header
       && property_exists( $header, 'news' )
       && array_key_exists( 'location', $header->news )
       && in_array( 'New York', $header->news['location'] )
    )
    {
        $collection->append( $p );
    }
}

but I don't know how to get all the pages first ! This is silly.
And I have the feeling that something easier could be done. With $page->evaluate(...) maybe ?

Thank you for any tip. I will also appreciate any relevant link to the documentation.

P.S: A convenient solution could be to make this "location" field a part of the taxonomy. But it bother me that this taxonomy field will appear in the admin settings form, for every page, including the pages where this field make no sense.

6 years ago Solution

@lilive, A few answers/suggestions:

  • To get all pages in PHP you can do:
    PHP
    $pages = $this->grav['pages']->all();
    

    See docs \Grav\Common\Page\Pages::all()

  • To filter all pages you could use \Grav\Common\Iterator::filter(callback)

    PHP
    public function onPagesInitialized()
    {
    $city = 'New York';
    $pages = $this->grav['pages']->all();
    
    $pages->filter(function ($slug, $path) use ($pages, $city) {
      $page = $pages[$path];
      $header = (array) $page->header();
    
      if (!empty($header['news']['location'])) {
        $location = $header['news']['location'];
    
        return (is_array($location) && in_array($city, $location)) ||
          $location === $city;
      }
    
      return false;
    });
    
    // Process found pages
    }
    
  • Use taxonomy as you suggested.
    • To prevent taxonomy field from being displayed on 'default' pages you could override the 'default' blueprint and remove the taxonomy field .
      Docs: Removing Fields / Properties (unset-*@)
    • Create a dedicated blueprint for your own custom page type/template and add the taxonomy field there together with other fields required for your page header (e.g 'link') in a dedicated 'tab' that only shows in that page type.
      Docs: Example page blueprint

Hope this gives you enough ideas to continue...

👍 1
last edited 02/08/20 by pamtbaau
6 years ago

@pamtbaau:
Hope this gives you enough ideas to continue…

Yes indeed ! Thank you very much for this quick and really complete answer. You make me understand grav better.
This code works fine (and the empty() test is a good shortcut).

I'm already making a blueprint for this type of pages, but after some reading here, it seems tricky to me to hide and displace only one taxonomy field. I think I will stay with the first solution.

Thanks again !

Suggested topics

Topic Participants Replies Views Activity
General · by Jerry Hunt, 4 days ago
2 76 8 hours ago
General · by pamtbaau, 13 hours ago
1 47 12 hours ago
General · by Andy Miller, 1 day ago
0 44 1 day ago
General · by Marcel, 12 months ago
6 346 5 days ago
General · by Duc , 5 days ago
3 40 5 days ago