skip to Main Content

I’m trying to get some php code to work in a shortcode.

Here is what i did in woocommerce dashboard.php. This code shows the data of the last order placed by the customer, everything works perfectly. As you can see it contains if, endif and else.

<?php
// For logged in users only
if ( is_user_logged_in() ) :

// Get the current WC_Customer instance Object
$customer = new WC_Customer( get_current_user_id() );

// Get the last WC_Order Object instance from current customer
$last_order = $customer->get_last_order();
?>

<?php if( is_a($last_order, 'WC_Order') ) : ?>
   
<?php foreach ( $last_order->get_items() as $item ) : ?>

<div class="last_order_items"><?php echo $item->get_name(); ?></div>
<div class="last_order_items"><?php echo $item->get_total(); ?>€</div>

<div class="order_number">#<?php echo $last_order->get_order_number(); ?> </div>
<div class="order_number">Data acquisto <?php echo $last_order->get_date_created()->date('d/m/Y - H:i'); ?> </div>
<div class="order_number">Stato dell'ordine <?php echo esc_html( wc_get_order_status_name( $last_order->get_status() ) ); ?>
  
<?php endforeach; ?>

<?php else : ?>

<div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
        <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>"><?php esc_html_e( 'Browse products', 'woocommerce' ); ?></a>
        <?php esc_html_e( 'No order has been made yet.', 'woocommerce' ); ?>
        </div>

<?php endif; ?>
<?php endif; ?>

Here is what I did in the functions.php file. The shortcode works fine, but if user is not logged in or has not placed an order, an error occurs. In dashboard.php file the error is not there because the if (is_user_logged_in ()) part exists and the else part which shows the message when a user has not placed any order.

//// LAST ORDER ON DASHBOARD WOOCOMMERCE SHORTCODE ////

add_shortcode( 'short_test' , 'test' );
function test(){    
    $customer = new WC_Customer( get_current_user_id() );
    $last_order = $customer->get_last_order();
    return $last_order->get_order_number();

}

How can i implement if, endif and else in this shortcode ? I would like to be able to show data only to logged in users, and for those who have not placed any orders I would like to display a message just like I did in the dashboard.php file. I tried a number of ways but couldn’t. I would like to use the shortcode because it is more convenient for me, moreover I prefer to keep the woocommerce templates "clean" and write everything directly in the functions.php file

Sorry, but I’m a fan and don’t have a lot of knowledge on the subject.

3

