【问题标题】:Twig: elegant way to output array elements in a grid of N columns with if conditionTwig:在具有 if 条件的 N 列网格中输出数组元素的优雅方式
【发布时间】:2016-11-18 18:17:26
【问题描述】:

我正在使用 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 %})

【问题讨论】:

    标签: wordpress twig timber


    【解决方案1】:

    据我所知,这是不可能的。如果您正在寻找一种优雅的方式,我建议您采用不同的方式:

    只要可以,我不会在 Twig 中过滤帖子,而是在 PHP 中过滤帖子,然后再将帖子传递给模板。使用 Timber,您可以采用多种方式:

    1。调整查询

    使用正确的parameters for WP_Query,您通常可以只选择您需要的帖子。

    $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。使用并覆盖默认参数

    正如 cmets 中提到的 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-&gt;is_main_query() 等)来确保您所做的更改仅应用于有意义的地方。在查询中,您可以设置/重置要更改的查询变量。

    // 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 干扰。

    【讨论】:

    • 谢谢!我最终使用第二种形式来过滤查询结果。我发现要优雅地使用#1,Timber 需要有一种方法来覆盖当前查询,只使用你想要的附加参数,而不是构建 整个 get_posts 中的 WP_Query 对象。
    • @Dan:是的,很遗憾,您不能像在更改主查询时那样将pre_get_posts 过滤器与 Timber 一起使用。我相应地添加了一个解决方案#3,它可能更适合你。但是,我不知道它有多优雅。
    • 太好了!这非常有用,谢谢您,感谢您在查询后过滤帖子的警告。如果问的不是太多,您能否进一步说明无法将pre_get_posts 与 Timber 一起使用?我似乎能够设置每页的自定义帖子数量(通过覆盖 posts_per_archive_page 查询变量),然后在 Timber 中使用它们。
    • @Dan 显然我错了。您可以将pre_get_posts 与 Timber 一起使用。我错误地尝试在模板文件中使用它而不是将其添加到functions.php。所以我今天自己学到了一些东西:),很高兴你问到它。我相应地添加了解决方案#4。
    • 太棒了!谢谢你这么彻底。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-08-10
    • 1970-01-01
    • 2011-08-06
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多