I am trying to make it so that the url.com/my-account or the shortcode [woocommerce_my_account] displays the orders instead of the dashboard that displays "Hello User (not user)?".
The only thing I have is for after logging in which redirects to the orders instead of the dashboard, but I then going to the /my-account still displays the dashboard which I don't want.
The closest code I found that does what I want is...
function woocommerce_orders() {
$user_id = get_current_user_id();
if ($user_id == 0) {
return do_shortcode('[woocommerce_my_account]');
}else{
ob_start();
wc_get_template( 'myaccount/my-orders.php', array(
'current_user' => get_user_by( 'id', $user_id),
'order_count' => $order_count
) );
return ob_get_clean();
}
}
add_shortcode('woocommerce_orders', 'woocommerce_orders');
However, if there are no orders placed then it comes out blank(doesn't display the "No order has been made yet." with shop button) and the my account nav-sidebar doesn't show up. Would I have to make a custom page-template for this to add in the woocommerce account nav-sidebar?
Edit: If I use the orders.php instead of my-orders.php then I am able to get the "No order has been made yet." But still no sidebar-nav
You could try the following code (that is not perfect as it removes the access to the dashboard):
add_action( 'woocommerce_account_content', 'remove_dashboard_account_default', 5 );
function remove_dashboard_account_default() {
remove_action( 'woocommerce_account_content', 'woocommerce_account_content', 10 );
add_action( 'woocommerce_account_content', 'custom_account_orders', 10 );
}
function custom_account_orders( $current_page ) {
global $wp;
if ( ! empty( $wp->query_vars ) ) {
foreach ( $wp->query_vars as $key => $value ) {
// Ignore pagename param.
if ( 'pagename' === $key ) {
continue;
}
if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
do_action( 'woocommerce_account_' . $key . '_endpoint', $value );
return;
}
}
}
$current_page = empty( $current_page ) ? 1 : absint( $current_page );
$customer_orders = wc_get_orders( apply_filters( 'woocommerce_my_account_my_orders_query', array(
'customer' => get_current_user_id(),
'page' => $current_page,
'paginate' => true,
) ) );
wc_get_template(
'myaccount/orders.php',
array(
'current_page' => absint( $current_page ),
'customer_orders' => $customer_orders,
'has_orders' => 0 < $customer_orders->total,
)
);
}
Code goes in function.php file of your active child theme (or active theme). Tested and work.
There's a much easier way: simply catch WordPress's parse_request, check if the request is for my-account (or whatever your account page slug is) and perform a redirect:
function vnm_wc_redirect_account_dashboard( $wp ) {
if ( !is_admin() ) {
// Uncomment the following line if you want to see what the current request is
//die( $wp->request );
// The following will only match if it's the root Account page; all other endpoints will be left alone
if ( $wp->request === 'my-account' ) {
wp_redirect( site_url( '/my-account/orders/' ) );
exit;
}
}
}
add_action( 'parse_request', 'vnm_wc_redirect_account_dashboard', 10, 1 );
I used code of LoicTheAztec and another complementary snippet, which removes dashboard tab:
// Remove or rename my account page navigation links (removes downloads and dashboard).
add_filter ( 'woocommerce_account_menu_items', 'my_account_menu_order' );
function my_account_menu_order() {
$menuOrder = array(
'orders' => __( 'Orders', 'woocommerce' ),
// 'downloads' => __( 'Download', 'woocommerce' ),
'edit-address' => __( 'Addresses', 'woocommerce' ),
'edit-account' => __( 'Account details', 'woocommerce' ),
'customer-logout' => __( 'Logout', 'woocommerce' ),
// 'dashboard' => __( 'Dashboard', 'woocommerce' )
);
return $menuOrder;
}
I also created a snippet which causes orders tab to be highlighted by default. It's done through adding active class and then CSS opacity: 1 highlights it. Script will show only in account section to avoid bloat where it isn't needed:
// Make orders link highlighted by default in my account section.
add_action('wp_footer', 'taisho_dashboard_orders_highlight');
function taisho_dashboard_orders_highlight() {
if (!is_account_page()) return; // Account section only
global $wp;
$acc_url = get_permalink( get_option( 'woocommerce_myaccount_page_id' ));
$my_acc = rtrim( $acc_url , '/' );
$my_acc = explode( '/', $my_acc );
?>
<script type="text/javascript">
var dashboard_active = <?php echo $wp->request === end($my_acc) ?>;
jQuery(document).ready(function($) {
$('.woocommerce-MyAccount-navigation-link--orders').toggleClass('is-active', dashboard_active);
});
</script>
<?php
}
Using parse_request action:
add_action( 'parse_request', function ( $wp ) {
// Prevent the redirection, in the case,
// the user is not logged in (no login, no orders)
if (!is_user_logged_in()) return false;
if ( $wp->request === 'my-account' ) {
wp_redirect( home_url( '/my-account/orders/' ) );
exit;
}
}, 10, 1 );
As of today there's only one workaround to set another My Account tab as default and also preserve the "Dashboard" tab.
Let's say we want to default to the "Downloads" tab. We need to:
replace the “Dashboard” tab content with the “Downloads” tab content
rename the “Dashboard” tab to “Downloads”
hide the original “Downloads” tab as we already have it now
readd the “Dashboard” tab
This is a little complex to paste here so I'll cover point 1 only which is the most difficult one. The rest can be easily found on StackOverflow or this Business Bloomer tutorial as it's basic rename/remove/add My Account tabs work.
As per point 1, we need to overwrite the woocommerce_account_content() function which is responsible to display the "Dashboard" content by default in case we're on the My Account and there are no query vars or there is a non-empty query var called "pagename".
I will therefore remove the WooCommerce function, and add my version instead:
add_action( 'woocommerce_account_content', 'bbloomer_myaccount_replace_dashboard_content', 1 );
function bbloomer_myaccount_replace_dashboard_content() {
remove_action( 'woocommerce_account_content', 'woocommerce_account_content', 10 );
add_action( 'woocommerce_account_content', 'bbloomer_account_content' );
}
Now I go define my custom bbloomer_account_content() function, and I basically tell the system that:
if there is no query var or if there is and a query var called "pagename" is not empty, I echo my custom content (the "Downloads" tab content in my case"
otherwise, it means I am on an endpoint URL, and therefore I copy whatever was inside woocommerce_account_content() to return the tab content
Code:
function bbloomer_account_content() {
global $wp;
if ( empty( $query_vars = $wp->query_vars ) || ( ! empty( $query_vars ) && ! empty( $query_vars['pagename'] ) ) ) {
woocommerce_account_downloads();
} else {
foreach ( $wp->query_vars as $key => $value ) {
if ( 'pagename' === $key ) {
continue;
}
if ( has_action( 'woocommerce_account_' . $key . '_endpoint' ) ) {
do_action( 'woocommerce_account_' . $key . '_endpoint', $value );
return;
}
}
}
}
In this way, if I go to "example.com/my-account" I will see the "Downloads" tab content; if I switch tab and go to "Dashboard" or "Orders", I will see their original content instead.
Remember that this is only part 1 and therefore additional workaround is needed with parts 2, 3 and 4 to really make it work.
Related
I'm struggling with a basic php function.
I implemented a backend checkbox in wordpress / woocommerce general tab which works fine:
// Add checkbox in Backend
function action_woocommerce_product_options_general_product_data() {
// Checkbox
woocommerce_wp_checkbox( array(
'id' => '_prevent_add_to_cart_button', // Required, it's the meta_key for storing the value (is checked or not)
'label' => __( 'Warenkorb Button', 'woocommerce' ), // Text in the editor label
'desc_tip' => false, // true or false, show description directly or as tooltip
'description' => __( 'Warenkorb Button ausblenden', 'woocommerce' ) // Provide something useful here
) );
}
add_action( 'woocommerce_product_options_general_product_data', 'action_woocommerce_product_options_general_product_data', 10, 0 );
// Save Field
function action_woocommerce_admin_process_product_object( $product ) {
// Isset, yes or no
$checkbox = isset( $_POST['_prevent_add_to_cart_button'] ) ? 'yes' : 'no';
// Update meta
$product->update_meta_data( '_prevent_add_to_cart_button', $checkbox );
}
add_action( 'woocommerce_admin_process_product_object', 'action_woocommerce_admin_process_product_object', 10, 1 );
Now i want to ask for the value of that checkbox and do things based on it.
It works in this function as expected:
// Add function for category / listing page add to cart button hook
function hide_listingpage_button( $add_to_cart_html, $product, $args ){
$hide_add_to_cart_button = $product->get_meta( '_prevent_add_to_cart_button' );
if ( $hide_add_to_cart_button == 'yes' ) {
$before = '<span style="display:none;">';
$after = '</span>';
return $before . $add_to_cart_html . $after;
}
else {
return $add_to_cart_html;
}
}
add_filter( 'woocommerce_loop_add_to_cart_link', 'hide_listingpage_button', 10, 3 );
but it does not work in this function(s):
// Add functions for singlepage before / after add to cart button hook
function beforehide_singlepage_button( $product ) {
$hide_add_to_cart_button = $product->get_meta( '_prevent_add_to_cart_button' );
if ( $hide_add_to_cart_button == 'yes' ) {
echo 'test after';
}
}
function afterhide_singlepage_button( $product ) {
$hide_add_to_cart_button = $product->get_meta( '_prevent_add_to_cart_button' );
if ( $hide_add_to_cart_button == 'yes' ) {
echo 'test after';
}
}
add_action( 'woocommerce_before_add_to_cart_button', 'beforehide_singlepage_button' );
add_action( 'woocommerce_after_add_to_cart_button', 'afterhide_singlepage_button' );
Im my opinion im doing basically the same things?
I give the $product object as argument in the function, ask then for yes / no boolean with
$hide_add_to_cart_button = $product->get_meta( '_prevent_add_to_cart_button' );
and then echo something with the if clause.
however, i get no output of the page from that line, and also no error message.
What am i missing?
thank you!
Updated:
I'm building a WooCommerce site where the user selects a series of options from dropdowns in the single product page which then display in the cart page and, thanks to help I've received on here, in the checkout as well. The options selected also influence the price of the product. I start with two product variations: 'Print' and 'Original' (the site is selling antique maps).
Everything works fine up till the checkout where all the order details display correctly but, after having placed the order, the details don't appear on the 'order received' screen under 'order details' nor do they appear in the customer confirmation email.
To give some background, the different variations are selected using jQuery, and added to hidden fields a per example below:
$( ":root" ).find("#mapchest-custom-fields").append("<input type='hidden'
name='test' value='wibble'>");
...and these hidden fields are then referenced to add the details to the cart in the following manner:
add_filter('woocommerce_add_cart_item_data','add_custom_field_data', 20,3);
function add_custom_field_data($cart_item_data, $product_id, $variation_id)
{
if(isset($_REQUEST['test']) && ! empty( 'test' )) { // not
$mc_test = sanitize_text_field($_POST['test']);
$cart_item_data['custom_data']['test'] = array(
'label' => 'Test',
'value' => $mc_test
);
}
if(isset($_REQUEST['original_map_vendor_details']) && ! empty(
'original_map_vendor_details' )) {
$mc_original_map_size =
sanitize_text_field($_REQUEST['original_map_vendor_details']);
$cart_item_data['custom_data']['original_map_vendor_details'] =
array(
'label' => 'Vendor',
'value' => $mc_original_map_size
);
}
// process above repeated for other fields
return $cart_item_data;
}
The details are displayed in the cart and checkout using the following function:
add_filter('woocommerce_get_item_data','wdm_add_item_meta',10,2);
function wdm_add_item_meta($cart_data, $cart_item)
{
$custom_items = array();
if( !empty( $cart_data ) )
$custom_items = $cart_data;
if( isset( $cart_item['custom_data'] ) ) {
foreach( $cart_item['custom_data'] as $key => $custom_data ){
if( $key != 'key' ){
$custom_items[] = array(
'name' => $custom_data['label'],
'value' => $custom_data['value'],
);
}
}
}
return $custom_items;
}
What I want to do, as I say is have the details display in the Order Received page and the emails but I can't make it work. I know that for emails I need to hook it to one of the email hooks but I don't know how to access the data sent to the cart in the function above.
I've tried adding using the woocommerce_checkout_create_order_line_item hook to along these lines:
add_action( 'woocommerce_checkout_create_order_line_item',
'add_custom_order_line_item_meta', 20,4 );
function add_custom_order_line_item_meta($item, $cart_item_key, $values,
$order)
{
if( array_key_exists('test', $values['custom_data']) ){
$item->update_meta_data( 'Test', $values['custom_data']['test'] );
}
}
...but whilst I can see the data if I var_dump it in the email like this:
add_action('woocommerce_email_customer_details',
'add_custom_checkout_field_to_emails_notifications', 25, 4 );
function add_custom_checkout_field_to_emails_notifications( $order,
$sent_to_admin, $plain_text, $email ) {
var_dump($order);
}
So, in summary, I have the data working and displaying up to the point of the checkout. After that, I want it to display in customer confirmation emails and on the 'order received' page but I'm having trouble accessing the data. Having looked through other questions on the same subject i would have thought that this would happen automatically regarding the order received page but it doesn't. I suspect there's a stage missing in the code but I can't work out what it should be.
Any tips as to what I'm doing wrong here?
Thanks in advance.
ps. I've now managed to display the fields in the confirmation email (after a fashion) using the following functions:
add_action( 'woocommerce_checkout_create_order_line_item',
'add_custom_order_line_item_meta', 20,4 );
function add_custom_order_line_item_meta($item, $cart_item_key, $values,
$order)
{
if ( isset( $values['custom_data'] ) ) {
$item->update_meta_data( __('The Custom Data', 'woocommerce'),
$values['custom_data'] );
}
}
and
add_action('woocommerce_email_customer_details',
'add_custom_checkout_field_to_emails_notifications', 25, 4 );
function add_custom_checkout_field_to_emails_notifications( $order,
$sent_to_admin, $plain_text, $email ) {
// var_dump($order);
foreach( $order->get_items() as $item_id => $item ){
$custom_data = $item->get_meta( 'The Custom Data' );
foreach( $custom_data as $key => $value ){
foreach( $value as $key1 => $value1 ){
$output = '';
$output .= '<span class="text">' . $value1 . '</span>';
echo $output;
}
echo "<br>";
}
echo "<br><br>";
// var_dump($custom_data );
}
'</strong> <span class="text">' . $order->get_data() . '</span></div>';
}
but this is a hacky solution and doesn't address the underlying problem of why the information isn't appearing in the order received page or directly in the order line items in the email.
Okay, I've worked this out. I'm putting the answer here for the benefit of anyone else having the same problem. Basically, my process was missing a stage. In order to achieve the above you do as follows:
Define the value you wish to pass as meta data. In my own case I used a hidden field but this can equally be set with a text input, a dropdown or other input field. In my case I used jquery to append this to an empty div with id 'mapchest-custom-fields' which I hooked into the process before the cart button. It can equally be set with a static value.
<?php
function define_container_div() {
?>
<div id="mapchest-custom-fields"></div>
<?php
}
add_action( 'woocommerce_before_add_to_cart_button', 'define_container_div', 20 );
?>
...jQuery code to append the value. Value can be dynamic as well:
$( ":root" ).find("#mapchest-custom-fields").append("<input type='hidden' name='test' value='wibble'>");
Next you add the value to your cart item data:
function add_values_to_cart_item_data( $cart_item_data, $product_id, $variation_id )
{
if(isset($_POST['test']) && ! empty( 'test' )) {
$test = filter_input( INPUT_POST, 'test' );
$cart_item_data['test'] = $test;
}
return $cart_item_data;
}
add_filter( 'woocommerce_add_cart_item_data', 'add_values_to_cart_item_data', 10, 3);
Next, you display the value in your cart:
function display_data_in_cart( $item_data, $cart_item ) {
$item_data[] = array(
'key' => __( 'Test', 'mapchest' ),
'value' => wc_clean( $cart_item['test'] ),
);
return $item_data;
}
add_filter( 'woocommerce_get_item_data', 'display_data_in_cart', 10, 2 );
And finally, you add the data to your order items:
function add_data_to_order_items( $item, $cart_item_key, $values, $order ) {
$item->add_meta_data( __( 'Test', 'mapchest' ), $values['test'] );
}
add_action( 'woocommerce_checkout_create_order_line_item', 'add_data_to_order_items', 10, 4 );
The above process works for me. It displays the custom data in the cart and in the checkout and persists it through to the 'Order Received' page archived orders and the confirmation email (not checked other emails yet).
Thanks to https://iconicwp.com/blog/add-custom-cart-item-data-woocommerce/ for explaining this process to me.
There are forum topics regarding custom continue shopping buttons, but there is nothing on how to link the custom button to the last product category page viewed. There is a plugin that gives the option for this; however, there is a flaw in that when the cart is refreshed, the button disappears. The following code works to create a custom message/button; however, I cannot figure out how to change the link from the shop page to the last product category page viewed:
/* Add Continue Shopping Button on Cart Page & Checkout page*/
add_action( 'woocommerce_before_cart_table',
'woo_add_continue_shopping_button_to_cart' );
add_action( 'woocommerce_before_checkout_form',
'woo_add_continue_shopping_button_to_cart' );
function woo_add_continue_shopping_button_to_cart() {
$shop_page_url = "get_permalink( wc_get_page_id( 'shop' ) )";
echo '<div class="woocommerce-message">';
echo ' <a href="'.$shop_page_url.'" class="button wc-forwards">Continue
Shopping →</a> Would you like some more prints?';
echo '</div>';
}
Thank you in advance!
J.
Here is the code that the plugin uses to link (I think):
add_action( 'woocommerce_cart_is_empty', 'hpy_cs_output_notice', 1 );
function hpy_cs_output_notice() {
$display_empty = get_option( 'hpy_cs_empty_cart_notice' );
if ( $display_empty == 'yes' ) {
$link = wc_custom_redirect_continue_shopping();
$message = sprintf('%s %s',
esc_url($link), esc_html__('Continue shopping', 'woocommerce'),
esc_html(get_option('hpy_cs_empty_cart_text', __('Your cart is empty.', '
$message = sprintf( \'%s %s\',
esc_url( $link ), esc_html__( \'Continue shopping\', \'woocommerce\' ),
esc_html( get_option( \'hpy_cs_empty_cart_text\', __( \'Your cart is
empty.\', \'hpy_cshpy_cshpy_cs\' ) ) ) );
'))));
wc_print_notice($message);
}
}
There is no built-in function to retrieve last category page viewed. But, I have some ideas on how this could be solved.
First is to create a custom action, check if page is category page, and set category ID to session data if so. Then on your button, use this to get proper URL.
/* Set up session */
add_action( 'init', 'wp_check_for_product_cat_sess');
function wp_check_for_product_cat_sess(){
if(!session_id()) {
session_start();
}
}
/* Set session variable when on Category or Product page */
add_action( 'wp', 'wp_check_for_product_cat');
function wp_check_for_product_cat(){
global $wp_query;
if( is_product_category() ){ // This is Category; use my ID
$_SESSION['wp_last_cat'] = $wp_query->get_queried_object()->term_id;
}
if( is_product() ){ // This is Product; use my ID to get my Categories
$cats = get_the_terms( $wp_query->get_queried_object(), 'product_cat' ) ;
if( count( $cats ) > 0 ){
foreach($cats as $one_cat ){
$_SESSION['wp_last_cat'] = $one_cat->term_id;
}
}
}
if( is_cart() ){
// Here we output only on Cart page, as debug tool */
var_dump( $_SESSION['wp_last_cat'] );
}
}
Then you replace in your action code:
$shop_page_url = "get_permalink( wc_get_page_id( 'shop' ) )";
Should become:
if( isset( $_SESSION['wp_last_cat'] ) ){
$shop_page_url = get_term_link( $_SESSION['wp_last_cat'], 'product_cat' );
} else {
$shop_page_url = get_permalink( wc_get_page_id( 'shop' ) );
}
Second is to retrieve last item added to cart, and use that item to retrieve its category URL.
I tried using this code below to change the URL of the word "Shop" but it seems to do nothing:
add_filter( 'woocommerce_page_title', 'woo_shop_page_title');
function woo_shop_page_title( $page_title ) {
if( 'Shop' == $page_title) {
return "My new title";
}
}
I don't want users to go to the main "Shop" page and setup many categories.
Unfortunately I have not been able to find a way to remove or change the URL of that "Shop" breadcrumb. The official docs only mention how to change the "Home" URL, not "Shop".
You're help is appreciated.
To rename any breadcrumb item and change its link, use woocommerce_get_breadcrumb filter hook this way:
add_filter( 'woocommerce_get_breadcrumb', 'custom_get_breadcrumb', 20, 2 );
function custom_get_breadcrumb( $crumbs, $breadcrumb ){
if( ! is_shop() ) return $crumbs; // Only shop page
// The Crump item to target
$target = __( 'Shop', 'woocommerce' );
foreach($crumbs as $key => $crumb){
if( $target === $crumb[0] ){
// 1. Change name
$crumbs[$key][0] = __( 'Name', 'woocommerce' );
// 2. Change URL (you can also use get_permalink( $id ) with the post Id
$crumbs[$key][1] = home_url( '/my-link/' );
}
}
return $crumbs;
}
Code goes in function.php file of your active child theme (or active theme). Tested and works.
Please check this code in on home replace Start chenag in woocommerce
function woocommerce_breadcrumb( $args = array() ) {
$args = wp_parse_args( $args, apply_filters( 'woocommerce_breadcrumb_defaults', array(
'delimiter' => ' / ',
'wrap_before' => '',
'wrap_after' => '',
'before' => '',
'after' => '',
'home' => _x( 'Home', 'breadcrumb', 'woocommerce' ),
) ) );
$breadcrumbs = new WC_Breadcrumb();
$args['home'] = "Start"; // home replace start set
if ( ! empty( $args['home'] ) ) {
$breadcrumbs->add_crumb( $args['home'], apply_filters( 'woocommerce_breadcrumb_home_url', home_url() ) );
}
$args['breadcrumb'] = $breadcrumbs->generate();
The 'shop' breadcrumb is coming from you 'Shop' pages'. Simply change your shop page slug to whatever you want, or if it is another page altogether then in the woocommerce settings you set the shop page to your new page. The url will always be the page's slug.
I use Lirox One theme on Wordpress with WooCommerce. I want make custom redirections after payment:
If a customer buy product ID 333, It will be redirected to product 444 (for example).
I have make some custom code but it doesn't works, I get an error 500 (and debug is empty).
What I am doing wrong and how can I make it work?
This is my code:
add_action( 'woocommerce_thankyou', 'check_order_product_id', 1 );
function check_order_product_id( $order_id ){
$order = new WC_Order( $order_id );
$items = $order->get_items();
foreach ( $items as $item ) {
$product_id = $item['product_id'];
//* single product id
if ( $product_id == 399 ) {
// Content Title line
$url = 'http://yoursite.com/custom-url1';
}
if ( $product_id == 358 ) {
$url = 'http://yoursite.com/custom-url2';
}
if ( $product_id == 398 ) {
$url = 'http://yoursite.com/custom-url3';
}
if ( $product_id == 357) {
$url = 'http://yoursite.com/custom-url5';
}
if ( $product_id == 356) {
$url = 'http://yoursite.com/custom-url6';
}
if ( $product_id == 335) {
$url = 'http://yoursite.com/custom-url';
}
if ( $order->status != 'failed' ) {
wp_redirect($url);
exit;
}
For redirections, use a custom function hooked in WordPress template_redirect action hook, to avoid errors 500…
I have changed your code as you will see, to match your requirements. This code is made for WooCommerce version 3+:
add_action( 'template_redirect', 'conditional_redirection_after_payment');
function conditional_redirection_after_payment(){
// When "thankyou" order-received page is reached …
if ( is_wc_endpoint_url( 'order-received' ) ) {
global $wp;
// Get the order ID from the browser url
$order_id = intval( str_replace( 'checkout/order-received/', '', $wp->request ) );
// Get an instance of the WC_Order object
$order = wc_get_order( $order_id );
// If the order status is 'failed' we stop the function
if( $order->has_status( 'failed' ) ) return;
// HERE set in the array for each product ID the coresponding url final path
$product_id_url_paths = array(
'399' => '/custom-url1',
'358' => '/custom-url2',
'398' => '/custom-url3',
'357' => '/custom-url4',
'356' => '/custom-url5',
'335' => '/custom-url6',
);
// Iterating through each order items
foreach( $order->get_items() as $item_id => $item_values ){
// The Product ID
$product_id = $item_values->get_product_id();
foreach( $product_id_url_paths as $key_id => $url_path ){
if( $key_id == $product_id ){
// Product is found and ID match: we got our path url. We redirect
wp_redirect( home_url( $url_path ) );
exit(); // always exit
}
}
}
}
}
Code goes in function.php file of your active child theme (or theme) or also in any plugin file.
Code is tested and works on WC 3+
Note: In your Code you have to remove the exit which you have used after the wp_redirect. Other all will work fine. Some more References are provided below in order to have better understanding of the Concept.
Explanation: Then you Provide Redirect only for the Particular Product
ID alone not For all the Product IDS since it may lead you to the
Internal Server Error as it is in the Foreach Loop.
It is Fine using wp_redirect() for the redirection purpose.
It is correct what have you checked for the Product ID. The Thing is that you have to follow another method if the URL are to be explicitly passed.
// We don't know for sure whether this is a URL for this site,
// so we use wp_safe_redirect() to avoid an open redirect.
wp_safe_redirect( $url );
// We are trying to redirect to another site, using a hard-coded URL.
wp_redirect( 'https://example.com/some/page' );
Some More Reference:
<?php wp_redirect( home_url() ); exit; ?>
Redirects can also be external, and/or use a “Moved Permanently” code :
<?php wp_redirect( 'http://www.example-one.com', 301 ); exit; ?>
The code below redirects to the parent post URL which can be used to redirect attachment pages back to the parent.
<?php wp_redirect( get_permalink( $post->post_parent ) ); exit; ?>
Reference: https://developer.wordpress.org/reference/functions/wp_redirect/
Th accepted answer works for Woocommerce 3+, for older versions (I'm using 2.6.4) it does not. For anyone else using this version, try the following code:
add_action( 'template_redirect', 'conditional_redirection_after_payment');
function conditional_redirection_after_payment(){
// When "thankyou" order-received page is reached …
if ( is_wc_endpoint_url( 'order-received' ) ) {
global $wp;
$order_id = intval( str_replace( 'checkout/order-received/', '', $wp->request ) );
// Get an instance of the WC_Order object
$order = new WC_Order( $order_id );
// If the order status is 'failed' we stop the function
if( $order->has_status( 'failed' ) ) return;
// HERE set in the array for each product ID the coresponding url final path
$product_id_url_paths = array(
'1234' => '/your-path/'
);
// Iterating through each order items
foreach( $order->get_items() as $item){
// echo $item_id;
// The Product ID
$product_id = $item['product_id'];
foreach( $product_id_url_paths as $key_id => $url_path ){
if( $key_id == $product_id ){
// Product is found and ID match: we got our path url. We redirect
wp_redirect( home_url( $url_path ) );
exit(); // always exit
}
}
}
}
}