user2018888 user2018888 -3 years ago 108
PHP Question

Accessing product meta data from WooComerce in email-order-items.php

I am having a real difficulty in trying to filter some data that is going out into an e-mail after the customer places an order. The issue is that every line item is showing the shipping information (pickup location) even though it is the same as the final pickup location at the end of the order.

I have been able to look at the item_meta data which is given, but I am unsure of how to filter it to essentially remove the array portion which has the "Pickup Location' meta key and then still print the rest. Here is the area of the email-order-items.php file where the data is being generated (it is not custom...this is standard for WooCommerce):

if ( ! empty( $item_meta->meta ) ) {

echo '<br/><small>' . nl2br( $item_meta->display( true, true, '_', "\n" ) ) . '</small>';
}


Here is what I am able to see by simply doing:

foreach ($item_meta as $value) {
print_r($value);
}


Result:


Cookie → Cookie (One-Time)Array ( [_qty] => Array ( [0] => 1 )
[_tax_class] => Array ( [0] => ) [_product_id] => Array ( [0] => 5807
) [_variation_id] => Array ( [0] => 0 ) [_line_subtotal] => Array (
[0] => 2.5 ) [_line_total] => Array ( [0] => 0 ) [_line_subtotal_tax]
=> Array ( [0] => 0.15 ) [_line_tax] => Array ( [0] => 0 ) [_line_tax_data] => Array ( [0] =>
a:2:{s:5:"total";a:1:{i:1;s:1:"0";}s:8:"subtotal";a:1:{i:1;s:4:"0.15";}}
) [_shipping_item_id] => Array ( [0] => 28795 ) [Pickup Location] =>
Array ( [0] => PICKUP ADDRESS HERE, City, State, Zip ) )
WC_Product_Simple Object ( [id] => 5807 [post] => WP_Post Object (
[ID] => 5807 [post_author] => 596 [post_date] => 2016-07-23 17:55:10
[post_date_gmt] => 2016-07-23 21:55:10 [post_content] => [post_title]
=> Power Protein Cookie (One-Time) [post_excerpt] => [post_status] => publish [comment_status] => closed [ping_status] => closed
[post_password] => [post_name] => power-protein-cookie-one-time
[to_ping] => [pinged] => [post_modified] => 2016-07-23 19:39:18
[post_modified_gmt] => 2016-07-23 23:39:18 [post_content_filtered] =>
[post_parent] => 5806 [menu_order] => 1 [post_type] => product
[post_mime_type] => [comment_count] => 0 [filter] => raw )
[product_type] => simple [shipping_class:protected] =>
[shipping_class_id:protected] => 0 ) ]


How can I iterate through the item_meta data, unset (I think is the way to do it) the Pickup Location data and then still display the rest?

UPDATE: I went in and tried the following code:

if(is_array($item_meta->meta))
{
foreach($item_meta->meta as $key => $value)
{
echo $key . '<br />' . $value;
}
}


That gave me the following:

Cookie → Cookie (One-Time)_qty
Array_tax_class
Array_product_id
Array_variation_id
Array_line_subtotal
Array_line_total
Array_line_subtotal_tax
Array_line_tax
Array_line_tax_data
Array_shipping_item_id
ArrayPickup Location
Array

I feel like I am fairly close but not understanding the structure of what is inside of item_meta very well...any help would be appreciated.

Answer Source

@update 3 - Manipulating a php object (untested):

This is my last try:

// Cloning the base object:
$custom_meta = clone $item_meta;

// OR
// $custom_meta = new stdClass();
// $custom_meta = $item_meta;

// saving the custom array in a temporary variable
$length = sizeof($custom_meta->meta) - 1;
$meta_temp = array_slice( $custom_meta->meta, 0, $length );

// Removing the property (array) from the object
unset($custom_meta->meta);

// Recreating the same property and setting the changed array Key/Values to it
$custom_meta->meta = $meta_temp;

// Displaying your custom object (for test)
echo print_r($custom_meta);

// Using it
$custom_meta->display();

Based on this thread: Is it possible to delete an object's property in PHP?


@update 2 - Alternatives:

1) Instead using unset() function use array_pop() function (as we have to remove the last item in the array):

$item_meta_meta_arr = array_pop( $item_meta->meta );

// you will use now $item_meta_meta_arr
print_r( $item_meta_meta_arr );

2) Instead using unset() function use array_slice() function (as we have to remove the last item in the array):

$length = sizeof($item_meta->meta) - 1;
$item_meta_meta_arr = array_slice( $item_meta->meta, 0, $length );

// you will use now $item_meta_meta_arr
print_r( $item_meta_meta_arr );

But you will not use $item_meta->meta as $item_meta is an object and it's not possible to remove the data from $item_meta->meta directly


@Update (related to the author comments)

Removing a key / value in an array, where the key is Pickup Location.

First we check that it's the right key / value we want to remove

echo $item_meta->meta['Pickup Location'] // should display right "Pickup Location" value.

Once you get the right value, you can use unset() php function. But first we are going to pass our array (keys/values) to a new array. This is the process:

// Copying the data to a new array.
$item_meta_meta_arr = $item_meta->meta;
unset($item_meta_meta_arr['Pickup Location']);

// Checking that it has correctly be unset from the array:
foreach($item_meta_meta_arr as $key => $value)
{
    echo 'Key: '. $key . ' / Value: '  . $value . '<br />';
}

References: - Removing key => value pairs from an array, but its not removing them


original answer

To iterate through multiple arrays / objects you could use this (to see what you get for testing):

if(!is_string($item_meta->meta) )
{
    foreach($item_meta->meta as $key1 => $value1)
    {
        if (is_string($value1)) echo $key1 . $value1 . ' (level 1 - string)<br />';
        elseif ( is_array($value1) || is_object($value1) )
        {
            echo $key1 . ' (level 1 - array)<br />';
            foreach($value1 as $key2 => $value2) {
            {
                if (is_string($value2)) echo $key2 . $value2 . ' (level 2 - string)<br />';
                elseif ( is_array($value2) || is_object($value2) )
                {
                    echo $key2 . ' (level 2 - array)<br />';
                    foreach($value2 as $key3 => $value3) {
                    {
                        if (is_string($value3)) echo $key3 . $value3 . ' (level 3 - string)<br />';
                    }
                } 
            } 
        } 
    }
}

To see the structured data instead using print_r() function, you can use var_dump() function:

echo var_dump( $item_meta );

// Or

foreach ($item_meta as $value)
     echo var_dump( $value );

// Or

foreach ($item_meta->meta as $value)
     echo var_dump( $value );
Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download