WordPress REST API中如何自定义元值验证?
Great question! The built-in schema validation in WordPress REST API can feel restrictive at times, but there are a few more workarounds beyond the two you’ve outlined. Let’s dive into them, plus expand on that pattern trick you mentioned—it’s more useful than you might think.
1. Use register_rest_field Instead of register_meta
Instead of relying on the default post controller’s auto-generated schema, you can create a custom REST field directly with register_rest_field. This gives you full control over validation via the update_callback parameter, where you can implement any custom logic you need.
Example code:
register_rest_field( 'your_custom_post_type', 'your_meta_key', array( 'get_callback' => function( $post ) { return get_post_meta( $post['id'], 'your_meta_key', true ); }, 'update_callback' => function( $value, $post ) { // Your custom validation logic here if ( ! preg_match( '/^[A-Z0-9]{8}$/', $value ) ) { return new WP_Error( 'invalid_meta_value', 'Your meta value must be 8 uppercase alphanumeric characters.', array( 'status' => 400 ) ); } // If validation passes, update the meta update_post_meta( $post->ID, 'your_meta_key', $value ); return true; }, 'schema' => array( 'type' => 'string', 'description' => 'Custom meta field with custom validation', ), ) );
This approach lets you bypass the default schema validation entirely for that specific field and handle things exactly how you want.
2. Hook into rest_request_before_callbacks
You can intercept the entire REST request before the controller callbacks run using the rest_request_before_callbacks filter. This is great if you need to validate multiple fields or add cross-field validation logic.
Example:
add_filter( 'rest_request_before_callbacks', function( $response, $handler, $request ) { // Check if we're dealing with the correct endpoint and post type if ( $request->get_route() === '/wp/v2/your_custom_post_type/(?P<id>[\d]+)' && $request->get_method() === 'POST' ) { $meta_value = $request->get_param( 'your_meta_key' ); // Custom validation if ( empty( $meta_value ) || strlen( $meta_value ) < 5 ) { return new WP_Error( 'invalid_meta', 'Meta value must be at least 5 characters long.', array( 'status' => 400 ) ); } } return $response; }, 10, 3 );
This gives you a high-level way to validate data before it reaches the default controller’s logic.
3. Extend rest_validate_value_from_schema with a Filter
WordPress provides the rest_validate_value_from_schema filter, which lets you override or extend the default validation logic for any schema value. You can use this to add custom validation rules without rewriting entire controller methods.
For example, if you want to add a custom validation rule for a specific meta field’s schema:
add_filter( 'rest_validate_value_from_schema', function( $is_valid, $value, $schema, $param ) { // Check if this is our target meta field and schema has a custom rule if ( $param === 'your_meta_key' && isset( $schema['custom_validation'] ) ) { switch ( $schema['custom_validation'] ) { case 'even_number': $is_valid = is_numeric( $value ) && $value % 2 === 0; if ( ! $is_valid ) { rest_add_validation_error( $param, 'Value must be an even number.' ); } break; } } return $is_valid; }, 10, 4 );
Then when registering your meta, add the custom flag to the schema:
register_meta( 'post', 'your_meta_key', array( 'type' => 'integer', 'single' => true, 'show_in_rest' => array( 'schema' => array( 'type' => 'integer', 'custom_validation' => 'even_number', // Custom flag ), ), ) );
This way, you can keep using register_meta but inject custom validation logic into the existing pipeline.
Don’t Sleep on the pattern Attribute
You mentioned the pattern property for string types, and it’s worth highlighting how powerful this can be for common validation needs. For example, validating a US zip code or a specific date format:
register_meta( 'post', 'custom_date', array( 'type' => 'string', 'single' => true, 'show_in_rest' => array( 'schema' => array( 'type' => 'string', 'pattern' => '^\d{4}-\d{2}-\d{2}$', // YYYY-MM-DD format 'description' => 'Date in YYYY-MM-DD format', ), ), ) );
This uses JSON Schema’s pattern keyword, which supports full regular expressions—perfect for simple to moderately complex string validation without writing custom PHP.
Which Approach Should You Choose?
- Use
register_rest_fieldif you want full control over the field’s behavior (validation, retrieval, updates). - Use
rest_request_before_callbacksfor cross-field validation or validating multiple fields at once. - Use
rest_validate_value_from_schemaif you want to extend the default schema validation while keepingregister_meta’s convenience. - Stick with
patternfor straightforward string format validation—it’s the simplest solution when it fits your needs.
内容的提问来源于stack exchange,提问作者Josef Wittmann

