Twig:在具有 if 条件的 N 列网格中输出数组元素的优雅方式
Twig: elegant way to output array elements in a grid of N columns with if condition
我正在使用 Timber & Twig 编写 Wordpress 主题。据我了解,在具有 N 列的网格中输出帖子的惯用方式是使用 batch
过滤器:
{% block content %}
{% for row in posts | batch(3) %}
<div class='grid-3'>
{% for post in row %}
<div class='col'>
{% include ['tease-'~post.post_type~'.twig', 'tease.twig'] %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock %}
如何使用具有 if
条件的 batch
过滤器,以便您只输出层次结构中的顶级帖子?
(条件为 {% if not post.parent %}
)
据我所知,这是不可能的。如果您正在寻找一种优雅的方式,我建议您采用不同的方式:
只要有可能,我不会在 Twig 中过滤帖子,而是在 PHP 中过滤帖子,然后再将帖子传递给模板。使用 Timber,您可以采用多种方式:
1。调整查询
使用正确的 parameters for WP_Query,您通常可以 select 只有您需要的帖子。
$context['posts'] = Timber::get_posts( array(
'post_parent' => 0
) );
2。筛选查询结果
有时在 WP_Query 中使用大量参数会使您的查询变慢。出于性能原因,有时查询更多稍后使用 PHP.
过滤的帖子会更好
$posts = Timber::get_posts();
$filtered = array();
foreach ( $posts as $post ) {
if ( $post->post_parent === 0 ) {
$filtered[] = $post;
}
}
$context['posts'] = $filtered;
或
$posts = Timber::get_posts();
$posts = array_filter( $posts, function( $post ) {
return $post->post_parent === 0;
} );
$context['posts'] = $posts;
一个小警告:默认查询使用您的 WordPress 后端在设置 > 阅读 > 博客页面中定义的帖子数量最多显示.当您过滤返回的帖子时,您最终得到的帖子可能比您预期的要少。
3。使用并覆盖默认参数
正如评论中提到的 Dan,使用 #1 必须再次构建整个 WP_Query
参数,如果在特殊页面上,比如存档页面。
要获取主查询使用的所有参数并用我们自己的参数覆盖它们以便稍后在 Timber::get_posts()
中使用它们,我们可以使用方便的 wp_parse_args 函数。我们将新参数作为第一个参数传递,并将主查询的查询变量作为默认参数传递给覆盖。
global $wp_query;
// Set query args before posts are queried in get_context()
$args = wp_parse_args( array(
'post_type' => 'page',
'post_parent' => 0,
), $wp_query->query_vars );
$context = Timber::get_context();
$posts = Timber::get_posts( $args );
$context['posts'] = $posts;
4。使用 pre_get_posts
操作挂钩(WordPress 方式)
适应主查询的默认 WordPress 方式是使用 pre_get_posts
操作挂钩。虽然这可能是最干净的方式,但使用起来并不方便。
pre_get_posts
动作挂钩需要在 functions.php
中定义。如果您在任何模板文件(如 page.php 或 archive.php)中定义它,则为时已晚。这里的缺点是您必须使用条件($query->is_main_query()
等)来确保您所做的更改只应用在有意义的地方。在查询中,您可以 set/reset 您想要更改的查询变量。
// In your functions.php
add_action( 'pre_get_posts', function( $query ) {
if ( $query->is_main_query() && $query->is_front_page() ) {
$query->set( 'post_type', 'page' );
$query->set( 'post_parent', 0 );
}
} );
如果您可以在实际使用它们的模板文件中设置查询变量,那就方便多了。这就是为什么我更喜欢#3 而不是#4。我已经 运行 进入调试会话,其中我的查询表现得很奇怪,直到我意识到有 pre_get_posts
干扰。
我正在使用 Timber & Twig 编写 Wordpress 主题。据我了解,在具有 N 列的网格中输出帖子的惯用方式是使用 batch
过滤器:
{% block content %}
{% for row in posts | batch(3) %}
<div class='grid-3'>
{% for post in row %}
<div class='col'>
{% include ['tease-'~post.post_type~'.twig', 'tease.twig'] %}
</div>
{% endfor %}
</div>
{% endfor %}
</div>
{% endblock %}
如何使用具有 if
条件的 batch
过滤器,以便您只输出层次结构中的顶级帖子?
(条件为 {% if not post.parent %}
)
据我所知,这是不可能的。如果您正在寻找一种优雅的方式,我建议您采用不同的方式:
只要有可能,我不会在 Twig 中过滤帖子,而是在 PHP 中过滤帖子,然后再将帖子传递给模板。使用 Timber,您可以采用多种方式:
1。调整查询
使用正确的 parameters for WP_Query,您通常可以 select 只有您需要的帖子。
$context['posts'] = Timber::get_posts( array(
'post_parent' => 0
) );
2。筛选查询结果
有时在 WP_Query 中使用大量参数会使您的查询变慢。出于性能原因,有时查询更多稍后使用 PHP.
过滤的帖子会更好$posts = Timber::get_posts();
$filtered = array();
foreach ( $posts as $post ) {
if ( $post->post_parent === 0 ) {
$filtered[] = $post;
}
}
$context['posts'] = $filtered;
或
$posts = Timber::get_posts();
$posts = array_filter( $posts, function( $post ) {
return $post->post_parent === 0;
} );
$context['posts'] = $posts;
一个小警告:默认查询使用您的 WordPress 后端在设置 > 阅读 > 博客页面中定义的帖子数量最多显示.当您过滤返回的帖子时,您最终得到的帖子可能比您预期的要少。
3。使用并覆盖默认参数
正如评论中提到的 Dan,使用 #1 必须再次构建整个 WP_Query
参数,如果在特殊页面上,比如存档页面。
要获取主查询使用的所有参数并用我们自己的参数覆盖它们以便稍后在 Timber::get_posts()
中使用它们,我们可以使用方便的 wp_parse_args 函数。我们将新参数作为第一个参数传递,并将主查询的查询变量作为默认参数传递给覆盖。
global $wp_query;
// Set query args before posts are queried in get_context()
$args = wp_parse_args( array(
'post_type' => 'page',
'post_parent' => 0,
), $wp_query->query_vars );
$context = Timber::get_context();
$posts = Timber::get_posts( $args );
$context['posts'] = $posts;
4。使用 pre_get_posts
操作挂钩(WordPress 方式)
适应主查询的默认 WordPress 方式是使用 pre_get_posts
操作挂钩。虽然这可能是最干净的方式,但使用起来并不方便。
pre_get_posts
动作挂钩需要在 functions.php
中定义。如果您在任何模板文件(如 page.php 或 archive.php)中定义它,则为时已晚。这里的缺点是您必须使用条件($query->is_main_query()
等)来确保您所做的更改只应用在有意义的地方。在查询中,您可以 set/reset 您想要更改的查询变量。
// In your functions.php
add_action( 'pre_get_posts', function( $query ) {
if ( $query->is_main_query() && $query->is_front_page() ) {
$query->set( 'post_type', 'page' );
$query->set( 'post_parent', 0 );
}
} );
如果您可以在实际使用它们的模板文件中设置查询变量,那就方便多了。这就是为什么我更喜欢#3 而不是#4。我已经 运行 进入调试会话,其中我的查询表现得很奇怪,直到我意识到有 pre_get_posts
干扰。