2

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

1

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;
}
7
  • Warwick, I couldn't fit my response in a comment so had to post my response as an answer. Sorry if that is wrong but I am new to the site and couldn't see another way.
    – Shaun21uk
    May 13, 2019 at 21:05
  • @Shaun21uk you should rather edit the original question and update that, instead of adding an answer. ;-)
    – Warwick
    May 13, 2019 at 21:55
  • @Shaun21uk have a look at my answer now, I have added in a modified function to the bottom, which will hopefully have fixed your issue.
    – Warwick
    May 13, 2019 at 22:09
  • @Shaun21uk, I have updated it again, I had to switch the wc_coupon and coupon around.
    – Warwick
    May 13, 2019 at 22:12
  • The output is still not looping any more and only printing the the_title and the_content. Seems the loop is broken somewhere and not even processing the [coupon] code?
    – Shaun21uk
    May 13, 2019 at 22:17
0

Warwick, thank you so much for taking the time to go through this.

My full code now looks 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();

            $aCoupon = GetSettings::getPostMeta( get_the_ID(), 'wc_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>';
                }
            }

            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;
}
  • This is now only outputting one post and doesn't seem to be looping. Before I added your code it successfully displayed the title and link for two (all) posts containing a coupon. The one item it is displaying does indeed have a coupon though.
  • Your code is still not outputting the $aCoupon['title'], it's just blank.
  • It's worth mentioning that the meta_key for some reason is 'wc_coupon' which is why I use it in the wp_query filter, yet in the coupon.php code as shown, they clearly use just 'coupon'.

I really thought you had cracked it here! Perhaps I have the code set up wrong somewhere above as I am pretty new to php but trying to learn :)

4
  • w.r.t "outputting one post". Does the offer button for the first post show? If not there could be an error in the code stopping it from looping.
    – Warwick
    May 13, 2019 at 22:02
  • w.r.t "not outputting the $aCoupon['title']". The if statement, that checks for a title was set incorrectly. It should have had a ! in it. e.g ! empty( $aCoupon )
    – Warwick
    May 13, 2019 at 22:04
  • Actually no, the button isn't showing....I didn't spot that
    – Shaun21uk
    May 13, 2019 at 22:05
  • Lastly, the "coupons" ID is stored on the post in a custom field called wc_coupon. Once we have that ID, we can call the custom field coupon using the coupons ID to get the correct info. Basically the post just stores the ID of the coupon its linking to. We need to get the info from there.
    – Warwick
    May 13, 2019 at 22:07

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.