При работе с WordPress Multisite часто возникает необходимость использовать одну медиабиблиотеку для всех подсайтов сети. По умолчанию каждый подсайт имеет собственную изолированную папку для медиафайлов (/wp-content/uploads/sites/{blog_id}/), что создает дублирование и усложняет управление контентом.
Проблема
В стандартной настройке WordPress Multisite:
- Основной сайт использует папку
/wp-content/uploads/ - Подсайты используют
/wp-content/uploads/sites/{site_id}/ - Каждый сайт имеет отдельные таблицы для медиа:
wp_posts,wp_2_posts,wp_3_postsи т.д.
Это приводит к тому, что медиафайлы, загруженные на основной сайт, недоступны на подсайтах, и наоборот.
Решение 1: Символические ссылки
ln -s /path/to/wp-content/uploads /path/to/wp-content/uploads/sites/2
Решение 2: плагин для исправления URL
Основная проблема заключается в том, что WordPress генерирует неправильные URL для медиафайлов на подсайтах. Создайте плагин для исправления этой проблемы:
<?php
/*
Plugin Name: Fix Multisite Media URLs
Description: Исправляет URL медиафайлов на подсайтах Multisite
Version: 1.0.0
Network: true
*/
if (!defined('ABSPATH')) {
exit;
}
class FixMultisiteMediaUrls {
public function __construct() {
if (!is_multisite()) {
return;
}
add_filter('wp_get_attachment_url', [$this, 'fix_attachment_url'], 10, 2);
add_filter('wp_get_attachment_image_src', [$this, 'fix_attachment_image_src'], 10, 4);
add_filter('upload_dir', [$this, 'fix_upload_dir']);
add_filter('the_content', [$this, 'fix_content_urls']);
add_filter('rest_prepare_attachment', [$this, 'fix_rest_api_urls'], 10, 3);
}
/**
* Исправляет URL вложений, убирая /sites/{blog_id}/ из путей
*/
public function fix_attachment_url(string $url, int $post_id): string {
if (is_main_site() || defined('WPM_TRANSLATION_PROCESSING')) {
return $url;
}
$blog_id = get_current_blog_id();
$pattern = '/\/sites\/' . $blog_id . '\//';
return preg_replace($pattern, '/', $url);
}
/**
* Исправляет источники изображений
*/
public function fix_attachment_image_src($image, int $attachment_id, $size, bool $icon) {
if (is_main_site() || !$image || defined('WPM_TRANSLATION_PROCESSING')) {
return $image;
}
if (is_array($image) && isset($image[0])) {
$image[0] = $this->fix_attachment_url($image[0], $attachment_id);
}
return $image;
}
/**
* Направляет загрузку файлов в общую папку
*/
public function fix_upload_dir(array $dirs): array {
if (is_main_site() || defined('WPM_TRANSLATION_PROCESSING')) {
return $dirs;
}
switch_to_blog(1);
$main_dirs = wp_upload_dir();
restore_current_blog();
return $main_dirs;
}
/**
* Исправляет URL в контенте постов
*/
public function fix_content_urls($content) {
if (is_main_site() || defined('WPM_TRANSLATION_PROCESSING')) {
return $content;
}
$blog_id = get_current_blog_id();
$pattern = '/\/wp-content\/uploads\/sites\/' . $blog_id . '\//';
$replacement = '/wp-content/uploads/';
return preg_replace($pattern, $replacement, $content);
}
/**
* Исправляет URL в REST API для Gutenberg
*/
public function fix_rest_api_urls($response, $post, $request) {
if (is_main_site() || defined('WPM_TRANSLATION_PROCESSING')) {
return $response;
}
$data = $response->get_data();
if (isset($data['source_url'])) {
$blog_id = get_current_blog_id();
$pattern = '/\/sites\/' . $blog_id . '\//';
$data['source_url'] = preg_replace($pattern, '/', $data['source_url']);
}
if (isset($data['media_details']['sizes'])) {
foreach ($data['media_details']['sizes'] as $size => $details) {
if (isset($details['source_url'])) {
$blog_id = get_current_blog_id();
$pattern = '/\/sites\/' . $blog_id . '\//';
$data['media_details']['sizes'][$size]['source_url'] =
preg_replace($pattern, '/', $details['source_url']);
}
}
}
$response->set_data($data);
return $response;
}
}
new FixMultisiteMediaUrls();
Плагин перехватывает генерацию URL медиафайлов на подсайтах и исправляет их:
До:
https://ru.yoursite.com/wp-content/uploads/<strong>sites/2</strong>/2025/01/image.jpg
После:
https://ru.yoursite.com/wp-content/uploads/2025/01/image.jpg
Диагностика проблем
Если медиафайлы не отображаются, проверьте:
1. Структуру базы данных
-- Проверьте существование подсайтов
SELECT blog_id, domain, path FROM wp_blogs;
-- Проверьте наличие медиа в таблицах
SELECT COUNT(*) FROM wp_posts WHERE post_type = 'attachment';
SELECT COUNT(*) FROM wp_2_posts WHERE post_type = 'attachment';
2. Пути к файлам
-- Проверьте пути в метаданных
SELECT post_id, meta_key, meta_value
FROM wp_2_postmeta
WHERE meta_key = '_wp_attached_file'
LIMIT 5;
Символические ссылки
Для продвинутых пользователей можно создать symlink:
ln -s /path/to/wp-content/uploads /path/to/wp-content/uploads/sites/2
Ограничения и рекомендации
- Безопасность: Создавайте резервные копии базы данных перед внесением изменений
- Совместимость: Плагин учитывает работу с WP Multilang и другими мультиязычными решениями
- Производительность: При большом количестве медиафайлов рекомендуется поэтапная миграция
- Обновления: Следите за совместимостью при обновлении WordPress
Заключение
Данное решение позволяет использовать единую медиабиблиотеку для всех сайтов в сети WordPress Multisite, избежав дублирования файлов и упростив управление контентом. Плагин автоматически исправляет URL и обеспечивает корректное отображение медиафайлов на всех подсайтах.
Решение протестировано на WordPress версий 5.0+ и совместимо с современными редакторами, включая Gutenberg.