I was working on a custom WordPress site recently, and came upon an interesting scenario. The client has a page of offered services, displayed as a grid of images with titles. The services offered by the client are hierarchical: that is, there are top level services, which drill down to second-level services, which drill to down to the individual services offered by the company. For example, if I offer “Content” as a service, that would drill down to “SEO” and “Copywriting.” “SEO” would drill down to consulting, keyword research, etc. You get the idea.
Because of this hierarchy, I decided to build this using pages instead of using a custom post type. Part of my reasoning behind this was because this just makes more sense given the nature of the content, and part of it was to leverage the natural hierarchy of WordPress that fits this arrangement: parent pages, children pages, and grandchildren pages. With featured images already supported, there is a a slight performance advantage to using pages for this vs. a custom post type.
The client wanted a grid of images representing each service on the parent page, followed by a brief excerpt of each service at the bottom. Both the excerpts and images linked to the sub-level services. This layout was identical for both the top-level service pages and the children service pages, with the grandchildren service pages (the actual individual services offered) being a more basic layout.
Of course, a custom template made the most sense for this, because the template could be applied to any parent or children service pages. The most intuitive use case for the end user is to be able to make the featured image of each page the image that would display in the grid. I also added a custom excerpt field (using Advanced Custom Fields) for the excerpt that would appear at the bottom of the page. This field would appear at the bottom of any page using the custom template.
The Challenge: Only Immediate Child Pages
The challenge then became how to list children pages of the current page with only a single level of depth. At first blush, this seems simple enough. The
wp_list_pages function already gives us a
child_of parameter and a
depth parameter. However, this function returns an unordered list, so it’s unusable to display a grid of images. That leaves us with the
get_pages function. However, this won’t give us what we need out of the box, either, because the
child_of parameter of this function returns both children and grandchildren. So, I had to manipulate this function a bit in order to get what I needed.
The solution was to pass the current page as an argument into both the
parent parameters of the
get_pages function, but using the first index of the
$post global variable in order to:
- Limit the children pages to only children of the current page (treating the current page as the parent), and
- Limit the displayed children pages to only the immediate children, excluding grandchildren.
So, each service page using this custom template displays the service pages that are its immediate children in the hierarchy. We can then loop through children pages to retrieve the title, permalink, featured image and the custom excerpt field for each page.
The content area of the custom template looks like this:
As you can see, once we’re able to limit the query to only the immediate children of the current page, then we can access those pages’ properties as usual because we’re just using the post object within our loop.
A side note: Because we’re using Advanced Custom Fields for the excerpt field in this demo, if you repurpose this for you own use, you should include a check for the function
the_field before running the “teaser” portion of this code, so that you don’t encounter a fatal error if the ACF plugin is ever de-activated. You can do this using the
Let me know if you find this useful!
Handy. Thanks for the snippet, David!
Thanks for reading, Jason!
Sure thing. Keep up the great work!