How do I get order nested meta data in WooCommerce 3 - php

We have installed another plugin for WooCommerce called Booster Plus for WooCommerce and this plugin can modify the checkout page by paying for an order by invoice number.
I am customizing our thank you page by displaying the invoice number too. Currently, I am not able to do that because I don't know how can I properly get the value of the nested $order->get_data() result.
<?php
$order_data = $order->get_data();
print_r($order_data);
?>
The result of order_data above looks like below:
(
[id] => 7403
[discount_total] => 0
[discount_tax] => 0
[shipping_total] => 0.00
[shipping_tax] => 0
[cart_tax] => 2.47
[total] => 21.47
[total_tax] => 2.47
[customer_id] => 20
[order_key] => wc_order_8pt3q7T79
[billing] => Array
(
[first_name] => John
[last_name] => Done
[company] => g2x
[address_1] => 3134 James Street
[address_2] =>
[city] => Moose Factory
[state] => ON
[postcode] => P0L 1W0
[country] => CA
[email] => testjohndoe123#gmail.com
[phone] => 705-658-2112
)
[cart_hash] => 087347d19dff4677dc8kaeb2b2c653c6
[number] => 7403
[meta_data] => Array
(
[0] => WC_Meta_Data Object
(
[current_data:protected] => Array
(
[id] => 102652
[key] => mailchimp_woocommerce_campaign_id
[value] =>
)
[data:protected] => Array
(
[id] => 102652
[key] => mailchimp_woocommerce_campaign_id
[value] =>
)
)
[1] => WC_Meta_Data Object
[2] => WC_Meta_Data Object
[3] => WC_Meta_Data Object
[4] => WC_Meta_Data Object
[5] => WC_Meta_Data Object
(
[current_data:protected] => Array
(
[id] => 102694
[key] => _wcj_custom_payment_gateway_input_fields
[value] => Array
(
[pay_by_po] => 123456789
)
)
[data:protected] => Array
(
[id] => 102694
[key] => _wcj_custom_payment_gateway_input_fields
[value] => Array
(
[pay_by_po] => 123456789
)
)
)
[coupon_lines] => Array
()
)
Do you know how can I get the value of [pay_by_po] which is 123456789? Any help is greatly appreciated. Thank you.

You can get and unprotect this nested meta data using WC_data method get_meta_data(), which gives an array of WC_Meta_Data Objects:
$meta_data = $order->get_meta_data();
print_r($order_data);
Then on each WC_Meta_Data Object, you can use WC_Meta_Data available methods like get_data() that gives an unprotected data array:
foreach( $order->get_meta_data() as $meta_data_obj ) {
$meta_data_array = meta_data_obj->get_data();
print_r($meta_data_array);
$meta_key = $meta_data_array['key']; // The meta key
$meta_value = $meta_data_array['value']; // The meta value
}
You can also get directly any nested meta data from the order using WC_Data method get_meta() from aspecific meta key as follow:
$meta_value = $order->get_meta('_wcj_custom_payment_gateway_input_fields');
print_r($meta_value);
Note This nested meta data exist since WooCommerce version 3.
About Abstract WC_Data Class
Its Implemented by classes using the same CRUD(s) pattern.
Direct known subclasses:
WC_Abstract_Legacy_Order, WC_Abstract_Legacy_Product, WC_Customer_Download, WC_Customer_Download_Log, WC_Legacy_Coupon, WC_Legacy_Customer, WC_Legacy_Payment_Token, WC_Legacy_Shipping_Zone, WC_Legacy_Webhook, WC_Order_Item
Indirect known subclasses:
WC_Abstract_Order, WC_Coupon, WC_Payment_Token, WC_Payment_Token_CC, WC_Payment_Token_ECheck, WC_Product, WC_Product_External, WC_Product_Grouped, WC_Product_Simple, WC_Product_Variable, WC_Product_Variation, WC_Shipping_Zone, WC_Customer, WC_Webhook, WC_Order, WC_Order_Item_Coupon, WC_Order_Item_Fee, WC_Order_Item_Product, WC_Order_Item_Shipping, WC_Order_Item_Tax, WC_Order_Refund
See: Developing using WooCommerce CRUD objects

Related

wordpress shortcode is picking full XML instead of a single line

I am trying to create a wordpress shortcode which returns the price of a book from an API.
Ideally, I would like to be able to create a shortcode with this format [currency_isbn13] but for the moment I'd be happy to just create a fixed shortcode for each book and currency.
After various attempts, I was able to put together the following php code, but it is not working as it should
function Price() {
$isbn13 = 9783899735215;
$url = 'https://api.bookdepository.com/search/lookup?isbn13='.$isbn13.'&clientId={redact}&authenticationKey={redact}&IP={redact}&currencies=GBP';
$sxml = simplexml_load_file($url);
print_r($sxml);
return $sxml->price;
}
add_shortcode('isbn13', 'Price');
I would expect the shortcode to return the price of the book, but I get the following:
How can I fix this? I'm sure it is very simple but can't figure it out
SimpleXMLElement Object ( [resultset] => SimpleXMLElement Object ( [status] => Success [results] => 1 [totalResults] => 1 [currentPage] => 1 [totalPages] => 1 ) [items] => SimpleXMLElement Object ( [item] => SimpleXMLElement Object ( [identifiers] => SimpleXMLElement Object ( [isbn13] => 9783899735215 ) [url] => https://www.bookdepository.com/Crocodile-Newts-Axel-Hernandez/9783899735215 [biblio] => SimpleXMLElement Object ( [title] => Crocodile Newts [format] => Hardback ) [availability] => Available - dispatched from the UK in 4 business days [pricing] => SimpleXMLElement Object ( [price] => SimpleXMLElement Object ( [#attributes] => Array ( [currency] => GBP ) [selling] => 50.27 ) ) [contributors] => SimpleXMLElement Object ( [contributor] => SimpleXMLElement Object ( [name] => Axel Hernandez [roleDescription] => By (author) [url] => https://www.bookdepository.com/author/Axel-Hernandez ) ) ) ) )
Looks as though you need to expand
return $sxml->price;
as your structure is more complex. Looks as though
return (string)$sxml->items->item->pricing->price->selling;
The cast to (string) makes the value easier to use elsewhere.

How can I merge two or more php objects?

I have 2 or more php objects that have the same sections. Each section has objects in it. I want to combine these objects together. Since each section has the same title I remove the title of the new object before merging them. My code isn't keeping the proper structure and is adding an unwanted level 'component' to the primary object. Feels like I am missing something obvious but I Can't figure out how to add the new object without the 'component' level.
Object 1 Example
stdClass Object(
[section_1] => stdClass Object
(
[title] => Production
[component_name_68] => stdClass Object
(
[title] => custom component title
[id] => 68
[type] => component_name_68
[subtotal] => 1127.50
[desc] => custom description
)
)
)
Object 2 Example
stdClass Object(
[section_2] => stdClass Object
(
[title] => Production
[component_name_69] => stdClass Object
(
[title] => custom component title2
[id] => 69
[type] => component_name_69
[subtotal] => 1985.50
[desc] => custom description2
)
)
)
Current Code
foreach($this->Details as $section1){
foreach($newinfo as $section2){
if($section1->title == $section2->title){
unset($section2->title);
$section1->{"component"} = $section2;
}
}
}
Current Result
stdClass Object(
[section_1] => stdClass Object
(
[title] => Production
[component_name_68] => stdClass Object
(
[title] => custom component title
[id] => 68
[type] => component_name_68
[subtotal] => 1127.50
[desc] => custom description
)
[component] => stdClass Object (
[component_name_69] => stdClass Object
(
[title] => custom component title2
[id] => 69
[type] => component_name_69
[subtotal] => 1985.50
[desc] => custom description2
)
)
)
Desired Result
stdClass Object(
[section_1] => stdClass Object
(
[title] => Production
[component_name_68] => stdClass Object
(
[title] => custom component title
[id] => 68
[type] => component_name_68
[subtotal] => 1127.50
[desc] => custom description
)
[component_name_69] => stdClass Object
(
[title] => custom component title2
[id] => 69
[type] => component_name_69
[subtotal] => 1985.50
[desc] => custom description2
)
)
)
Might something like this work?
foreach($this->Details as $section1){
foreach($newinfo as $section2){
if($section1->title == $section2->title){
unset($section2->title);
$components = get_object_vars($section2);
// Check to see that only one key is present. Skip if more than one.
if (count($components) > 1) {
continue;
}
$component_keys = array_keys($components);
$component_key = reset($component_keys);
$section1->{$component_key} = $section2->{$component_key};
}
}
}
Basically it seems the issue is determining the key name for the subordinate component. You would have to add your own error checking. For example, I assume the second component will only have the one object, but that may not be true. Perhaps you need to ensure the key begins with the string "component_name", perhaps that is just a placeholder. You would just need to adapt this to your data structure.
Combining Objects sometime is hectic job because we want to keep the object definintion after merging them into single object(parent)
Check this link for more information.

how to access protected array values ?

Hi I have this array and I am not sure how will I fetch the name , brand, image, token values from it?
Gloudemans\Shoppingcart\CartCollection Object
(
[items:protected] => Array
(
[1264477c2182cc04a63fde1186741fa7] => Gloudemans\Shoppingcart\CartRowCollection Object
(
[associatedModel:protected] =>
[associatedModelNamespace:protected] =>
[items:protected] => Array
(
[rowid] => 1264477c2182cc04a63fde1186741fa7
[id] => 1
[name] => washington apples
[qty] => 1
[price] => 90
[options] => Gloudemans\Shoppingcart\CartRowOptionsCollection Object
(
[items:protected] => Array
(
[brand] => awesome apple
[image] => C:\xampp\htdocs\srsgrocery\storage/app/products/1/apple-06.jpg
[token] => WiQgUjqgHEB3HZ2ImJ6iPQWHnm246twFD3Uyk6AH
)
)
[subtotal] => 90
)
)
)
)
I am using the php framework called laravel.
Please help.
save the object in a variable and do a foreach loop,
foreach($cart as $item) {
echo $item->name;
echo $item->options->brand;
}
if that's not working, you can use the fetch method from the collection class.
http://laravel.com/api/5.0/Illuminate/Support/Collection.html#method_fetch
$item->fetch('name');
and the package you're using has a alternate method search
$item->search('name');
$item->search(['options' => 'name'])
https://github.com/Crinsane/LaravelShoppingcart/blob/master/src/Gloudemans/Shoppingcart/CartRowOptionsCollection.php

How to get value out of this...?

Can someone explain me how to get data out of this...like if I just want subject, description..etc...
stdClass Object
(
[tickets] => Array
(
[0] => stdClass Object
(
[url] => https://codemymobilecom.zendesk.com/api/v2/tickets/1.json
[id] => 1
[external_id] =>
[via] => stdClass Object
(
[channel] => sample_ticket
[source] => stdClass Object
(
[from] => stdClass Object
(
)
[to] => stdClass Object
(
)
[rel] =>
)
)
[created_at] => 2015-04-22T08:30:29Z
[updated_at] => 2015-05-19T06:01:22Z
[type] => incident
[subject] => This is a sample ticket requested and submitted by you
[raw_subject] => This is a sample ticket requested and submitted by you
[description] => This is the first comment. Feel free to delete this sample ticket.
[priority] => high
[status] => closed
[recipient] =>
[requester_id] => 794599791
[submitter_id] => 794599791
[assignee_id] => 794599791
[organization_id] => 39742491
[group_id] => 24344491
[collaborator_ids] => Array
(
)
[forum_topic_id] =>
[problem_id] =>
[has_incidents] =>
[due_at] =>
[tags] => Array
(
[0] => sample
[1] => zendesk
)
[custom_fields] => Array
(
)
[satisfaction_rating] =>
[sharing_agreement_ids] => Array
(
)
[fields] => Array
(
)
[followup_ids] => Array
(
)
[brand_id] => 565681
)
[1] => stdClass Object
(
[url] => https://codemymobilecom.zendesk.com/api/v2/tickets/10.json
[id] => 10 //multiple object like [0]...
Thanks...Any help would be great..
When you need to access to array's key, use []. When you have object, use ->.
echo $obj->tickets[0]->subject; // returns first subject
echo $obj->tickets[0]->description; // returns first description
You can put it into foreach loop, of course to gain all subjects, etc.
It's STD object so use properties
$obj->tickets[0]->subject
$obj->tickets[0]->description
You can obviously loop tickets
foreach($obj->tickets as $ticket)
{
echo $ticket->subject;
echo $ticket->description
}
this is an std object.to get subject and description follow this
$obj->tickets[0]->subject;
$obj->tickets[0]->description;
if you feel better in array just make it array using this code
$array = get_object_vars($obj);

Access part of SimpleXMLElement Object - PHP

I need to loop through the items as an array within the SimpleXMLElement Object below but cannot seem to access it using $order->order->order->items. I can access the delivery and billing addresses using the same format, ie. $order->order->order->delivery_address and expected to get to the items array in the same way. However, I get an empty SimpleXMLElement Object when I print_r($order->order->order->items)
SimpleXMLElement Object
(
[order] => SimpleXMLElement Object
(
[id] => 860268
[shopkeeper_orderno] => 1001
[customer] => 797476
[creationdate] => Apr 19 2012 10:36:38:100AM
[reference] => k2koju45rmaqfl45n20xbkmq
[net] => 1500
[vat] => 17.5
[status] => 0
[isnew] => 1
[deductions] => 0
[postage] => 1
[paymentmethod] => PayPal
[instructions] => SimpleXMLElement Object
(
)
[errors] => SimpleXMLElement Object
(
)
[kashflow_synch] => 0
[order] => Array
(
[0] => SimpleXMLElement Object
(
[billing_address] => SimpleXMLElement Object
(
[0] =>
)
)
[1] => SimpleXMLElement Object
(
[delivery_address] => SimpleXMLElement Object
(
[0] =>
)
)
[2] => SimpleXMLElement Object
(
[items] => Array
(
[0] => SimpleXMLElement Object
(
[id] => 1285158
[headerID] => 860268
[productID] => 4867690
[description] => TEST ORDERING PF NODES - Special Offer Price
[net] => 1400
[vat] => 0
[qty] => 1
[formID] => -1
)
[1] => SimpleXMLElement Object
(
[id] => 1285159
[headerID] => 860268
[productID] => 4959678
[description] => Wedding dress
[net] => 100
[vat] => 17.5
[qty] => 1
[formID] => -1
)
)
)
)
[postage_tax] => 0
[dispatched] => 0
[paybyotherid] => -1
[ip] => 81.168.43.121
[wheredidyouhearid] => -1
)
)
EDIT: I just saw you made a mistake with the naming, the parent needs to be called <orders> and the sub items <order>
The SimpleXMLElement seems to be empty, in fact it's usually filled but not displayed when dumping (whoever thought of this crazy behaviour)
Can you try this?
foreach($order->orders->order as $order) { // should be orders then
echo $item->getName();
}
Or try it with SimpleXMLElement::children()
your items are actually on the second offset of the order array.
I'd just use the xPath to process these.
foreach($xmlObject->xpath('/order/order[2]/items') as $item)
{
// Do something with my $item
}
You can use a loop like the one below, then all you need to do is $items->id
foreach($order->children()->children()->items as $items)
{
}
Using Dan Lees suggestion I tried SimpleXMLElement::children() and did the below which works
foreach ($order->children() as $order) {
foreach ($order->children() as $order_details) {
foreach ($order_details->children() as $order_items) {
echo $order_items->id;
}
}
}

Categories