Ошибка при перемещении папки загрузок
Похоже, я столкнулся с ошибкой в WordPress, которая связана с директорией wp-content/uploads. Хотя я не утверждаю, что это ошибка, логики явно не хватает…
Давайте разберёмся по порядку. У меня есть старый сайт на WP версии 2+. Когда я его создавал, я переместил папку uploads в корень сайта. Для этого я добавил константу в wp-config.php:
// это означает, что папка "uploads" должна быть в корне сайта
define( 'UPLOADS', 'uploads' );
Я также переименовал папку wp-content в content. Для этого я добавил следующие константы в тот же файл wp-config.php:
define( 'WP_CONTENT_DIR', $_SERVER['DOCUMENT_ROOT'].'/content' );
define( 'WP_CONTENT_URL', 'http://'. $_SERVER['HTTP_HOST'] .'/content' );
Всё работало до недавнего времени…
Я недавно переместил ядро WordPress в отдельную папку wp — это удобно. Теперь у меня такая структура: ядро WP в папке wp, плагины и прочее в папке content, файлы в uploads, и всё это в корне сайта.
В WordPress можно логически разделить файлы контента (wp-content) и файлы ядра (wp-includes, wp-admin и т.д.). Это настраивает два разных URL в настройках: адрес сайта и адрес WordPress.

После перемещения ядра WordPress у меня пропали изображения из медиатеки. Посмотрев на URL изображений, я заметил, что он изменился с /uploads на /wp/uploads, при этом установленная ранее константа UPLOADS не изменилась.
Взглянув на код функции _wp_upload_dir() (эта функция отвечает за получение всех ссылок на файлы), я увидел, что URL строится из константы UPLOADS и опции siteurl, а путь создаётся следующим образом:
if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option('ms_files_rewriting' ) ) ) {
$dir = ABSPATH . UPLOADS;
$url = trailingslashit( $siteurl ) . UPLOADS;
}
Это означает, что основа берётся не из корня сайта, а из директории, где находится ядро WordPress. Если это подпапка, то UPLOADS будет ссылаться на эту директорию. Это не логично, так как файлы загрузок — это контент сайта, а не его движок!
В таком случае, поскольку мы не можем задать константу UPLOADS так, чтобы загружаемые файлы ссылались на корень сайта, мне пришлось удалить её. Я удалил константу UPLOADS из wp-config.php, а затем переместил папку uploads в папку content.
В результате общая структура стала следующей:
/wp/wp-admin
/wp/wp-includes
/content
/content/uploads
После этого, чтобы проверить, всё ли работает правильно, я попытался загрузить изображение в медиатеку, но оно не загрузилось в ожидаемую папку: /content/uploads/..., а оказалось в той же подпапке движка: /wp/uploads/....
Расследование показало, что в настройках WP установлена опция upload_path, которая с версии 3.0 не является обязательной и не устанавливается по умолчанию. А у меня там было значение uploads, которое я однажды указал в константе UPLOADS.
Чтобы решить проблему, я просто удалил опцию upload_path. Затем заменил все старые ссылки в контенте на новые. Для этого я выполнил следующий SQL-запрос:
UPDATE wp_posts SET post_content = REPLACE (post_content, 'http://example.com/uploads/', 'http://example.com/content/uploads/');
На всякий случай я перестроил все значения полей guid для вложений, для этого я создал мини-плагин.
В чём дело?
Суть в том, что если вы перемещаете базовые папки WordPress на своём старом сайте, вам нужно зайти на страницу всех настроек: http://YOURSITE/wp-admin/options.php и проверить, есть ли у вас опции upload_path и upload_url_path. Они на 99% не нужны с версии WP 3.0+ и могут быть просто удалены.
В тех случаях, когда они вам действительно нужны, вы, скорее всего, уже знаете об этом, и эта статья вам не интересна. 😊
Также не пытайтесь перемещать папку uploads за пределы папки контента (по умолчанию wp-contents). Вы не сможете этого сделать, если файлы движка WordPress помещены в отдельную директорию. Это вызовет проблемы, если вы в будущем решите переместить файлы движка в отдельную папку.
Я упомянул выше, что опции не нужны в 99% случаев, но есть 1%, когда опция upload_url_path нужна — это когда у нас включён мультисайт и мы перенесли папку контента или ядро WP. В обоих случаях нам нужно задать константу WP_CONTENT_URL. Дальше, когда мы переключаемся между блогами в одной сети с помощью switch_to_blog(), возникает ошибка, так как во многих функциях, например, для получения URL изображения (смотрите wp_get_attachment_url() и _wp_upload_dir()), WordPress использует константу WP_CONTENT_URL, которая будет ссылаться на текущий блог, а не на тот, на который мы переключились. Вот здесь-то и нужна опция upload_url_path, так как её значение проверяется первым, и только затем используется константа, если опция пуста.
Следует отметить, что URL загруженных файлов, даже если константа WP_CONTENT_URL установлена, по-прежнему работает при переключении на другой блог. Однако домен этого URL будет первичным, а не текущего сайта, на который мы переключились.