Ordering Meta Box group rows by a sub field in Bricks

In the BricksLabs Facebook group a user asks:

Any idea how to set the sort order of a cloneable group in the query? In this case, I just need to sort social media accounts alphabetically. I know it can be done manually, but that isn’t a viable option with multiple people entering content.

In the past, we showed how posts could be sorted/ordered by a Meta Box group field’s sub-field value in the Sort Posts by Meta Box Group Sub Field in Bricks tutorial.

This Pro tutorial shows a relatively simplified case of the above where we want to order the rows of a Meta Box group by the value of one of its sub fields in Bricks.

Given this Meta Box group (JSON export below the screenshot):

JSON export of the field group

let’s say, for a specific post the group-type field is populated like this:

With the Meta Box group query type for a query loop in the single post Bricks template like this:

The output on the single post will be:

After implementing this tutorial, it will become:

i.e., the results are sorted in ascending order of the account type (sub field value).

Solution

Add the following in child theme‘s functions.php (don’t include the opening PHP tag in this case) or a code snippets plugin:

<?php 

// Order posts by Meta Box group's (social_media_accounts) sub field (account_type) value
add_filter( 'bricks/query/result', function( $result, $query_obj ) {
	// Return the original result if the query object type is not "mb_post_social_media_accounts"
	if ( $query_obj->object_type !== 'mb_post_social_media_accounts' ) {
		return $result;
	}

	usort( $result, function ( $a, $b ) {
		return strcmp( $a['account_type'], $b['account_type'] );
	});

	return $result;
}, 10, 2 );

Replace both instances of mb_post_social_media_accounts with mb_<yourposttype>_<yourgroupfieldname>.

We are calling PHP’s usort() function on the $result array (screenshot) with a custom comparison (anonymous) function. This comparison function receives the first two items, compares the string values and returns an integer. If the first string is less than the second string, it returns a negative value. If the first string is greater than the second string, it returns a positive value. If the strings are equal, it returns 0.

If the returned value is negative, it means that $a (the first MB group row) should come before $b (the second MB group row) in the sorted array. If the returned value is positive, it means that $a should come after $b in the sorted array. If the returned value is 0, it means that $a and $b are equal and their order remains unchanged.

The comparison then happens between 2nd and 3rd items, 3rd and 4th items and so on.

By the end, $result array will be sorted in ascending order based on the account_type values.