如何用PHP脚本在WordPress中程序化添加Gallery区块
WordPress 6 第三方画廊插件迁移至Gutenberg Gallery区块完整方案
以下是针对你需求的分步实现方案,包含代码示例和关键细节:
1. 将下载的图片注册为WordPress媒体附件
首先需要把本地下载的图片导入WP媒体库,生成对应的attachment类型文章及元数据,这是后续关联Gallery区块的基础:
function import_image_as_attachment( $local_file_path, $parent_post_id, $alt_text = '', $title = '' ) { // 获取文件类型信息 $filetype = wp_check_filetype( basename( $local_file_path ), null ); $filename = basename( $local_file_path ); // 构造attachment数组 $attachment = array( 'post_mime_type' => $filetype['type'], 'post_title' => $title ?: sanitize_file_name( $filename ), 'post_content' => '', 'post_status' => 'inherit' ); // 插入attachment $attach_id = wp_insert_attachment( $attachment, $local_file_path, $parent_post_id ); if ( is_wp_error( $attach_id ) ) return $attach_id; // 生成缩略图元数据并更新 require_once( ABSPATH . 'wp-admin/includes/image.php' ); $attach_data = wp_generate_attachment_metadata( $attach_id, $local_file_path ); wp_update_attachment_metadata( $attach_id, $attach_data ); // 设置图片alt文本 if ( $alt_text ) { update_post_meta( $attach_id, '_wp_attachment_image_alt', $alt_text ); } return $attach_id; }
说明:
- 该函数会自动生成所有WP预设尺寸的缩略图
- 返回值为新创建的附件ID,用于后续构建Gallery区块
2. 处理视频附件(如需支持)
核心Gallery区块仅支持图片,若需添加视频,需单独注册为video类型附件,并使用独立的wp:video区块:
function import_video_as_attachment( $local_file_path, $parent_post_id, $title = '' ) { $filetype = wp_check_filetype( basename( $local_file_path ), null ); $filename = basename( $local_file_path ); $attachment = array( 'post_mime_type' => $filetype['type'], 'post_title' => $title ?: sanitize_file_name( $filename ), 'post_content' => '', 'post_status' => 'inherit' ); $attach_id = wp_insert_attachment( $attachment, $local_file_path, $parent_post_id ); if ( is_wp_error( $attach_id ) ) return $attach_id; // 更新视频元数据 require_once( ABSPATH . 'wp-admin/includes/media.php' ); $attach_data = wp_generate_attachment_metadata( $attach_id, $local_file_path ); wp_update_attachment_metadata( $attach_id, $attach_data ); return $attach_id; }
3. 构建Gutenberg Gallery区块标记
利用已获取的附件ID,生成符合WP规范的Gallery区块代码:
function build_gallery_block( $image_ids, $link_to = 'none', $size_slug = 'large' ) { // 初始化Gallery区块头部 $gallery_block = sprintf( '<!-- wp:gallery {"linkTo":"%s"} -->', esc_attr( $link_to ) ); $gallery_block .= "\n<figure class=\"wp-block-gallery has-nested-images columns-default is-cropped\">"; // 循环添加每个图片子区块 foreach ( $image_ids as $id ) { $image_src = wp_get_attachment_image_url( $id, $size_slug ); $image_alt = get_post_meta( $id, '_wp_attachment_image_alt', true ); $image_block = sprintf( '<!-- wp:image {"id":%d,"sizeSlug":"%s","linkDestination":"%s"} -->', $id, esc_attr( $size_slug ), esc_attr( $link_to ) ); $image_block .= "\n<figure class=\"wp-block-image size-large\">"; $image_block .= "<img src=\"" . esc_url( $image_src ) . "\" alt=\"" . esc_attr( $image_alt ) . "\" class=\"wp-image-" . $id . "\"/>"; $image_block .= "</figure>\n<!-- /wp:image -->\n\n"; $gallery_block .= $image_block; } // 闭合Gallery区块 $gallery_block .= "</figure>\n<!-- /wp:gallery -->"; return $gallery_block; }
4. 将Gallery区块关联至主文章
可选择替换旧插件的短码,或直接追加到文章内容末尾:
function add_gallery_to_post( $post_id, $gallery_markup, $replace_shortcode = false, $old_shortcode = '' ) { $post = get_post( $post_id ); if ( !$post ) return new WP_Error( 'invalid_post', '文章不存在' ); $new_content = $post->post_content; if ( $replace_shortcode && !empty($old_shortcode) && strpos( $new_content, $old_shortcode ) !== false ) { // 替换旧画廊短码 $new_content = str_replace( $old_shortcode, $gallery_markup, $new_content ); } else { // 追加到文章末尾 $new_content .= "\n\n" . $gallery_markup; } // 更新文章内容 wp_update_post( array( 'ID' => $post_id, 'post_content' => $new_content ) ); return true; }
使用示例:
// 假设已获取图片附件ID数组 $image_ids = array( 166, 168 ); $gallery_markup = build_gallery_block( $image_ids ); // 将画廊添加到ID为123的文章,替换旧插件短码 add_gallery_to_post( 123, $gallery_markup, true, '[third_party_gallery id="456"]' );
5. 混合媒体(图片+视频)区块方案
若需在同一区块中展示图片和视频,可使用wp:columns构建网格布局:
function build_media_grid_block( $media_ids ) { $columns_block = '<!-- wp:columns {"columns":2} -->'; $columns_block .= '<div class="wp-block-columns has-2-columns">'; foreach ( $media_ids as $id ) { $attachment = get_post( $id ); if ( str_starts_with( $attachment->post_mime_type, 'image/' ) ) { // 生成图片区块 $media_markup = sprintf( '<!-- wp:image {"id":%d,"sizeSlug":"large","linkDestination":"none"} -->', $id ); $src = wp_get_attachment_image_url( $id, 'large' ); $alt = get_post_meta( $id, '_wp_attachment_image_alt', true ); $media_markup .= "\n<figure class=\"wp-block-image size-large\"><img src=\"" . esc_url( $src ) . "\" alt=\"" . esc_attr( $alt ) . "\" class=\"wp-image-" . $id . "\"/></figure>"; $media_markup .= "\n<!-- /wp:image -->"; } elseif ( str_starts_with( $attachment->post_mime_type, 'video/' ) ) { // 生成视频区块 $media_markup = sprintf( '<!-- wp:video {"id":%d} -->', $id ); $src = wp_get_attachment_url( $id ); $media_markup .= "\n<figure class=\"wp-block-video\"><video controls src=\"" . esc_url( $src ) . "\"></video></figure>"; $media_markup .= "\n<!-- /wp:video -->"; } // 添加到列中 $columns_block .= "\n<!-- wp:column -->\n<div class=\"wp-block-column\">" . $media_markup . "\n</div>\n<!-- /wp:column -->"; } $columns_block .= '</div>\n<!-- /wp:columns -->'; return $columns_block; }
批量迁移注意事项
- 避免超时:对于大型站点,建议将迁移逻辑封装为WP CLI命令
- 错误日志:使用
error_log()记录迁移失败的条目 - 测试环境验证:先在 staging 站点完成测试,再部署到生产环境
- 清理旧数据:迁移完成后可删除旧插件的文章元数据和短码
内容的提问来源于stack exchange,提问作者Amar
相关产品推荐
相关产品推荐

