Reputation: 376
I have the following WordPress query code working in my Timber theme, but am struggling with how to convert into the Timber/Twig format.
$args = array(
'taxonomy' => 'category',
'parent' => '7',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
);
$terms = get_terms( $args );
foreach ( $terms as $term ) {
$termId = $term->term_id;
// Output first level of children of parent category ID 7
echo '<p>' . $term->name . '</p>';
$args = array(
'taxonomy' => 'category',
'child_of' => $termId,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
);
$childTerms = get_terms( $args );
foreach ( $childTerms as $childTerm ) {
$childTermId = $childTerm->term_id;
// Output second level of children of parent category ID 7
echo '<p>' . $childTerm->name . '</p>';
$args = array(
'cat' => $childTermId,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
);
$query = new WP_Query( $args );
while( $query->have_posts() ) : $query->the_post();
// Output posts assigned to second level children categories
echo '<p><a href="' . get_the_permalink() . '">' . get_the_title() . '</a></p>';
endwhile;
wp_reset_postdata();
// $posts = Timber::get_posts( $args );
}
}
Example Timber/Twig code with incomplete functionality
{% for term in terms %}
<div class="category">
<h3>
{{ term.name }}
</h3>
{% for childTerm in terms %}
{% if childTerm.parent == term.term_id %}
<div class="category__child">
<h4>{{ childTerm.name }}</h4>
<!-- Output posts from child terms here -->
</div>
{% endif %}
{% endfor %}
</div>
{% endfor %}
HTML nested output example
Parent Category
Parent Category
Parent Category
Any assistance is greatly appreciated.
Upvotes: 1
Views: 1281
Reputation: 376
Here is my working PHP and Twig code with the helpful solutions provided by @DarkBee. I hope this is helpful to anyone working with Timber for WordPress.
Page Stories PHP
$context = Timber::context();
$timber_post = new Timber\Post();
$data = [];
$terms = get_terms([
'taxonomy' => 'category',
'parent' => '7',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
]);
foreach ( $terms as $term ) {
/**
* Assign parent term to array and initiate children array
* Use term id so you can match the children easier with their parent
**/
$data[$term->term_id] = [
'name' => $term->name,
'slug' => $term->slug,
'children' => [],
];
$childTerms = get_terms([
'taxonomy' => 'category',
'child_of' => $term->term_id,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
]);
foreach ( $childTerms as $childTerm ) {
/**
* Assign child term to parent inside array and initiate post array
* Use child term id so you can match the post easier with the correct child
**/
$data[$term->term_id]['children'][$childTerm->term_id] = [
'name' => $childTerm->name,
'posts' => [],
];
$query = new WP_Query([
'cat' => $childTerm->term_id,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
]);
while($query->have_posts()) {
$query->the_post();
$data[$term->term_id]['children'][$childTerm->term_id]['posts'][] = [
'url' => get_the_permalink(),
'title' => get_the_title(),
'date' => get_the_date(),
];
}
wp_reset_postdata();
}
}
$context['data'] = $data;
Timber::render( array( 'page-' . $timber_post->post_name . '.twig', 'page.twig' ), $context );
Page Stories Twig
{% for parent in data %}
<div class="category">
<h3 id="{{ parent.slug }}">
{{ parent.name }}
</h3>
{% if parent.children|default %}
{% for child in parent.children %}
<div class="category__child">
<h4>
{{ child.name }}
</h4>
{% if child.posts|default %}
{% for post in child.posts %}
<div class="story">
<a href="{{ post.url }}" title="{{ post.title }}">
{{ post.title }}
</a>
<span>
{{ post.date }}
</span>
</div>
{% endfor %}
{% endif %}
</div>
{% endfor %}
{% endif %}
</div>
{% endfor %}
Upvotes: 0
Reputation: 15624
First you have to alter the data your are sending to the view. Group the children with the parents and groups the posts with the corresponding child. This could be achieved with something like this:
<?php
$data = [];
$terms = get_terms([
'taxonomy' => 'category',
'parent' => '7',
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
]);
foreach ($terms as $term) {
/**
* Assign parent term to array and initiate children array
* Use term id so you can match the children easier with their parent
**/
$data[$term->term_id] = [
'name' => $term->name,
'children' => [],
];
$childTerms = get_terms([
'taxonomy' => 'category',
'child_of' => $term->term_id,
'orderby' => 'name',
'order' => 'ASC',
'hide_empty' => false,
]);
foreach ($childTerms as $childTerm) {
/**
* Assign child term to parent inside array and initiate post array
* Use child term id so you can match the post easier with the correct child
**/
$data[$term->term_id]['children'][$childTerm->term_id] = [
'name' => $childTerm->name,
'posts' => [],
];
$query = new WP_Query([
'cat' => $childTerm->term_id,
'orderby' => 'title',
'order' => 'ASC',
'posts_per_page' => -1,
]);
while($query->have_posts()) {
$query->the_post();
$data[$term->term_id]['children'][$childTerm->term_id]['posts'][] = [
'url' => get_the_permalink(),
'title' => get_the_title(),
];
}
wp_reset_postdata();
}
}
This will create a nested array which will be easier to use inside twig, e.g.
<ul>
{% for parent in data %}
<li>
{{ parent.name }}
{% if parent.children|default %}
<ul>
{% for child in parent.children %}
<li>
{{ child.name }}
{% if child.posts|default %}
<ul>
{% for post in child.posts %}
<li><a href="{{ post.url }}" title="{{ post.title }}">{{ post.title }}</a></li>
{% endfor %}
</ul>
{% endif %}
</li>
{% endfor %}
</ul>
{% endfor %}
</li>
{% endfor %}
</ul>
note: didn't test the wordpress part as I don't use wordpress
Upvotes: 1