代码克隆Elementor页面后前端布局异常的原因及自动修复方案
问题
我开发了一个插件,用来克隆由Elementor创建的WordPress页面(下称原页面)。激活插件后页面已完整复制,但访问克隆页面时布局与原页面不一致;然而在Elementor编辑器中打开克隆页面,其结构完全保留且与原页面一致。
我已检查_postmeta表,克隆页面的meta_keys与原页面一致,meta_value字段值也完全相同。
另外发现,若编辑克隆页面并保存后,前端显示就与原页面一致,但我希望克隆时自动实现这一效果,无需手动操作。
附当前克隆代码:
function duplicate_page_111_as_draft( $new_status, $old_status, $post ) { global $wpdb; if ( 'sda_churches' === $post->post_type && $new_status === 'publish' && $old_status !== 'publish' ) { $original_post_id = 111; // ID of the page you want to duplicate // Get the original post data $post = get_post($original_post_id); // Set the new post author (optional, you can customize as needed) $new_post_author = $post->post_author; // Create an array with new post data $args = array( 'comment_status' => $post->comment_status, 'ping_status' => $post->ping_status, 'post_author' => $new_post_author, 'post_content' => $post->post_content, 'post_excerpt' => $post->post_excerpt, 'post_name' => $post->post_name . '-copy', // You may want to adjust this to avoid conflicts 'post_parent' => $post->post_parent, 'post_password' => $post->post_password, 'post_status' => 'publish', 'post_title' => $post->post_title . ' Copy', // You may want to adjust this to avoid conflicts 'post_type' => $post->post_type, 'to_ping' => $post->to_ping, 'menu_order' => $post->menu_order ); // Insert the new post $new_post_id = wp_insert_post($args); // Duplicate all post terms and set them to the new post draft $taxonomies = get_object_taxonomies($post->post_type); foreach ($taxonomies as $taxonomy) { $post_terms = wp_get_object_terms($original_post_id, $taxonomy, array('fields' => 'slugs')); wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false); } // Duplicate all post meta in two SQL queries $post_meta_infos = $wpdb->get_results("SELECT meta_key, meta_value FROM $wpdb->postmeta WHERE post_id=$original_post_id"); if (count($post_meta_infos) != 0) { $sql_query = "INSERT INTO $wpdb->postmeta (post_id, meta_key, meta_value) "; foreach ($post_meta_infos as $meta_info) { $meta_key = $meta_info->meta_key; if ($meta_key == '_wp_old_slug') continue; $meta_value = addslashes($meta_info->meta_value); $sql_query_sel[] = "SELECT $new_post_id, '$meta_key', '$meta_value'"; } $sql_query .= implode(" UNION ALL ", $sql_query_sel); $wpdb->query($sql_query); } } } add_action( 'transition_post_status', 'duplicate_page_111_as_draft', 10, 3 );
原因分析
Elementor页面前端展示依赖缓存的静态CSS文件和内部的_elementor_assets_hash元数据加载对应样式。直接复制元数据后,克隆页面的哈希值和原页面一致,但Elementor资产系统会认为该哈希对应原页面的缓存,不会为克隆页面关联新缓存;而手动保存页面时,Elementor会重新生成哈希并绑定新的缓存资源,前端就能正常加载样式。
另外,用SQL直接复制元数据可能存在序列化格式问题(比如addslashes处理序列化数据会破坏原有结构),即使表面看元数据一致,实际可能存在隐形错误。
解决方案
改用WordPress官方函数复制元数据避免序列化问题,同时调用Elementor内置函数触发资产重新生成,模拟手动保存的效果。
修改后的代码如下:
function duplicate_page_111_as_draft( $new_status, $old_status, $post ) { global $wpdb; if ( 'sda_churches' === $post->post_type && $new_status === 'publish' && $old_status !== 'publish' ) { $original_post_id = 111; // 要克隆的页面ID $original_post = get_post($original_post_id); if ( !$original_post ) return; // 设置新文章数据 $args = array( 'comment_status' => $original_post->comment_status, 'ping_status' => $original_post->ping_status, 'post_author' => $original_post->post_author, 'post_content' => $original_post->post_content, 'post_excerpt' => $original_post->post_excerpt, 'post_name' => $original_post->post_name . '-copy', 'post_parent' => $original_post->post_parent, 'post_password' => $original_post->post_password, 'post_status' => 'publish', 'post_title' => $original_post->post_title . ' Copy', 'post_type' => $original_post->post_type, 'to_ping' => $original_post->to_ping, 'menu_order' => $original_post->menu_order ); // 插入新文章 $new_post_id = wp_insert_post($args); if ( is_wp_error($new_post_id) ) return; // 复制分类法 $taxonomies = get_object_taxonomies($original_post->post_type); foreach ($taxonomies as $taxonomy) { $post_terms = wp_get_object_terms($original_post_id, $taxonomy, array('fields' => 'slugs')); wp_set_object_terms($new_post_id, $post_terms, $taxonomy, false); } // 复制元数据:用WordPress官方函数,避免SQL序列化问题 $post_meta = get_post_meta($original_post_id); foreach ( $post_meta as $meta_key => $meta_values ) { if ( $meta_key === '_wp_old_slug' ) continue; foreach ( $meta_values as $meta_value ) { // 反序列化后重新保存,确保格式正确 $unserialized = maybe_unserialize($meta_value); update_post_meta($new_post_id, $meta_key, $unserialized); } } // 触发Elementor重新生成资产哈希和缓存 if ( class_exists('Elementor\Core\Files\CSS\Post') ) { $elementor_css = new \Elementor\Core\Files\CSS\Post($new_post_id); $elementor_css->update(); // 更新Elementor的资产哈希元数据 update_post_meta($new_post_id, '_elementor_assets_hash', wp_generate_password(12, false)); } } } add_action( 'transition_post_status', 'duplicate_page_111_as_draft', 10, 3 );
内容的提问来源于stack exchange,提问作者Ed Dias
相关产品推荐
相关产品推荐

