Skip to content

Instantly share code, notes, and snippets.

@rmpel
Last active September 4, 2021 13:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save rmpel/8b103a5dd360a5000e4d4f9aa22e2787 to your computer and use it in GitHub Desktop.
Save rmpel/8b103a5dd360a5000e4d4f9aa22e2787 to your computer and use it in GitHub Desktop.
Get WordPress Post Meta by RegExp, a regular expression variant of get_post_meta
<?php
/**
* Retrieve post meta field for a post, by Regular Expression match on the key.
*
* @since 0.0.1
*
* @param int $post_id Post ID.
* @param string $regexp The regexp to match the meta key against. One capture-group
* allowed for key-ing the results. Full meta_key is used if no
* capture-groups in the expression
* @param bool $single_sub_values Optional. Whether to return an array of single values. Default false.
* @return WP_Error|array(mixed) Will be an array with either scalars or arrays based on $single_sub_values.
* contains the individual meta_value results of get_post_meta.
* Will be WP_Error in case the regular expression fails to validate.
*/
function get_post_meta_regexp($post_id, $regexp, $single_sub_values = false) {
global $wpdb;
if (preg_match($regexp, null) === false) {
return new WP_Error('regexp_invalid', 'Please supply a valid regexp, the current expression is missing boundaries', array($regexp));
}
$regexp_boundary = substr($regexp, 0, 1);
$regexp_boundary_end = strrpos($regexp, $regexp_boundary); // position of closing boundary
$regexp_options = substr($regexp, $regexp_boundary_end + 1); // just the part between the boundaries
$trimmed_regexp = substr($regexp, 1, $regexp_boundary_end - 1); // just the part between the boundaries
// notes:
// MYSQL regexp is always case insensitive, so in case of no /i flag, MYSQL might report too many rows, these are then filtered by PHP,
// flags m and s are for multi-line matching. meta_keys are never multiline, do, we can ignore those
// flag x modified the way whitepsace is handled, sinde meta_keys cannot have whitespace, we ignore those too
// flag e (eval) makes no sense whatsoever in this context, do we ignore that as well.
$regexp_options = (false !== strpos($regexp_options, 'i')) ? 'i' : '';
$regexp = $regexp_boundary . $trimmed_regexp . $regexp_boundary . $regexp_options;
$meta_keys = $wpdb->get_col( $wpdb->prepare("SELECT meta_key FROM {$wpdb->postmeta} WHERE meta_key REGEXP %s AND post_id = %d", $trimmed_regexp, $post_id ) );
$meta = array();
foreach ($meta_keys as $key) {
if (preg_match($regexp, $key, $m)) {
$meta[ isset($m[1]) ? $m[1] : $m[0] ] = get_post_meta($post_id, $m[0], $single_sub_values);
}
}
return $meta;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment