Баг с перемещением папки uploads
Похоже напоролся на баг в WordPress, который связан с каталогом загрузок wp-content/uploads
. Хотя утверждать что это баг я не буду, но логика точно отсутствует...
Разберемся по порядку, дело было так: есть у меня старый сайт, который работает еще с версии WP 2+. При его создании я переместил папку файлов uploads
в корень сайта. Для этого определил константу в wp-config.php
:
define( 'UPLOADS', 'uploads'); // значит что папка uploads должна лежать в корне сайта
Также, переименовал папку контента с wp-content
на content
. Для этого определил константы в том же wp-config.php
:
define( 'WP_CONTENT_DIR', __DIR__ . '/content' ); define( 'WP_CONTENT_URL', 'http://' . $_SERVER['HTTP_HOST'] . '/content' );
Все работало до недавнего времени.
Недавно я переместил ядро WordPress в отдельную папку wp
- это удобно. Теперь, получилось: ядро лежит в папке wp
, плагины и т.д. в content
и файлы в uploads
и все это в корне сайта.
Для тех кто не знает, в WordPress можно логически разделить файлы содержимого (wp-content) и файлы движка (wp-includes, wp-admin, ...). При этом в настройках устанавливаются два разных УРЛ: адрес сайта (home) и адрес WordPress (siteurl):

После перемещения ядра WordPress, в медиатеке у меня пропали картинки. Посмотрев на УРЛ картинок я увидел что УРЛ изменился с /uploads
на /wp/uploads
при этом я не менял ранее установленную константу UPLOADS
.
Заглянув в код _wp_upload_dir() (эта функцию лежит в основе получения всех ссылок на файлы) увидел, что ссылка (url) строиться из объединения UPLOADS
с опцией siteurl
, а путь (path) строиться так: ABSPATH . UPLOADS
.
if ( defined( 'UPLOADS' ) && ! ( is_multisite() && get_site_option( 'ms_files_rewriting' ) ) ) { $dir = ABSPATH . UPLOADS; $url = trailingslashit( $siteurl ) . UPLOADS; }
Это значит что за основу берется не корень сайта, а папка где находится ядро WordPress, и если это вложенный каталог, то UPLOADS будет относится уже к этому каталогу. Это не логично, потому что едва ли можно отнести папку с файлами сайта к ядру системы - это контент сайта!
OK, раз нельзя определить константу 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://ВАШСАЙТ/wp-admin/options.php
и проверьте не установлены ли у вас опции upload_path
и upload_url_path
они в 99% случаев не нужны с версии WP 3.0+ и их можно просто удалить. К слову на этом блоге они тоже были и я их удалил...
В тех случаях, когда они нужны, вы скорее все будите знать об этом и эта статья будет вам не интересна
Также, не пытайтесь перенести папку uploads
за пределы папки контента (по умолчанию wp-content):
- это не получится, если WP вынесен в отдельную папку
- или это вызовет проблемы, если в будущем вы захотите вынести файлы движка в отдельную папку.
Выше упомянул что опции нужны в 99%, но есть 1% когда опция upload_url_path
нужна - это когда у нас включен мультисайт и мы переместили папку контента или ядро ВП. В обоих случаях нам придется установить константу WP_CONTENT_URL. Далее, при переключении в одном блоге сети на другой с помощью switch_to_blog(). Мы поймаем баг, потому что во многих функциях, например получение URL картинки (см. wp_get_attachment_url() и _wp_upload_dir()) ВП использует константу WP_CONTENT_URL, а она при переключении будет относится к текущему блогу, а не к тому на который переключились. Вот для таких случаев нужна опция upload_url_path
, потому что сначала проверяется её значение и только потом используется константа, если в опции пусто.
Обращу еще внимание на то, что Url на загруженные файлы даже при установленной константе WP_CONTENT_URL, все равно остается рабочим при переключении на другой блог. Только домен этого URL будет основной, а не текущего сайта на который переключились.