WordPress.org

Make WordPress Core

Opened 5 years ago

Closed 5 years ago

Last modified 4 years ago

#29738 closed enhancement (fixed)

Support nested queries in WP_Tax_Query

Reported by: boonebgorges Owned by: boonebgorges
Milestone: 4.1 Priority: normal
Severity: normal Version:
Component: Taxonomy Keywords: has-patch
Focuses: Cc:

Description

See #29642 for a related ticket for WP_Meta_Query.

The current syntax of WP_Tax_Query is limited to a flat set of queries, linked by a single 'relation'. This limits the kinds of queries you can run. For example, the following type of query cannot be run with the current syntax:

SELECT ... WHERE (
    'post_tag' IN ( 'gum', 'cereal', 'candy' )
    AND
    (
        'favorite_turtle' NOT IN ('Raphael')
        OR
        'favorite_soda' = 'RC Cola'
    )
)

(Don't ask me what kind of WordPress installation would be querying for these things. A pretty cool one?)

I propose that WP_Tax_Query be restructured to allow for nested queries of arbitrary depth. The above translates to a tax_query argument that looks like this:

'tax_query' => array(
    'relation' => 'AND',
    array(
        'taxonomy' => 'post_tag',
        'terms' => array( 'gum', 'cereal', 'candy' ),
        'field' => 'slug',
        'operator' => 'IN',     
    )
    array(
        'relation' => 'OR',
        array(
            'taxonomy' => 'favorite_turtle',
            'terms' => array( 'Raphael' ),
            'field' => 'name',
            'operator' => 'NOT IN',
        ),
        array(
            'taxonomy' => 'favorite_soda',
            'terms' => array( 'RC' ),
            'field' => 'name',
        ),
    ),
),

The attached patch contains this restructuring. Notes:

  • Complete backward compatibility. Query syntax does not change, nor does the SQL generated by the class. (With the exception of whitespace: I added indentation to make the nesting clearer.)
  • Unit tests. There are a few nesting-specific unit tests included. I've put them in a separate file (tests/term/query-nested.php) so that they'd apply cleanly. The patch also passes my extended unit tests, described here: #29718
  • Some modifications to WP_Query are included. WP_Query does a couple of pretty hackish checks of tax_query when filling in legacy query vars. Now that the tax_query can be nested, these hackish checks are no longer reliable. In WP_Tax_Query, during the sanitization of the query passed to the class, I generate a flat array of queried_terms, and then use that instead in WP_Query. IMO, the result is much cleaner code in WP_Query, and it also fixes a couple of odd bugs in the previous backward compatibility code. See https://core.trac.wordpress.org/ticket/29718#comment:3 for more details.
  • Aside from the recursion stuff, the internal SQL generation logic of WP_Tax_Query hasn't been touched.
  • Did I mention that all the unit tests pass? #29718

Attachments (2)

29738.patch (20.3 KB) - added by boonebgorges 5 years ago.
29738.2.patch (26.2 KB) - added by boonebgorges 5 years ago.

Download all attachments as: .zip

Change History (12)

@boonebgorges
5 years ago

This ticket was mentioned in IRC in #wordpress-dev by boonebgorges. View the logs.


5 years ago

This ticket was mentioned in IRC in #wordpress-dev by boonebgorges. View the logs.


5 years ago

#3 @boonebgorges
5 years ago

  • Milestone changed from Awaiting Review to 4.1
  • Owner set to boonebgorges
  • Status changed from new to assigned

#4 @boonebgorges
5 years ago

  • Keywords has-patch added
  • Status changed from assigned to accepted

29738.2.patch is a refresh that does the following:

  • Greater parity with WP_Meta_Query [29887]:
    • Documentation format is now parallel
    • sanitize_query() mirrors more closely in terms of internal logic and variable naming
    • Methods have been reordered to match
    • get_sql_clauses() and get_sql_for_query() are now duplicates of their brethren in WP_Meta_Query
  • Improved documentation throughout the patch
  • Moved the new unit tests to their proper home (for now - once this is all in place, I'd like to think about reorganizing)

#5 @DrewAPicture
5 years ago

The docs in 29738.2.patch look fabutastic.

#6 @boonebgorges
5 years ago

In 29891:

Introduce support for nested queries in WP_Tax_Query.

Previously, tax query arguments could be joined by a single AND or OR relation.
Now, these queries can be arbitrarily nested, allowing clauses to be linked
together with multiple relations.

In a few places, WP_Query runs through a list of clauses in a tax_query in order
to set certain query vars for backward compatibility. The necessary changes have
been made to WP_Query to support this feature with the new complex structure of
tax_query. Unit tests are included for these backward compatibility fixes.

Unit tests for the new nesting syntax are included.

Props boonebgorges.
Fixes #29718. See #29738.

#7 @boonebgorges
5 years ago

In 29901:

Support nested tax query syntax in redirect_canonical().

The proper place to look for a list of queried terms is in the flat
queried_terms array, not in tax_query->queries.

See #29738.

#8 @boonebgorges
5 years ago

In 29931:

Remove invalid continue calls from WP_Tax_Query::get_sql_for_clause().

This was leftover code from the previous implementation, which used a foreach()
loop. See [29901].

Props nofearinc.
See #29738, #29718.

#9 @boonebgorges
5 years ago

  • Resolution set to fixed
  • Status changed from accepted to closed

We're golden here.

#10 @boonebgorges
4 years ago

In 30771:

In WP_Query::get_queried_object(), use the new format for referencing tax query clauses.

queried_terms, rather than queries, is the tax_query property where a flat
index of terms is stored.

See [29901] for a similar fix in redirect_canonical(). See #29738.

Props dd32.
Fixes #30623.

Note: See TracTickets for help on using tickets.