Answers


  1. Chosen as BEST ANSWER

    I found a solution, here's what I did:

    <?php
    
    add_shortcode( 'short_test' , 'test' );
    
    function test() {
    
    // Get the WC_Customer instance Object for the current user
    $customer = new WC_Customer( get_current_user_id() );
    
    // Get the last WC_Order Object instance from current customer
    $last_order = $customer->get_last_order();
    
    // Then I added the if condition. If this is the last order, then it shows the data from it
    if ( is_a( $last_order, 'WC_Order' ) ) {
    return $last_order->get_order_number();  // Change get_order_number to another parameter if you want to show different information  
    } 
        
    // With else show the warning message if the user has not placed any order
    else {
    ?><div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
    <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>"><?php esc_html_e( 'Browse products', 'woocommerce' ); ?></a>
    <?php esc_html_e( 'No order has been made yet.', 'woocommerce' ); ?>
    </div><?php
    } 
    }
    
    

    I leave below some information for those who have encountered the same problem.

    1. In case you want to change the type of information to be displayed, just change get_order_number(); with the parameter you want. An example could be the following: $last_order = $customer->get_formatted_order_total(); will show the order total instead of the order number. Here you find a list of all woocommerce parameters https://www.businessbloomer.com/woocommerce-easily-get-order-info-total-items-etc-from-order-object/

    2. If you want to add different parameters such as items, then you have to introduce foreach inside the if as follows.

    // Get and Loop Over Order Items
    if ( is_a( $last_order, 'WC_Order' ) ) {
         foreach ( $last_order->get_items() as $item ) {
         return $last_order = $item->get_product_id();   
         }
        } 
    
    1. If you want to show more information within the same shortcode then edit the if part as follows. Remember that only $ items go into the foreach. If you don't need $ item parameters you can also delete the foreach.
    if ( is_a( $last_order, 'WC_Order' ) ) {
          
         ?><div class="last_order" style="display:block">Order Number <?php echo $last_order->get_order_number();
         ?><div class="last_order">Order Total <?php echo $last_order->get_formatted_order_total();
         ?><div class="last_order">Order Status <?php echo $last_order->get_status();
          
         foreach ( $last_order->get_items() as $item ) {
         ?><div class="last_order">Product ID <?php echo $last_order = $item->get_product_id(); 
         }
        } 
    

    Edit with @Josh Bonnick's solution After "playing" a bit with various ways to get an error message instead of breaking the layout I also tried @Josh Bonnick's solution which I implemented in the following motion. (I took the first part of the code and not the second that requires the template).

    <?php
    
    add_shortcode( 'short_test' , 'test' );
    
    function test() {
    
    // Get the WC_Customer instance Object for the current user
    $customer = new WC_Customer( get_current_user_id() );
    
    // Get the last WC_Order Object instance from current customer
    $last_order = $customer->get_last_order();
    
    // Then I added the if condition. If this is the last order, then it shows the data from it
    if ( is_a( $last_order, 'WC_Order' ) ) {
    return $last_order->get_order_number();  // Change get_order_number to another parameter if you want to show different information  
    } 
    
    // Josh Bonnick recommended piece of code
    $order_count = wc_get_customer_order_count(get_current_user_id()); 
    if ($order_count == 0) { 
    return '<p>This is where you would put your HTML</p>'; 
    }
    

  2. Here’s two version of the same shortcode [short-test]

    • One will allow you to write some HTML into a string, this can get messy, especially if you need to add customer data into it.
    • Two will allow you to create a .php file in a subdirectory of the theme and pull that template as the text to return.

    functions.php

    add_shortcode('short-test', 'test');
    function test()
    {
        if (get_current_user_id() == 0) {
            // User isn't logged in, don't output anything.
            return '';
        }
        // Customer order count
        $order_count = wc_get_customer_order_count(get_current_user_id());
        if ($order_count == 0) {
            return '<p>This is where you would put your HTML</p>';
        }
    }
    
    add_shortcode('short-test', function () {
        if (!get_current_user_id()) {
            // User isn't logged in, don't output anything.
            return '';
        }
    
        // Customer order count
        $order_count = wc_get_customer_order_count(get_current_user_id());
        if ($order_count == 0) {
            // Customer has no orders, pull our template from /templates/customer-has-no-orders.php
            ob_start();
            include __DIR__ . '/templates/customer-has-no-orders.php';
            return ob_get_clean();
        }
    
        return '';
    });
    

    templates/customer-has-no-orders.php

    <p>You can write whatever you want here, in HMTL/PHP/JS</p>
    

    Usage:

    • In .php template file: <?= do_shortcode('[short-test]'); ?>
    • In post editor: [short-test]

    If you’re only writing small amount of text and not planning to add customer data into the text, like their name then use the first option and delete the second. I’ve made the second an anonymous callback so it won’t break if you copy paste both.

    Output buffering documentation ob_start()

    wc_get_customer_order_count

    Login or Signup to reply.
  3. I found a solution to make the download button work as well as this would break the layout if the user no download available.

    <?php
    add_shortcode( 'order_download' , 'last_order_info_08' );
    function last_order_info_08(){
    $customer = new WC_Customer( get_current_user_id() );
    $last_order = $customer->get_last_order();
    
      if ( is_a( $last_order, 'WC_Order' ) ) {
         $downloads = $last_order->get_downloadable_items();
         
         if ($downloads){
             wc_get_template(
             'button-downloads.php',
             array(
             'downloads'  => $downloads,
             'show_title' => true,
             ));
             }
         } else {
            ?><div class="woocommerce-message woocommerce-message--info woocommerce-Message woocommerce-Message--info woocommerce-info">
            <a class="woocommerce-Button button" href="<?php echo esc_url( apply_filters( 'woocommerce_return_to_shop_redirect', wc_get_page_permalink( 'shop' ) ) ); ?>"><?php esc_html_e( 'Browse products', 'woocommerce' ); ?></a>
            <?php esc_html_e( 'No order has been made yet.', 'woocommerce' ); ?>
            </div><?php
        }     
    }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search