如何将Elementor设计的WooCommerce产品页复制到自定义文章类型并保留结构
问题:Elementor产品页复制到自定义文章类型后丢失结构
我用Elementor、WooCommerce和自定义文章类型edit-invitation搭建在线邀请网站,需求是订单完成时自动将Elementor设计的WooCommerce产品页复制到edit-invitation类型文章中。目前复制后内容能正常显示、样式也没问题,但所有Elementor区块、列、小部件都合并成了单个Text Editor小部件,无法保留原结构,也不能在Elementor编辑器里正常编辑。
已尝试的操作
- 自定义PHP复制代码:在
functions.php中添加订单完成触发的复制逻辑,代码如下:
function rudr_complete_for_status($order_id) { $order = wc_get_order($order_id); $order_key = $order->get_order_key(); foreach ($order->get_items() as $item_id => $item) { $product = $item->get_product(); if ($product) { $product_id = $product->get_id(); $elementor_data = get_post_meta($product_id, '_elementor_data', true); wp_insert_post(array( 'post_type' => 'edit-invitation', 'post_content' => \Elementor\Plugin::$instance->frontend->get_builder_content($product_id), 'post_title' => '#' . $order->get_id() . ' - ' . $order->get_billing_first_name(), 'post_status' => 'publish', 'meta_input' => array( '_elementor_data' => $elementor_data, '_elementor_edit_mode' => 'builder', '_elementor_template_type' => 'page', 'product_id' => $product_id, ) )); } } } add_action('woocommerce_order_status_completed', 'rudr_complete_for_status');
- 自定义CPT模板:创建
single-edit-invitation.php模板展示内容:
<?php if (have_posts()) : while (have_posts()) : the_post(); ?> <div id="content-wrapper"> <?php the_content(); ?> </div> <?php endwhile; endif; ?>
- 加载Elementor CSS:为自定义文章类型加载对应产品的Elementor样式:
if (is_singular('edit-invitation')) { $product_id = get_post_meta($post->ID, 'product_id', true); if ($product_id) { $elementor_css_path = wp_upload_dir()["baseurl"] . '/elementor/css/post-' . $product_id . '.css'; wp_enqueue_style('elementor-product-styles', $elementor_css_path); } }
解决方案
问题核心是你设置了post_content为get_builder_content()返回的HTML内容,Elementor会将其识别为普通文本,自动塞进Text Editor小部件。要保留原结构,需完全模拟Elementor的存储逻辑,同时确保Elementor能识别自定义文章类型。
步骤1:修改复制代码,移除post_content并完善元数据
更新functions.php中的复制函数,避免写入HTML内容,直接完整复制Elementor元数据:
function rudr_complete_for_status($order_id) { $order = wc_get_order($order_id); foreach ($order->get_items() as $item_id => $item) { $product = $item->get_product(); if (!$product) continue; $product_id = $product->get_id(); // 复制所有Elementor相关元数据 $elementor_meta = get_post_meta($product_id); $filtered_meta = array(); foreach ($elementor_meta as $key => $value) { if (str_starts_with($key, '_elementor')) { $filtered_meta[$key] = maybe_unserialize($value[0]); } } // 添加自定义产品ID元数据 $filtered_meta['product_id'] = $product_id; // 创建新文章,留空post_content $new_post_id = wp_insert_post(array( 'post_type' => 'edit-invitation', 'post_title' => '#' . $order->get_id() . ' - ' . $order->get_billing_first_name(), 'post_status' => 'publish', 'post_content' => '', // 关键:让Elementor用元数据渲染内容 )); // 批量写入元数据 foreach ($filtered_meta as $key => $value) { update_post_meta($new_post_id, $key, $value); } } } add_action('woocommerce_order_status_completed', 'rudr_complete_for_status');
步骤2:确保自定义文章类型支持Elementor
注册edit-invitation时,必须添加supports和show_in_rest参数,让Elementor识别该类型:
function register_edit_invitation_cpt() { $args = array( 'public' => true, 'label' => '编辑邀请', 'supports' => array('title', 'editor'), // 必须支持editor 'show_in_rest' => true, // 支持REST API,Elementor依赖此 'show_in_elementor' => true, // 明确声明支持Elementor编辑 ); register_post_type('edit-invitation', $args); } add_action('init', 'register_edit_invitation_cpt');
如果已注册过该CPT,检查并补充上述参数。
步骤3:优化CPT模板,优先用Elementor渲染
修改single-edit-invitation.php,直接调用Elementor的渲染函数:
<?php if (have_posts()) : while (have_posts()) : the_post(); ?> <div id="content-wrapper"> <?php // 优先用Elementor渲染内容 if (\Elementor\Plugin::$instance->db->is_built_with_elementor(get_the_ID())) { echo \Elementor\Plugin::$instance->frontend->get_builder_content(get_the_ID()); } else { the_content(); } ?> </div> <?php endwhile; endif; ?>
步骤4:修复样式加载(可选)
用Elementor官方方法获取CSS路径,避免路径错误:
add_action('wp_enqueue_scripts', 'enqueue_edit_invitation_styles'); function enqueue_edit_invitation_styles() { if (is_singular('edit-invitation')) { $post_id = get_the_ID(); $product_id = get_post_meta($post_id, 'product_id', true); if ($product_id) { $css_file = \Elementor\Core\Files\CSS\Post::create($product_id); if ($css_file->exists()) { wp_enqueue_style( 'elementor-product-' . $product_id, $css_file->get_url(), array('elementor-frontend'), $css_file->get_modified_time() ); } } } }
内容的提问来源于stack exchange,提问作者Hendra
相关产品推荐
相关产品推荐

