have_rows() │ ACF 4.3.0
Checks if a field (such as Repeater or Flexible Content) has any rows of data to loop over. This function is intended to be used in conjunction with the_row() to step through available values.
Хуков нет.
Возвращает
true|false.
Использование
have_rows( $selector, $post_id );
- $selector(строка) (обязательный)
- The field name or field key.
- $post_id(разное)
- The post ID where the value is saved.
По умолчанию: current post
Список изменений
| С версии 4.3.0 | Введена. |
Код have_rows() have rows ACF 6.4.2
function have_rows( $selector, $post_id = false ) {
// Validate and backup $post_id.
$_post_id = $post_id;
$post_id = acf_get_valid_post_id( $post_id );
// Vars.
$key = "selector={$selector}/post_id={$post_id}";
$active_loop = acf_get_loop( 'active' );
$prev_loop = acf_get_loop( 'previous' );
$new_loop = false;
$sub_field = false;
// Check if no active loop.
if ( ! $active_loop ) {
$new_loop = 'parent';
// Detect "change" compared to the active loop.
} elseif ( $key !== $active_loop['key'] ) {
// Find sub field and check if a sub value exists.
$sub_field_exists = false;
$sub_field = acf_get_sub_field( $selector, $active_loop['field'] );
if ( $sub_field ) {
$sub_field_exists = isset( $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ] );
}
// Detect change in post_id.
if ( $post_id != $active_loop['post_id'] ) {
// Case: Change in $post_id was due to this being a nested loop and not specifying the $post_id.
// Action: Move down one level into a new loop.
if ( empty( $_post_id ) && $sub_field_exists ) {
$new_loop = 'child';
// Case: Change in $post_id was due to a nested loop ending.
// Action: move up one level through the loops.
} elseif ( $prev_loop && $prev_loop['post_id'] == $post_id ) {
acf_remove_loop( 'active' );
$active_loop = $prev_loop;
// Case: Chang in $post_id is the most obvious, used in an WP_Query loop with multiple $post objects.
// Action: leave this current loop alone and create a new parent loop.
} else {
$new_loop = 'parent';
}
// Detect change in selector.
} elseif ( $selector != $active_loop['selector'] ) {
// Case: Change in $field_name was due to this being a nested loop.
// Action: move down one level into a new loop.
if ( $sub_field_exists ) {
$new_loop = 'child';
// Case: Change in $field_name was due to a nested loop ending.
// Action: move up one level through the loops.
} elseif ( $prev_loop && $prev_loop['selector'] == $selector && $prev_loop['post_id'] == $post_id ) {
acf_remove_loop( 'active' );
$active_loop = $prev_loop;
// Case: Change in $field_name is the most obvious, this is a new loop for a different field within the $post.
// Action: leave this current loop alone and create a new parent loop.
} else {
$new_loop = 'parent';
}
}
}
// Add loop if required.
if ( $new_loop ) {
$args = array(
'key' => $key,
'selector' => $selector,
'post_id' => $post_id,
'name' => null,
'value' => null,
'field' => null,
'i' => -1,
);
// Case: Parent loop.
if ( $new_loop === 'parent' ) {
$field = get_field_object( $selector, $post_id, false );
if ( $field ) {
$args['field'] = $field;
$args['value'] = $field['value'];
$args['name'] = $field['name'];
unset( $args['field']['value'] );
}
// Case: Child loop ($sub_field must exist).
} else {
$args['field'] = $sub_field;
$args['value'] = $active_loop['value'][ $active_loop['i'] ][ $sub_field['key'] ];
$args['name'] = "{$active_loop['name']}_{$active_loop['i']}_{$sub_field['name']}";
$args['post_id'] = $active_loop['post_id'];
}
// Bail early if value is either empty or a non array.
if ( ! $args['value'] || ! is_array( $args['value'] ) ) {
return false;
}
// Allow for non repeatable data for Group and Clone fields.
if ( acf_get_field_type_prop( $args['field']['type'], 'have_rows' ) === 'single' ) {
$args['value'] = array( $args['value'] );
}
// Add loop.
$active_loop = acf_add_loop( $args );
}
// Return true if next row exists.
if ( $active_loop && isset( $active_loop['value'][ $active_loop['i'] + 1 ] ) ) {
return true;
}
// Return false if no next row.
acf_remove_loop( 'active' );
return false;
}