简体   繁体   中英

Custom shortcode displaying a loop of WooCommerce product variations

Im trying to make a custom shortcode in order to display some product variations that have no stock quantity with stock <= 0 .

Here's what I did so far:

if( ! function_exists('preorable_products') ) {

    // Add Shortcode
    function preorable_products( $atts ) {
        global $woocommerce_loop;

        // Attributes 
        $atts = shortcode_atts(
            array(
                'columns'   => '4',
                'limit'     => '20',
                'preordable'     => "yes",
                'stock'       => 0,
            ),
            $atts, 'preorable_products'
        );


        $woocommerce_loop['columns'] = $atts['columns'];
        
        // The WP_Query
        $products_variation = new WP_Query( array (
            'post_type'         => 'product_variation',
            'post_status'       => 'publish',
            'fields'         => 'id=>parent',
            'posts_per_page'    => $atts['limit'],
            'meta_query'        => array(
                'relation'      => 'AND',
                'preordable'  => array(
                    'key'       =>'_ab_preorder_checkbox',
                    'value'     => "yes",
                    'compare'   => '=='
                ),
                'stock'  => array(
                    'key'       =>'_stock',
                    'value'     => 0,
                    'compare'   => '<='
                ),
            )
        ));
        $products = $products_variation;
        ob_start();
        
        if ( $products->have_posts() ) { ?>

            <?php woocommerce_product_loop_start(); ?>

                <?php while ( $products->have_posts() ) : $products->the_post(); ?>

                    <?php wc_get_template_part( 'content', 'product' ); ?>

                <?php endwhile; // end of the loop. ?>

            <?php woocommerce_product_loop_end(); ?>

            <?php
        } else {
            do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
            echo "<p>Aucun article disponible à la précommande.</p>";
        }

        woocommerce_reset_loop();
        wp_reset_postdata();

        return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';
    }

    add_shortcode( 'preorable_products', 'preorable_products' );
}

The WP Query part seems to work perfectly, but the code part to display the product seems wrong. I feel like $product variable doesn't have have_post method:

if ( $products->have_posts() ) { ?>
    <?php woocommerce_product_loop_start(); ?>

        <?php while ( $products->have_posts() ) : $products->the_post(); ?>

            <?php wc_get_template_part( 'content', 'product' ); ?>

        <?php endwhile; // end of the loop. ?>

    <?php woocommerce_product_loop_end(); ?>

    <?php
} else {
    do_action( "woocommerce_shortcode_products_loop_no_results", $atts );
    echo "<p>Aucun article disponible à la précommande.</p>";
}

woocommerce_reset_loop();
wp_reset_postdata();

return '<div class="woocommerce columns-' . $atts['columns'] . '">' . ob_get_clean() . '</div>';     

Any help is welcome.

There are some errors and missing things in your code, use instead the following revisited code:

if( ! function_exists('get_preordable_products') ) {

    function get_preordable_products( $atts ) {
        // Shortcode Attributes
        extract( shortcode_atts( array(
            'columns'    => '4',
            'limit'      => '20',
            'preordable' => "yes",
            'stock'      => 0,
        ), $atts, 'preordable_products' ) );

        // The WP_Query
        $query = new WP_Query( array (
            'post_type'         => 'product_variation',
            'post_status'       => 'publish',
            'posts_per_page'    => $limit,
            'meta_query'        => array(
                'relation'      => 'AND',
                'preordable'  => array(
                    'key'       =>'_ab_preorder_checkbox',
                    'value'     => "yes",
                    'compare'   => '=='
                ),
                array(
                    'key'       =>'_stock',
                    'value'     => 0,
                    'compare'   => '<='
                ),
            )
        ) );

        global $woocommerce_loop;

        $woocommerce_loop['columns']      = $columns;
        $woocommerce_loop['is_shortcode'] = 1;
        $woocommerce_loop['name']         = 'preordable_products';
        $woocommerce_loop['total']        = $query->post_count;
        $woocommerce_loop['total_pages']  = $query->max_num_pages;
        $woocommerce_loop['per_page']     = $limit;

        ob_start();

        if ( $query->have_posts() ) {
            woocommerce_product_loop_start();

            while ( $query->have_posts() ) {
                $query->the_post();
                wc_get_template_part( 'content', 'product' );
            }
            woocommerce_product_loop_end();
            woocommerce_reset_loop();
            wp_reset_postdata();
        } else {
            do_action( "woocommerce_shortcode_products_loop_no_results", $atts );

            echo '<p>'. __("Aucun article disponible à la précommande.") . '</p>';
        }

        $content = ob_get_clean();

        return '<div class="woocommerce columns-' . $columns . '">' . $content . '</div>';
    }

    add_shortcode( 'preordable_products', 'get_preordable_products' );
}

Code goes in functions.php file of the active child theme (or active theme). Tested and works.

Usage: [preordable_products] or in Php code echo do_shortcode('[preordable_products]');

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM