0

We wrote a small custom plugin for a client to pull some custom options (set in the WP dashboard) to be used to calculate custom shipping costs in Woocommerce.

The issue right now is that changes to the options from the admin panel don't seem to be reflected in the checkout. The "old" (previous) values are in use.

Here is a snippet showing how we set these options (in our plugin's main .php file):

add_action('admin_init', 'vds_settings_init');

function vds_settings_init() {

  register_setting('pluginPage', 'vds_settings');

  add_settings_field(
    'vds_pick_base_rate',
    __('Pick n Dropp Base Rate', 'wordpress'),
    'vds_pick_base_field_render',
    'pluginPage',
    'vds_pluginPage_section'
  );

...
/** Other settings fields are defined... **/
...

function vds_pick_base_field_render() {
  $options = get_option('vds_settings');
  ?>
  <input type='text' name='vds_settings[vds_pick_base_rate]' value='<?php echo $options['vds_pick_base_rate']; ?>'>
  <?php
}

I had a hard time finding good information on how transients and option caches work from a beginner/intermediate level - so my question is, how can I flush those options anytime a change is made in the dashboard and should this be done at the plugin level on page load or through some other mechanism? Once we hand the site off we can't expect its owner to manually blow away any cached stuff.

This is the hook we used to update the shipping totals via AJAX when fields were updated, etc.

add_action('woocommerce_checkout_update_order_review', 'update_shipping_costs');

And an example function running in that callback which gets and sets the rates defined above:

function update_shipping_costs($post_data) {
  // Clear transients to make sure shipping is re-calculated
  // The transients were apparently causing problems with a freelancer and he had used this nuclear option to get rid of them. We left it in as we assumed it helped. 
  global $wpdb;
  $wpdb->query("DELETE FROM `$wpdb->options` WHERE `option_name` LIKE ('%\_transient\_%')");

Further down in this callback, we have some helper functions. This is one of them:

function set_distance_rate($vd_dist) {
  $vds_options = get_option('vds_settings');

  foreach (WC()->cart->get_cart() as $cart_item_key => $cart_item) {
    $product = $cart_item['data'];

    // Use of the max function ensures our shipping rate is at least $5
    if (has_term('courier', 'product_cat', $product->id)) {
      $vd_rate = max($vds_options['vds_pick_base_rate'] + ($vd_dist * $vds_options['vds_pick_multiplier']), 5);
    } else {
      $vd_rate = max($vds_options['vds_shop_base_rate'] + ($vd_dist * $vds_options['vds_shop_multiplier']), 5);
    }
  }

  WC()->session->set('vdropp_shipping_charges', $vd_rate);
}

This isn't the complete plugin file obviously, but you can see we're clearly asking for the vds_settings set in the Dashboard. Yet, they don't reflect changes.

You may notice in the comment that we know that query is a bit nuclear. But without better understanding transients and options in WP, we borrowed it from some partially functioning code we outsourced. That dev moved and we lost touch, so we decided to do a full re-write and left the transient-deleting query in there because we knew he had issues with cache/transient objects.

We don't believe it's a Woocommerce issue because the shipping and checkout process works -- it's the values coming from get_options that don't seem to change when we play with them and refresh the checkout.

We had some issues early on with people arriving on the checkout page and seeing a previous session's shipping costs already there, so I nuked them with this (but I don't think it should be affecting retrieval of updated values):

// Always clear session vars and get new stuff
add_action('woocommerce_before_checkout_form', 'clear_session_vars');

function clear_session_vars($a) {
  WC()->session->set('pickup_postal_code', null);
  WC()->session->set('delivery_postal_code', null);
  WC()->session->set('vdropp_shipping_charges', null);
  WC()->session->set('shipping_total', null);
}

The options themselves are set with this, which shows them in the dashboard, but oddly I don't see them when browsing the database manually with phpMyAdmin:

function vds_options_page() {
?>
  <form action='options.php' method='post'>
    <h2>Distance Shipping</h2>
  <?php
    settings_fields('pluginPage');
    do_settings_sections('pluginPage');
    submit_button();
  ?>
  </form>
<?php
}

EDIT: Added a bunch of code to hopefully better illustrate the situation! EDIT 2: Added more snippets showing session vars and option setting

  • Can you post an example that exhibits this behaviour so we can replicate and debug? There's no code in your question so it's hard to tell if it's a simple fix you've not applied or used incorrectly, or something else going on. Also, woocommerce specific questions are out of scope here, make sure your question isn't Woocommerce specific – Tom J Nowell Dec 8 '17 at 18:06
  • Hey @TomJNowell -- good idea. I'll add a code snippet or two. I don't believe it's Woocommerce specific, I think something in my plugin's options is getting cached somewhere. We're simply using a WC hook at the checkout stage to override the original shipping costs and that is working fine. It's retrieving the values from our options that is causing weirdness. – armadadrive Dec 8 '17 at 19:03
  • hmmm, do you have a caching plugin? Object caching? Memcached/Redis/etc? How is vds_settings being set? – Tom J Nowell Dec 8 '17 at 20:39
  • Nope, just WordFence and some WC helper plugins (WC Fields Factory, a payment gateway...). Their host is HostGator so I have no control or clue what they're doing. Is it possible these values are just being cached on the host side? The other thing I find weird is that I don't see my values in the wp_options table even though the fields populate with the data just fine in the dashboard. – armadadrive Dec 8 '17 at 20:48
  • @TomJNowell vds_settings is being set by the top snippet and the function vds_options_page() block is doing the rest as far as I'm aware. Again, the values are there in the fields when in the WP Dashboard, it's just that changing them seems to have no effect even though the values are updated in the fields on the Options page as well. When "used" at checkout, I'm not getting updated values. – armadadrive Dec 8 '17 at 20:56
1

Did you confirm it was the transient values causing the options to not update?

Here's the WordPress function to clear transient values: https://codex.wordpress.org/Function_Reference/delete_transient

An example:

<?php
// Create a simple function to delete our transient
function edit_term_delete_transient() {
     delete_transient( 'the_transient_name_to_delete' );
}
// Add the function to the edit_term hook so it runs when categories/tags are edited
add_action( 'edit_term', 'edit_term_delete_transient' );
?>
  • You can search the database for the names of the transient entries to delete.

(Note, you might also want to verify that the edit_term hook is a sufficient place to call the delete_transient function. You could have other optimized points in your code to call this as well.)

** You can also check https://docs.woocommerce.com/document/shipping-method-api/ for info on how to manipulate WooCommerce shipping options.

  • No, I have a rudimentary understanding of when and how transients are created so perhaps I'll have a look at this! I think I'd need a different hook, but I'll mark this as correct if it helps me solve the problem. Just need some more time to investigate! – armadadrive Dec 8 '17 at 19:01
  • Ok. In case it's not the transient values, maybe you can take a look at this page (if you did not as yet) docs.woocommerce.com/document/shipping-method-api it has more info on how to manipulate WooCommerce shipping options. – signal2013 Dec 8 '17 at 19:13
  • Thanks! The shipping charges are updating just fine, it's the values coming in from get_options that aren't changing. We can complete the checkout with the custom shipping rates in place, but if we changed a shipping multiplier, for instance, it isn't using the new values on hard refresh. I've updated the question with some code snippets and further description :) – armadadrive Dec 8 '17 at 19:20
  • Maybe try the action hook woocommerce_review_order_before_shipping to see if it's an ok point to try update the values... – signal2013 Dec 8 '17 at 20:28
  • Not explicity - the override is done using this hook: add_filter('woocommerce_package_rates','vds_overwrite_flat_shipping_rate', 100, 2); and it seems to be working fine. – armadadrive Dec 8 '17 at 20:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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