Meta-value query

A little long-winded but trying to explain clearly 🙂

I am delving into the code of my new theme and am not familiar with this type of data storing/pulling – can someone help me understand what is going on here please:

I am trying to create a page which outputs only the posts which have a ‘coupon’ attached to it. ‘Coupon’ is stored as a meta_key against a post.

It’s meta_value is stored as an array which looks like this (output using print_r):

a:7:{s:9:”highlight”;s:14:”Test Highlight”;s:5:”title”;s:12:”50% off food”;s:11:”description”;s:16:”Test description”;s:4:”code”;s:7:”1524521″;s:11:”popup_image”;s:4:”4548″;s:17:”popup_description”;s:17:”Popup description”;s:11:”redirect_to”;s:0:””;}

I want the custom page to output:

  • Post title
  • Post content
  • Post image
  • Coupon details

I can output the first three by running a wp_query:

$q = new WP_Query(array(
    'post_type' => 'listing',
    'posts_per_page' => 5,
    'meta_key' => 'wc_coupon',
    'meta_value' => ' ',
    'meta_compare' => '!='
));

However, I cannot find a way to split out the meta_value array to display the individual elements per post.


The theme handles this in a way I don’t understand, perhaps someone can explain it to me.

Coupon.php is a partial file which is used when displaying any single post which looks like this:

global $post, $Args;
use ListingTools\Framework\Helpers\GetSettings;

$aCoupon = GetSettings::getPostMeta($post->ID, 'coupon');
if ( empty($aCoupon) || ( empty($aCoupon['code']) && empty($aCoupon['redirect_to']) ) ){
    return '';
}
?>

<div class="content-box_module__333d9">
    <div class="content-box_body__3tSRB">
        <?php echo do_shortcode('[get_coupon highlight="'.esc_attr($aCoupon['highlight']).'" title="'.esc_attr($aCoupon['title']).'" description="'.esc_attr($aCoupon['description']).'" code="'.esc_attr($aCoupon['code']).'" redirect_to="'.esc_attr($aCoupon['redirect_to']).'"]'); ?>
    </div>
</div>

So I don’t understand how the “use” code works at the top in the variables section.

I also don’t understand how the
$aCoupon = GetSettings::getPostMeta($post->ID, 'coupon'); is working, but they can use this to display the individual parts of the coupon array as you can see later in the code:

echo do_shortcode('[get_coupon highlight="'.esc_attr($aCoupon['highlight'])

Hopefully that was follow-able 🙂

Thanks in advance.

2 Answers
2

The string you are outputting using print_r() is what is known as a serialized string. When WordPress stores an array of values in 1 custom field, it compresses the array into this string using a function called serialize()

What you want to do is to unserialize the string, and then you can access each “associated index” in the array.

Usually get_post_meta() unserializes the string for you, but it looks like the custom function GetSettings::getPostMeta() does not. In this case we can run maybe_unserialize() which will convert it into a usable array if it is able to.

Then we can simply loop through the array, outputting what you need to.

$aCoupon = GetSettings::getPostMeta($post->ID, 'coupon');
$aCoupon = maybe_unserialze( $aCoupon );
if ( empty( $aCoupon ) ){
    foreach ( $aCoupon as $key => $value ) {
        echo '<div><span class="label">' . $key . '</span> ' . $value . '</div>';
    }
}

Based on your example, it would output something like this.

<div><span class="label">highlight</span> Test Highlight</div>
<div><span class="label">title</span> 50% off food</div>
<div><span class="label">description</span> Test description</div>
<div><span class="label">code</span> 1524521</div>
<div><span class="label">popup_image</span> 4548</div>
<div><span class="label">popup_description</span> Popup description</div>
<div><span class="label">redirect_to</span> </div>

Or if you want to access 1 value directly.

$aCoupon = GetSettings::getPostMeta($post->ID, 'coupon');
$aCoupon = maybe_unserialze( $aCoupon );
if ( empty( $aCoupon ) ){
    //If the title is set, and is not empty, output it.
    if ( isset( $aCoupon['title'] ) && '' !== $aCoupon['title'] ) {
        echo '<div><span class="label">Title</span> ' . $aCoupon['title'] . '</div>';
    }
}

EDIT by @Shaun21uk – I got it to work making some minor changes (full code below). For whatever reason the $aCoupon = GetSettings::getPostMeta($coupon_id, 'coupon'); was breaking the function – I still would like to know how to tap into the theme’s way of handling data.

Your shortcode function should look something like this:

add_shortcode( 'qg_shortcode', 'qg_shortcode' );
function qg_shortcode() {

    $q = new WP_Query(array(
        'post_type' => 'listing',
        'posts_per_page' => 5,
        'meta_key' => 'wc_coupon',
        'meta_value' => ' ',
        'meta_compare' => '!='
    ));

    if ( $q->have_posts() ) :
        while ( $q->have_posts() ) : $q->the_post();

            echo '<h2 class="text-center"><a href="' . get_permalink() . '">';
                the_title();
            echo '</a></h2>';

            the_content();

            // Get the ID of the attached coupon.
            $coupon_id = get_post_meta( get_the_ID(), 'wc_coupon', true );

            // Get the coupon details from the coupon using the coupons ID.
        $aCoupon = maybe_unserialize( $coupon_id );

            // This checks if the coupon details are NOT empty, if that is true, then output the info.
            if ( ! empty( $aCoupon ) ) {

                // If the title is set, and is not empty, output it.
                if ( isset( $aCoupon['title'] ) && '' !== $aCoupon['title'] ) {
                    echo '<div><span class="label">Title</span> ' . $aCoupon['title'] . '</div>';
                }
            }

            echo'<div class="offer-button">';
            echo'<a href="' . get_permalink() . '" class="offer-button-text">Claim this offer!</a>';
            echo'</div>';
        endwhile;
        wp_reset_postdata();
    endif;
}

Leave a Comment