WP_Query::parse_orderby()protectedWP 4.0.0

Converts the given orderby alias (if allowed) to a properly-prefixed value.

Method of the class: WP_Query{}

No Hooks.

Return

String|false. Table-prefixed value to used in the ORDER clause. False otherwise.

Usage

// protected - for code of main (parent) or child class
$result = $this->parse_orderby( $orderby );
$orderby(string) (required)
Alias for the field to order by.

Notes

  • Global. wpdb. $wpdb WordPress database abstraction object.

Changelog

Since 4.0.0 Introduced.

WP_Query::parse_orderby() code WP 6.5.2

protected function parse_orderby( $orderby ) {
	global $wpdb;

	// Used to filter values.
	$allowed_keys = array(
		'post_name',
		'post_author',
		'post_date',
		'post_title',
		'post_modified',
		'post_parent',
		'post_type',
		'name',
		'author',
		'date',
		'title',
		'modified',
		'parent',
		'type',
		'ID',
		'menu_order',
		'comment_count',
		'rand',
		'post__in',
		'post_parent__in',
		'post_name__in',
	);

	$primary_meta_key   = '';
	$primary_meta_query = false;
	$meta_clauses       = $this->meta_query->get_clauses();
	if ( ! empty( $meta_clauses ) ) {
		$primary_meta_query = reset( $meta_clauses );

		if ( ! empty( $primary_meta_query['key'] ) ) {
			$primary_meta_key = $primary_meta_query['key'];
			$allowed_keys[]   = $primary_meta_key;
		}

		$allowed_keys[] = 'meta_value';
		$allowed_keys[] = 'meta_value_num';
		$allowed_keys   = array_merge( $allowed_keys, array_keys( $meta_clauses ) );
	}

	// If RAND() contains a seed value, sanitize and add to allowed keys.
	$rand_with_seed = false;
	if ( preg_match( '/RAND\(([0-9]+)\)/i', $orderby, $matches ) ) {
		$orderby        = sprintf( 'RAND(%s)', (int) $matches[1] );
		$allowed_keys[] = $orderby;
		$rand_with_seed = true;
	}

	if ( ! in_array( $orderby, $allowed_keys, true ) ) {
		return false;
	}

	$orderby_clause = '';

	switch ( $orderby ) {
		case 'post_name':
		case 'post_author':
		case 'post_date':
		case 'post_title':
		case 'post_modified':
		case 'post_parent':
		case 'post_type':
		case 'ID':
		case 'menu_order':
		case 'comment_count':
			$orderby_clause = "{$wpdb->posts}.{$orderby}";
			break;
		case 'rand':
			$orderby_clause = 'RAND()';
			break;
		case $primary_meta_key:
		case 'meta_value':
			if ( ! empty( $primary_meta_query['type'] ) ) {
				$orderby_clause = "CAST({$primary_meta_query['alias']}.meta_value AS {$primary_meta_query['cast']})";
			} else {
				$orderby_clause = "{$primary_meta_query['alias']}.meta_value";
			}
			break;
		case 'meta_value_num':
			$orderby_clause = "{$primary_meta_query['alias']}.meta_value+0";
			break;
		case 'post__in':
			if ( ! empty( $this->query_vars['post__in'] ) ) {
				$orderby_clause = "FIELD({$wpdb->posts}.ID," . implode( ',', array_map( 'absint', $this->query_vars['post__in'] ) ) . ')';
			}
			break;
		case 'post_parent__in':
			if ( ! empty( $this->query_vars['post_parent__in'] ) ) {
				$orderby_clause = "FIELD( {$wpdb->posts}.post_parent," . implode( ', ', array_map( 'absint', $this->query_vars['post_parent__in'] ) ) . ' )';
			}
			break;
		case 'post_name__in':
			if ( ! empty( $this->query_vars['post_name__in'] ) ) {
				$post_name__in        = array_map( 'sanitize_title_for_query', $this->query_vars['post_name__in'] );
				$post_name__in_string = "'" . implode( "','", $post_name__in ) . "'";
				$orderby_clause       = "FIELD( {$wpdb->posts}.post_name," . $post_name__in_string . ' )';
			}
			break;
		default:
			if ( array_key_exists( $orderby, $meta_clauses ) ) {
				// $orderby corresponds to a meta_query clause.
				$meta_clause    = $meta_clauses[ $orderby ];
				$orderby_clause = "CAST({$meta_clause['alias']}.meta_value AS {$meta_clause['cast']})";
			} elseif ( $rand_with_seed ) {
				$orderby_clause = $orderby;
			} else {
				// Default: order by post field.
				$orderby_clause = "{$wpdb->posts}.post_" . sanitize_key( $orderby );
			}

			break;
	}

	return $orderby_clause;
}