如何检索具有匹配子字段值的特定 ACF 转发器行

How to retrieve specific ACF repeater row with matching sub-field value

我已经试验和研究了几个小时,试图找到一种方法让它发挥作用,但我只是运气不好。

所以我有几个不同的自定义 post 类型需要混合使用。让我试着尽可能清楚和经济地解释它。

有 2 种自定义 post 类型,消息和校园。 (这是一个大型的多校区教会网站)。每个消息 post 都会有一些基于校区的转发器行(通过分类字段),每个校区 post 将尝试获取最新的消息 post,并拉取特定的 "campus" 转发器行,以及该行的相同字段值。

消息单曲的 ACF 转发器部分 post...(我们选择校园 post 之一,然后手动输入演讲者姓名和消息 URL)

所以目前,我在一个 "Campus" 单曲 post 中,试图查询并获取最新的消息 post,这是有效的。但是后来我试图定位并仅提取消息 post 内部特定转发器行的值。消息中的转发器字段是校园 Select(select 框基于 Post 对象字段(在 "campus" post 类型上),以及 2不同的文本字段。

为了进一步说明...消息 post 具有以下转发器数据: 转发器第 1 行:校园 Select - 特洛伊 (post),消息发言人 - 丹尼考克斯,消息 URL - (url A) 中继器第 2 行:校园 Select - 伯明翰 (post),消息发言人 - Cliff Johnson,消息 URL - (url B) ...并且多个校区将有一个动态数量的中继器。

所以我要做的是如下...在我的校园内 post - 例如 "Troy" - 我想获取最新消息 post,进入中继器并找到具有 "Campus Select" 值的行。我只想 return 消息发言人 (Danny Cox) 和来自该行的消息 URL (url A)。我不需要其他行的任何东西。

我当前的 "latest message" 中有 2 个转发器行,这是我当前的查询:

<?php
  $args = array(
    'post_type' => 'messages',
    'posts_per_page' => 1
  );

  $latestMessageQuery = new WP_Query($args);
  if( $latestMessageQuery->have_posts() ) { ?>
    <?php while ($latestMessageQuery->have_posts()) : $latestMessageQuery->the_post(); ?>
      <?php if( have_rows('campus_message') ): ?>
        <?php while( have_rows('campus_message') ): the_row(); ?>
          <?php if( get_sub_field('campus_selector') == 'troy' ): ?>
            <?php the_sub_field('message_speaker'); ?>
          <?php else: ?>
            <?php the_sub_field('message_speaker'); ?>
          <?php endif; ?>
        <?php endwhile; ?>
      <?php endif; ?>
    <?php endwhile; ?>
  <?php }
  wp_reset_query();
?>

为了进行故障排除,我正在手动尝试获取 "troy" 值 "campus selector",而不是根据我当前的 "campus" 位置动态获取该值...

查询是 return 两者:"Cliff Johnson Danny Cox"(因为我有 2 个转发器行)。

我怎样才能 return 在我的查询中只显示:“Troy, Danny Cox, url A”?

我在这个问题上得到了 ACF 支持的一些帮助,他们发给我的以下代码满足了我的要求。

<?php
$args = array(
    'post_type' => 'messages',
    'posts_per_page' => 1
);
$current_campus_id = get_the_ID();

$latestMessageQuery = new WP_Query($args);
if( $latestMessageQuery->have_posts() ) {
    while ($latestMessageQuery->have_posts()) : $latestMessageQuery->the_post();
        if( have_rows('campus_message') ):
            while( have_rows('campus_message') ): the_row();
                if( get_sub_field('campus_selector') == $current_campus_id ):
                    the_sub_field('message_speaker');
                    the_sub_field('message_url');
                    break;
                endif;
            endwhile;
        endif;
    endwhile;
}
wp_reset_query();
?>

我正在使用 $wpdb 全局提供更多 SQL 直接解决方案。 通常,我强烈反对使用 SQL "directly",但在这种情况下,WP 元数据的结构和 ACF 存储的元数据应该在未来稳定,因为 ACF 流将字段存储为 "normal" 元/自定义字段。

我发布这个是因为它是一种非常简单且无冗余的方法,可以通过子字段值获取特定的 ACF 转发器行。
...当您有很多 ACF 中继器行时很有用。

我将向您展示选项字段组中转发器的示例,因为我认为它最相关。

假设您有 key/name your_option_name 的选项字段和 key/name subfield_name 的子字段 - 请注意 \ 在某些部分转义,这是因为SQL LIKE 正在使用 _ 作为
一个特殊字符 - 意思是 "any single character"

  $query = 
 "SELECT option_name, option_value FROM {$GLOBALS['wpdb']->prefix}options"
." WHERE option_name LIKE ("
        ." SELECT"
        ." CONCAT( 'options\_your\_option\_name\_', CAST( REPLACE(option_name, 'options_your_option_name_', '' ) AS INTEGER ), '%' )"
        ." FROM {$GLOBALS['wpdb']->prefix}options"
        ." WHERE"
        ." (option_name LIKE 'options\_your\_option\_name\_%\_subfield\_name')"
        ." AND"
        ." (option_value = 'some subfield value')"
      ." LIMIT 0,1"
." )"
  ;

  $results = $GLOBALS['wpdb']->get_results( $query, ARRAY_A );

  if( !empty($results) ){
    foreach($results as $result){
      //do something with it :)
      echo $result['option_name'] . " => " . $result['option_value'];
      echo "<br>";
    }

  }

此解决方案的主要缺点是,如果您有一些格式化字段,则必须手动处理格式化,对于所见即所得的字段,它非常简单,只需使用 the_content 过滤器,如
echo apply_filters('the_content', $wysiwyg_stored_content);.

SQL 注意:它基本上搜索 prefix_main_key_NUMBER_subkey 然后从找到的键中删除 prefix_main_key_,所以只剩下 NUMBER_subkey =>现在,如果您在 MySQL/MariaDB 中将字符串转换为 INTEGER,并且它以 INTEGER 开头,您将以这种方式获得 INTEGER...:)

这不会遍历所有行,而是仅在您的 sub-field 与您的搜索匹配时才读取该行。希望这有帮助

 while (have_rows('repeater_name')) {
      the_row();
      if (get_sub_field('sub_field') != $unique_key) {
        // not our row
        continue;
      }
      // will get here if this is our row
    $sub_field1= get_sub_field('sub_field1');
    $sub_field2= get_sub_field('sub_field2');
    }