-
Notifications
You must be signed in to change notification settings - Fork 10.8k
Add multi-field search search_fields
parameter to products REST API
#59450
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add multi-field search search_fields
parameter to products REST API
#59450
Conversation
… parameter Introduces a flexible search mechanism for the v3 products endpoint by adding a `search_fields` parameter. Previously, searching was limited to predefined parameter combinations like `search_name_or_sku`. This change allows clients to specify exactly which fields to search—`name`, `sku`, or `global_unique_id`—using the `search_fields` parameter in combination with the `search` parameter. Key features: - All search tokens must match within the same field (e.g., searching for "blue shirt" will not match a product named "blue" with a SKU of "shirt"). - The `search_fields` parameter takes precedence over all other search-related parameters to ensure predictable results. - Full backward compatibility is maintained for existing search parameters. Includes a comprehensive suite of PHPUnit tests to validate the new functionality, including parameter precedence, same-field matching logic, and security against invalid field names.
Refactored the build_dynamic_search_clauses method in the products REST API controller to use a mapping array for resolving API field names to database columns, replacing the previous switch statement. This change makes it easier to extend the search functionality in the future and reduces code repetition.
📝 WalkthroughWalkthroughThe changes introduce a new Changes
Sequence Diagram(s)sequenceDiagram
participant Client
participant REST_API
participant ProductsController
participant Database
Client->>REST_API: GET /wc/v3/products?search=foo&search_fields=name,sku
REST_API->>ProductsController: prepare_objects_query(request)
ProductsController->>ProductsController: Validate and tokenize search_fields
ProductsController->>ProductsController: Build dynamic SQL WHERE clause
ProductsController->>Database: Query products with dynamic search criteria
Database-->>ProductsController: Return matching products
ProductsController-->>REST_API: Return filtered products
REST_API-->>Client: Respond with product data
sequenceDiagram
participant Client
participant REST_API
participant ProductsController
Client->>REST_API: GET /wc/v3/products?search=foo&search_fields=invalid
REST_API->>ProductsController: prepare_objects_query(request)
ProductsController->>ProductsController: Validate search_fields
ProductsController-->>REST_API: Return 400 error (invalid field)
REST_API-->>Client: Respond with error
📜 Recent review detailsConfiguration used: .coderabbit.yml 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (26)
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
SupportNeed help? Create a ticket on our support page for assistance with any issues or questions. Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
Documentation and Community
|
Test using WordPress PlaygroundThe changes in this pull request can be previewed and tested using a WordPress Playground instance. Test this pull request with WordPress Playground. Note that this URL is valid for 30 days from when this comment was last updated. You can update it by closing/reopening the PR or pushing a new commit. |
Testing GuidelinesHi @jorgeatorres , Apart from reviewing the code changes, please make sure to review the testing instructions (Guide) and verify that relevant tests (E2E, Unit, Integration, etc.) have been added or updated as needed. Reminder: PR reviewers are required to document testing performed. This includes:
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @staskus!
This is looking really good and tests as described. I left some feedback but nothing too serious.
I'm wondering whether search_fields
is the best name for the argument, not because it is incorrect, but because it could give the impression that it can be used to search by any product field which is not the case. Even if that were possible, the search heuristics for these specific name/SKU/GTIN searches are not necessarily what others might expect for a generic search field. Not sure if something like sku_search_fields
could work (even if SKU
is not the only field involved).
If we can't find a different arg name, that's probably fine, though. Just curious if you have other ideas.
In any case, I think this implementation is way better than adding new args for every possible combination of fields. Let me know what you think!
...ins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-products-controller.php
Outdated
Show resolved
Hide resolved
...ins/woocommerce/includes/rest-api/Controllers/Version3/class-wc-rest-products-controller.php
Outdated
Show resolved
Hide resolved
The REST API framework already handles validation of search_fields against the allowed enum values, making the manual array_intersect validation redundant. This simplifies the code by removing the duplicate validation logic and relying on the framework's built-in validation.
Only include 'sku' in the search_fields enum when wc_product_sku_enabled() returns true. This ensures consistency with other SKU-related functionality and prevents SKU searches when the SKU feature is disabled.
5160c66
to
3e458c7
Compare
@jorgeatorres, thanks for the review! I made improvements based on your comments. Regarding the naming, it's complicated. I agree that
Yes, that's an extra level of complexity. It's quite hard to tell whether the search tokens should or shouldn't be split between the SKU/Global Identifier/Name. We assume that you're looking for one of those and not aiming to look for something among multiple fields. Probably |
@jorgeatorres Another idea proposed by the team is to keep As I understood, What would be your take on this idea? |
Thanks for making the changes and for giving this a bit more thought @staskus! Things are looking good to me.
I think this makes sense. We don't have to change the search logic now. Maybe in the future we can offer different "matching" heuristics, but as long as we document that by using If it's too much trouble, we can go with what we have and iterate later on. Just let me know what you'd like to do, before I do one final round of testing on the PR. |
…-field matching - Add description and short_description fields to search_fields parameter - Implement cross-field matching behavior (tokens match across any specified field) - Update schema enum to include new content fields - Add comprehensive test coverage for new functionality - Maintain WordPress native search compatibility - Fix code formatting and alignment issues
Remove array_map('esc_sql', ...) calls in prepare_objects_query method that were causing double-escaping of search tokens before passing to $wpdb->prepare(). This was preventing searches with special characters like apostrophes from working correctly.
@jorgeatorres, thanks again for all the help.
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hey @staskus!
Thanks for making the changes and for all your work on this and for submitting an update to the REST docs as well.
This looks good to me and I'm pre-approving with just one tiny (optional) feedback.
As discussed, this does search the way matching works. Previously searching for, say, scarf+987
using search_name_or_sku
wouldn't have returned a match for a product with name "Scarf" and SKU "SKU987" but now it does. As long as this behavior is not problematic for you on the POS side, I'm good with it.
Let me know what you think.
} | ||
|
||
$db_column = $column_map[ $field ]; | ||
$field_token_clauses[] = '(' . $db_column . ' LIKE ' . $wpdb->prepare( '%s', $like_search ) . ')'; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe something along these lines would be a tiny bit easier to grasp?
$field_token_clauses[] = '(' . $db_column . ' LIKE ' . $wpdb->prepare( '%s', $like_search ) . ')'; | |
$field_token_clauses[] = $wpdb->prepare( "({$db_column} LIKE %s)", $like_search ); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks, definitely reads better 👍
@jorgeatorres thank you for the review! Yes, the change in the search behavior is not problematic. Should I know anything about deployment or merging is enough? |
Merging should be enough after the approval. |
Refactor SQL query construction in build_dynamic_search_clauses() to use more common WordPress coding patterns. Replace string concatenation approach with wpdb::prepare() for the entire SQL clause.
…ce db_column is whitelisted
Hi @staskus! Your PR contains REST API changes. Please consider updating the REST API documentation if your changes affect the public API. Changed API files:
|
Original PR: #59241
RFC: pfZP8i-cI-p2 -worth checking it first
WOOMOB-713
Documentation PR: woocommerce/woocommerce-rest-api-docs#271
Changes proposed in this Pull Request:
This pull request introduces a new, flexible search mechanism to the WooCommerce Products REST API (
GET /wc/v3/products
). Instead of expandingsearch_name_or_sku
parameter even further to supportglobal_unique_id
, this implementation uses a combination of the existingsearch
parameter and a newsearch_fields
array parameter. This allows clients to specify which fields to search (name
,sku
,global_unique_id
,description
,short_description
) and supports cross-field matching logic.The search behavior has been updated to support cross-field matching same way as a
search=
parameter:search
argument is treated as a collection of space-separated tokens.Examples:
blue shirt
withsearch_fields=name
will match a product with the name "Casual Blue Shirt" because both tokens exist in the same field (name), but not "Red Shirt".scarf 987
withsearch_fields=name,global_unique_id
will match a product with name "Premium Wool Scarf" and GTIN "9876543210" because the tokens can be found across the specified fields.quality professionals
withsearch_fields=description,short_description
will match a product where "quality" appears in the short description and "professionals" appears in the description.This new approach takes precedence over all other search-related parameters:
search_name_or_sku
,search_sku
, andsku
. Ifsearch_fields
is present in a request, all others will be ignored for search logic.This functionality is added to the v3 REST API products endpoint only.
How to test the changes in this Pull Request:
Create products with the following details:
Premium Wool Scarf
SCARF-W-PREM
9876543210
Essential tool for professionals.
High quality craftsmanship.
Casual Blue Shirt
SHIRT-B-CASUAL
1234567890
A premium quality winter scarf made from wool.
Perfect for summer activities.
Red Cotton Tee
TEE-C-RED
0000000000
Create an application password for your WordPress user in your user profile page from the WP admin area.
Test same-field matching: Perform the following request to find "Product B" by searching for tokens that exist in the same field (name).
You should get one result: the "Casual Blue Shirt" product.
Test individual field searches: Verify that single tokens work across all fields.
Test cross-field matching: Confirm that tokens can match across different specified fields.
Verify precedence: Confirm that
search_fields
andsearch
override all other search parameters.Verify regression: Confirm that the older search parameters continue to work as expected when the new one is not present.
The following returns the "Casual Blue Shirt" product:
The following returns the "Red Cotton Tee" product:
The following returns the "Premium Wool Scarf" product:
Changelog entry
Changelog Entry Details
Significance
Type
Message
Add support for dynamic multi-field product search via
search_fields
andsearch
parameters in the Products REST API endpoint with cross-field matching capability.