ACF: How to get users with a ACF flexible content subfield with a specific value AND layout?

New answer


I now have a better understanding of the question thanks to OPs comment and have come up with the following. Not tested!

global $wpdb;

/**
 * @var string $field The flexible content field name.
 */
$field = 'a_flexible_content_field';

/**
 * @var string $layout The flexible layout name.
 */
$layout="layoutTwo";

/**
 * @var string $subfield The name of the layouts sub field.
 */
$subfield = 'status';

/**
 * @var string $subfield_value The value of the layouts sub field.
 */
$subfield_value="some value";

/**
 * @var array|int[] $users The array we will push matching user IDs to.
 */
$users = [];

/**
 * @var string $map_sql Query for finding all users using the `$layout`
 */
$map_sql = <<<MAPQUERY
    SELECT `user_id`, `meta_value` FROM $wpdb->usermeta 
    WHERE `meta_key` = '$field'
    AND `meta_value` LIKE '%$layout%'
    GROUP BY `user_id`
MAPQUERY;

/**
 * @var array|object[] $map_results Returns array of users and their flexible field mappings.
 */
$map_results = $wpdb->get_results( $map_sql );

foreach ( $map_results as $map_result ) {

    $user_id = (int)$map_result->user_id;

    /**
     * @var mixed|string[] $map An array layouts orders.
     */
    $map = maybe_unserialize( $map_result->meta_value );

    if ( is_array( $map ) ) {

        /**
         * @var false|int $layout_index The position/index of the desired layout.
         */
        $layout_index = array_search( $layout, $map );

        if ( $layout_index !== false ) {

            /**
             * @var string $meta_key Build the specific layout meta key e.g. `a_flexible_content_field_1_status`
             */
            $meta_key = $field . '_' . $layout_index . '_' . $subfield;

            /**
             * @var string $user_sql Query if user has any layout subfield matching desired value.
             */
            $user_sql = <<<USERQUERY
    SELECT COUNT(*) FROM $wpdb->usermeta 
    WHERE `meta_key` = '$meta_key'
    AND `meta_value` = '$subfield_value'
    AND `user_id` = $user_id
USERQUERY;

            $user_result = $wpdb->get_var( $user_sql );

            // User has matching values, add them to array.
            if ( $user_result > 0 ) {
                $users[] = $user_id;
            }
        }

    }
}

The result should be an array ($users) of user IDs that use the layout layoutTwo and has a subfield key of status and value some value.


Old answer


If I understand correctly, all you need to do is perform a simple query on the usermeta table, like so…

global $wpdb;

$sql = <<<USERQUERY
    SELECT `user_id` FROM $wpdb->usermeta 
    WHERE `meta_key` LIKE 'a_flexible_content_field_%_status'
    AND `meta_value` IN ( 'layoutTwo', 'some value' )
    GROUP BY `user_id`
USERQUERY;

$user_ids = array_map( function( $row ) {
    return $row->user_id;
}, $wpdb->get_results( $sql ) );

The above will return an array of user IDs that have meta fields with a key like a_flexible_content_field_%_status and if the values are either layoutTwo or some value.

Example output for $user_ids

Array
(
    [0] => 1
    [1] => 3
    [2] => 9
)

Need the meta keys and values?

This should do the trick…

global $wpdb;

$sql = <<<USERQUERY
    SELECT `user_id`, `meta_key`, `meta_value` FROM $wpdb->usermeta 
    WHERE `meta_key` LIKE 'a_flexible_content_field_%_status'
    AND `meta_value` IN ( 'layoutTwo', 'some value' )
USERQUERY;

$results = $wpdb->get_results( $sql );

Example output for $results

Array
(
    [0] => stdClass Object
        (
            [user_id] => 1
            [meta_key] => a_flexible_content_field_0_status
            [meta_value] => some value
        )
    [1] => stdClass Object
        (
            [user_id] => 1
            [meta_key] => a_flexible_content_field_1_status
            [meta_value] => layoutTwo
        )
    [2] => stdClass Object
        (
            [user_id] => 3
            [meta_key] => a_flexible_content_field_0_status
            [meta_value] => layoutTwo
        )
    [3] => stdClass Object
        (
            [user_id] => 9
            [meta_key] => a_flexible_content_field_0_status
            [meta_value] => some value
        )
)

As you can see, if a user matches the condition more than once they will have multiple results in the returned array. You could combine them with something like:

$combined = [];

foreach ( $results as $result ) {
    $user_id = $result->user_id;
    $meta_key = $result->meta_key;
    $meta_value = $result->meta_value;

    if ( !array_key_exists( $user_id, $combined ) ) {
        $combined[ $user_id ] = [
            'user_id' => $user_id,
            'values' => []
        ];
    }

    $combined[ $user_id ][ 'values' ][] = [
        'key' => $meta_key,
        'value' => $meta_value
    ];
}

$combined = array_values( $combined );

Example output for $combined

Array
(
    [0] => Array
        (
            [user_id] => 1
            [values] => Array
                (
                    [0] => Array
                        (
                            [key] => a_flexible_content_field_0_status
                            [value] => some value
                        )

                    [1] => Array
                        (
                            [key] => a_flexible_content_field_1_status
                            [value] => layoutTwo
                        )

                )

        )

    [1] => Array
        (
            [user_id] => 3
            [values] => Array
                (
                    [0] => Array
                        (
                            [key] => a_flexible_content_field_0_status
                            [value] => layoutTwo
                        )

                )

        )

    [2] => Array
        (
            [user_id] => 9
            [values] => Array
                (
                    [0] => Array
                        (
                            [key] => a_flexible_content_field_0_status
                            [value] => some value
                        )

                )

        )

)