【问题标题】:WooCommerce do_action in shortcode is messing up page layout简码中的 WooCommerce do_action 弄乱了页面布局
【发布时间】:2021-01-03 08:11:08
【问题描述】:

我创建了一个短代码来显示特定产品类别的产品(结合一些 ACF 字段)。一切都很好,所以为了你自己的利益使用下面的代码。

短代码如下所示:[yl_get_products cat_id='51' order='ASC' template='1'] 如您所见,我添加了 template='1' 以便您以后可以根据需要添加新布局。

好的,那我有什么问题: 当我想添加 ADD-TO-CART 按钮(连同我的产品插件)时,我需要类似:

do_action( 'woocommerce_' . $product->get_type() . '_add_to_cart' ); 在我的简码中。

do_action( 'woocommerce_single_product_summary' );(然后删除所有不需要的操作)

结果是它确实显示了带有附加选项等的整个添加到购物车的输出,但它始终显示在页面顶部(而不是模式),并且任何页面样式都被完全忽略。

我相信我以前有过这种情况,我认为它必须与 echo return return = return .= 做某事,但我无法正确理解。

所以我的实际问题是:
如何在我的产品循环短代码中为上述操作添加一个而不弄乱布局?

这是我的代码:

// Get a dish category via shortcode
function yl_get_products_shortcode( $atts ) {

    $atts = shortcode_atts( array(
        'cat_id'    => '',
        'orderby'   => '',
        'order'     => '',
        'template'  => '',
    ), $atts );

    $products = new WP_Query(array(
        'post_type'         => 'product',
        'tax_query'         => array( array(
            'taxonomy'          => 'product_cat',
            'field'             => 'term_id',
            'terms'             => $atts['cat_id'],
            // 'include_children' => false // or true (optional)
        )),
        'orderby'           => $atts['orderby'],
        'order'             => $atts['order'],
        'post_status'       => 'publish',
        'posts_per_page'    => -1
    ));

    if ( $products->have_posts() ) {

        while ( $products->have_posts() ) {

            $products->the_post();

            if ($atts['template'] == '1') {

                global $product;
                $id                 = get_the_ID();
                $product            = wc_get_product( $id );

                $name               = $product->get_title();
                $short_description  = $product->get_short_description();
                $description        = $product->get_description();
                $rating_count       = $product->get_rating_count();
                $rating_average     = number_format($product->get_average_rating() * 20, 0) . '%';
                $review_count       = $product->get_review_count();
                $price              = $product->get_price();
                $image_url          = wp_get_attachment_url( $product->get_image_id() );

                $description_nl     = get_field('description_nl');
                $title_en           = get_field('title_en');
                $description_en     = get_field('description_en');
                $allergens          = get_field('allergens');
                $specifics          = get_field('specifics');

                $output .= '
                <li>
                    <div class="uk-grid-small" uk-grid>';
                        if ($product->is_in_stock()) {
                            $output .= '
                            <div class="uk-width-auto">
                                <a href="#product-' . $id . '" class="uk-button uk-button-small uk-button-primary" uk-toggle>
                                        <span uk-icon="icon: cart"></span>
                                </a>
                            </div>';
                        }
                        if (!empty($allergens)) {
                            $output .= '
                            <div class="uk-width-auto">
                                <a href="#allergens-' . $id . '" uk-toggle>
                                    <span uk-icon="icon: info"></span>
                                </a>
                            </div>';
                        }
                        $output .= '
                        <div class="uk-width-expand">
                            <p class="uk-h6 uk-margin-remove">
                                ' . $name;
                                if (!empty($specifics)) {
                                    foreach ($specifics as $specific) {
                                        $output .= '
                                        <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' .  $specific . '">';
                                    }
                                }
                            $output .= '
                            </p>
                            <p class="uk-margin-remove">
                                ' . $description_nl;
                                if ($short_description) {
                                    $output .= '<br />' . $short_description;
                                }
                            $output .= '
                            </p>
                        </div>
                        <div class="uk-width-auto uk-h6">
                            € ' . $price . '
                        </div>
                    </div>';

                    if (!empty($allergens) || !empty($specifics)) {
                        $output .= '
                        <div id="allergens-' . $id . '" uk-modal="center: true">
                            <div class="uk-modal-dialog uk-modal-body">
                                <button class="uk-modal-close-default" type="button" uk-close></button>
                                <h3 class="uk-modal-title uk-margin-small uk-text-truncate">
                                    ' . $name;
                                    if (!empty($specifics)) {
                                        foreach ($specifics as $specific) {
                                            $output .= '
                                            <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' . $specific . '">';
                                        }
                                    }
                                $output .= '
                                </h3>
                                <p class="uk-margin-small">' . __( 'Below you will find an overview of the allergens that are in this dish. For more information you can always contact our service staff.', 'yorlinq' ) . '</p>
                                <div uk-alert>
                                    <div class="uk-grid-small uk-child-width-1-2@s" uk-grid>';
                                        foreach ($allergens as $allergen) {
                                            $output .= '
                                            <div>
                                                <div class="uk-grid-small uk-flex-middle" uk-grid>
                                                    <div class="uk-width-1-4">
                                                        <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $allergen) . '.svg">
                                                    </div>
                                                    <div class="uk-width-3-4">
                                                        ' . $allergen . '
                                                    </div>
                                                </div>
                                            </div>';
                                        }
                                    $output .= '
                                    </div>
                                </div>
                            </div>
                        </div>';
                    }

                    if ($product->is_in_stock()) {
                        $output .= '
                        <div id="product-' . $id . '" uk-modal="center: true">
                            <div class="uk-modal-dialog uk-modal-body">
                                <button class="uk-modal-close-default" type="button" uk-close></button>
                                <h3 class="uk-modal-title uk-margin-small uk-text-truncate">
                                    ' . $name;
                                    if (!empty($specifics)) {
                                        foreach ($specifics as $specific) {
                                            $output .= '
                                            <img src="/wp-content/uploads/network/images/food-icons/icon-' . str_replace(' ', '-', $specific) . '.svg" width="16" uk-tooltip="' . $specific . '">';
                                        }
                                    }
                                $output .= '
                                </h3>
                                ' . $description;
                        
                                // Here is where the action sould appear
                        
                            $output .= '
                            </div>
                        </div>';
                    }
                $output .= '
                </li>';

            }

        };

        return '<ul class="uk-list uk-list-divider">' . $output . '</ul>';

    }

}

add_shortcode('yl_get_products','yl_get_products_shortcode');

【问题讨论】:

    标签: php wordpress woocommerce action shortcode


    【解决方案1】:

    我建议使用output bufferecho 输出存储为字符串。存储的内容可以很容易地附加到简码输出中:

    function yl_get_products_shortcode( $atts ) {
    //  ... your logic
    
        add_action( 'woocommerce_' . $product->get_type() . '_add_to_cart', function () {
    //      You could remove any action you want
    //      remove_action( 'xxx', 'xxx', priority );
        }, 1 );
    
        ob_start();
        do_action( 'woocommerce_' . $product->get_type() . '_add_to_cart' );
        $add_to_cart_content = ob_get_clean();
    
        return '<ul class="uk-list uk-list-divider">' . $output . '</ul>' . $add_to_cart_content;
    }
    

    【讨论】: