I'm just starting out with WooCommerce and hitting one mental block out of the gate. I see this whole web of template files that I'm wrapping my head around, but there are a few situations where I'd love to be able to just access the full $product object, methods and all, and just write my own template code.
This is playing out right now with the variable product attributes dropdown. Rather than a select I'd like radios with labels to make it easy to style them. Ideally I'd just grab the attributes from the $product object and write some HTML in a loop, but when I print_r($product) all I get is the slug of the product.
I noticed that in wc_dropdown_variation_attribute_options() there's a call to $product->get_variation_attributes(), but I can't access that myself.
Any helpful tips for somebody at this stage with WooCommerce? Any suggestions around how to access the main $product object and template functions are preferred over copy/paste situations.
You can use the WC_Product_Factory class and then call function get_product(ID) to access the main $product object
Example
$_pf = new WC_Product_Factory();
$product = $_pf->get_product($product_id);
You can then use all the function calls as listed in their api: http://docs.woothemes.com/wc-apidocs/class-WC_Product.html
Related
Does anyone know if there is a way in Wordpress's core functions to retrieve posts but not the full WP_Post object ? For example let's say only the post title and permalink ?
The full post object is very big and the standard queries quickly become slow as your site grows.
There is a return argument in the standard WP_Query :
https://developer.wordpress.org/reference/classes/wp_query/#return-fields-parameter
But this only provides few options and you can't really retrieve what you want.
Thanks for your help
You can use the get_results() function. You can use simple SQL statements like SELECT x,y,z,... to get only the columns you need from a table of your choice.
Simple example:
function get_players() {
global $wpdb;
return $wpdb->get_results("SELECT a.id, a_name ROM player a");
}
The docs say that only 3 options are supported, and none of them allow an ad-hoc selection of fields. To do something more custom, you'd probably need to use the wpdb class
The most appropriate solution I found to avoid big requests is to use the WPGraphQL plugin.
It allows you to make GraphQL API calls on your Wordpress database, and directly specify in your request what you want in return. The server appears to be way less overloaded.
In my case it is very appropriate, but if you want to stay in a classic PHP wordpress approach, the get_results() function is working too as said in the other answers.
I'm using WooCommerce Subscriptions on a site to provide team-based memberships. I'd like to ensure that the owner of the Subscription matches the owner of the team (one user to rule them all...!)
It's possible to do this via admin by using the customer dropdown fields.
So, I have been trying to set this programmatically. As I understand it, there are getter and setter methods for all the Subscription data (and as a Subscription is extended from WC_Order, those methods should work too). However, I can't figure out what method to use to make this change.
I've tried creating both a subscription and an order instance from a subscription ID, but neither of the methods I've tried below work:
set_user_id(456)
set_customer_id(456)
When I print_r() the Subscription instance, the original customer_id is still there under the data array:
WC_Subscription Object
(
[data:protected] => Array
(
...
[customer_id] => 123
)
...
)
Given that the array is protected, I'm guessing there's a setter method I haven't tried yet. Can someone please help me with what type of instance and setter method I need for this please?
Cheers!
I'm pleased to say I've solved this one myself - posting here to hopefully help someone else from banging their heads against the walls!
Turns out I was doing everything correctly, I just wasn't calling the save() method after I made my changes......! D'oh!
I'm quite used to functions in WordPress having immediate effect - a valid call to update_post_meta, for example, will take effect straight away.
Instead, WooCommerce stores changes via getters/setters within the local instance created through WC_Order (or other abstractions). These are only saved to the database* when you call the save() method. I believe this is to help prevent unnecessary database calls.
*or data store if you're doing something very fancy.
Code example for those who need it, for an order ID '123' and a new user ID '456':
// Create order instance
$order_instance = wc_get_order(123);
// Set new customer id
$order_instance->set_customer_id(456);
// Save changes
$order_instance->save();
// To echo data back, use the get_data() method to create an array of data, which you can assign however needed. For example:
$order_data = $order_instance->get_data();
$customer_id = $order_data['customer_id'];
echo 'customer number = ' . $customer_id;
I found the information about why the data requires manually saving (it's only stored in the local instance) from the very helpful doc at Advanced Woo:
"Setter methods update information in the WC_Data object held in working memory. However, one of the Database Operations Methods must be called to make the change in the database."
https://advancedwoo.com/topic/wc_data-and-data-storage-manipulate/#/setters
What are some ways to get the current order ID from within a callback function hooked to a WooCommerce filter where the callback is not passed the order ID by default?
Example hook to a WooCommerce filter that meets this criteria:
add_filter('woocommerce_get_downloadable_file_urls', array('fooClass', 'fooFighter'), 10, 4);
This hook passess the following variables to the callback:
$file_urls
$product_id
$variation_id
$item
I have looked into accessing the order ID through $woocommerce by defining it as a global. In this instance (when WooCommerce sends the customer the completed order email), $woocommerce does not contain a WC_Order object.
For additional information, I am attempting to use the aforementioned hook to create custom download links for specific WooCommerce products. This filter is called each time a downloadable product is listed on the completed order email and again on the order complete page). To create the custom link, I need the order_id.
I know it's been a while since this was asked, but I stumbled upon the same problem today and fixed it by putting the following code inside my filter function.
global $woocommerce;
$orderId = $woocommerce->woocommerce_email->emails['WC_Email_New_Order']->object->id;
The $woocommerce-woocommerce_email->emails variable is only set when sending out e-mails, so adding some checks might also be necessary.
Hope this helps someone someday. :)
I also know this is pretty old, but just wanted to note that for WooCommerce 2.2 the get_downloadable_file_urls() method is deprecated in favor of get_item_downloads(). That means the that appropriate filter would now be woocommerce_get_item_downloads.
return apply_filters( 'woocommerce_get_item_downloads', $files, $item, $this );
The third parameter is $this which since get_item_downloads() is a method in the WC_Abstract_Order abstract (responsible for WC_Order) would ultimately mean it is the $order object and $order->id would be the ID.
Buddypress has a group functionality in which I combined with the plugin BP Group Hierarchy so that I can create an hierarchy of groups based on user role.
However, the plugin used an method as taught by Buddpress in group-extension-api> link.
The group steps are registered using the function bp_register_group_extension and add_action are called. I tried to remove the action by with no success. Because I not really understand how the array works i.e. array( &$extension, \'_register\' ), so I go search out and found this post.
There's a line stating that
The new format for the above object referenced method callbacks are always: class name, followed immediately by the method name, followed by the amount of previously added (classname+methodname). For classes, this allows you to add as many object referenced classes and add methods which don’t override each other.
However I can't seems to be able to remove the action.
I tried to remove the action by putting following lines of code in function.php
function remove_bp_hierarchy(){
if (has_action('bp_actions')) {
echo $extension = new BP_Groups_Hierarchy_Extension;
remove_action('bp_actions', array( &$extension, '_register' ), 999);
} else {
}
add_action('bp_init','remove_bp_hierarchy', 999);
Is it something wrong with my remove_action or I use wrong method? Thanks and regards.
## Update
Found a page in which let we see a list of hooks and also hooked function in the page. I see that there's a function with the name _register which is the function I'm looking for. However, class address always change. I was thinking using the function found to do a preg_match on it and remove it when it found. this is super heavy. So is there other way of removing it? Thanks and Regards.
CodingBabyDotCom -
Long story short: you will have to traverse the $wp_filter array to remove the action.
You need a reference to the SAME instance that was used to create the action in order to remove it with the remove_action function. So the function you posted doesn't work because it is using a new instance.
Unfortunately bp_register_group_extension() creates only a temporary instance, so it can't be referenced by later functions.
The code in your comment will remove ALL actions at level 8, which means all group extensions. To remove only the one you want, iterate over each filter and check its type with:
is_a( $wp_filter['bp_actions'][8][$key], 'BP_Groups_Hierarchy_Extension' )
I'm trying to understand some of the function in WordPress, but I can't get my head around what apply_filters(...) actually does.
Is someone able to clear this up for me with a few examples?
apply_filters($tag, $value) passes the 'value' argument to each of the functions 'hooked' (using add_filter) into the specified filter 'tag'. Each function performs some processing on the value and returns a modified value to be passed to the next function in the sequence.
For example, by default (in WordPress 2.9) the the_content filter passes the value through the following sequence of functions:
wptexturize
convert_smilies
convert_chars
wpautop
shortcode_unautop
prepend_attachment
do_shortcode
late answer
Short explanation
apply_filters() interacts with the global $wp_filters array. Basically it just checks the array if the current filter (or hook) has an action(/callback function) attached and then calls it.
Long explanation
When you attach a callback/action to a filter or hook, then you just add the callback name to global filters array. When then, in code (for e.g. a template, core or plugin file) a call to do_action() or apply_filters() happens, then WordPress searched through the array and calls the callback. The only thing more special with filters than with hooks is, that it returns the value (for further handling) instead of just firing the callback. So summed up: Hooks are to insert data, while filters are to modify data.
Here's what I'm gleaning, upon considering the most popular answer and additional resources:
$tag seems to be a synonym for the name of the hook. (That's not particularly intuitive to me.)
the_content is an example of a hook, of the "filter" type.
the_content hook consists of multiple filters.
Filters modify data. They basically filter the database, changing the data before the users view it.
A common use of apply_filters(), for instance, is to apply the_content filters to $content. In this instance, double returns will convert to <p> tags, smiley faces will convert to icons, etc.
"the_content" is a hook, while "the_content()" is a function.
In the most basic terms, apply_filters is used to initialise a filter hook... add_filter assigns a new function to hooks that have already been created.