Возможно ли установить изображение записи через внешний URL изображения

20 авг. 2014 г., 10:53:53
Просмотры: 42.5K
Голосов: 25

Я знаю, что существуют плагины, которые загружают изображения с удаленного URL и сохраняют их локально. Мне просто хотелось бы узнать, возможно ли использовать изображение в качестве изображения записи, не сохраняя его в Медиатеке?

4
Комментарии

Вы можете сделать это с помощью пользовательского поля, где будет храниться URL внешнего изображения. Может быть сложно заставить это работать каждый раз при использовании the_post_thumnail() (или аналогичной функции) или при работе с разными размерами изображений, заданными темой или плагином.

cybmeta cybmeta
20 авг. 2014 г. 11:21:22

Вы можете использовать этот плагин, чтобы установить URL внешнего изображения в качестве миниатюры записи: https://wordpress.org/plugins/wp-remote-thumbnail/

Advanced SEO Advanced SEO
20 авг. 2014 г. 11:59:27

Он сохраняет изображение локально или загружает его удалённо?

Volatil3 Volatil3
20 авг. 2014 г. 13:22:22

@Volatil3 Я не тестировал, но, читая описание плагина, могу предположить, что он вызывает это удалённо.

Andy Macaulay-Brook Andy Macaulay-Brook
24 мая 2016 г. 10:48:53
Все ответы на вопрос 1
4
40

Да, это возможно и довольно просто.

Вот рабочий процесс, который я предлагаю:

  1. Добавить интерфейс для ввода URL изображения записи. Лучше всего использовать хук фильтра 'admin_post_thumbnail_html'
  2. Использовать хук действия 'save_post' для сохранения URL (после проверки безопасности и валидации) в произвольном метаполе записи
  3. Использовать хук фильтра 'post_thumbnail_html' для вывода HTML-разметки <img>, переопределяя стандартный вывод, если для записи задано метаполе с внешним изображением

Для работы этого процесса необходимо, чтобы миниатюра записи выводилась в шаблоне с помощью функций get_the_post_thumnbail() или the_post_thumbnail().

Кроме того, мы должны убедиться, что метазначение '_thumbnail_id' не пустое, когда мы устанавливаем метаполе для внешнего URL, иначе функция has_post_thumbnail() будет возвращать false для записей, у которых есть только внешнее изображение записи.

Фактически, запись может иметь как стандартное локальное изображение записи, так и заданное через наш метод, и в этом случае будет использоваться внешнее изображение.

Для реализации нашего процесса нам нужна функция для валидации URL, используемого как внешнее изображение записи, чтобы убедиться, что это корректный URL изображения.

Есть разные способы выполнить эту задачу; здесь я использую очень простой метод, который только проверяет URL, не загружая изображение. Это работает только для статических URL изображений и не проверяет, существует ли изображение на самом деле, но это быстро. Модифицируйте его на что-то более продвинутое, если нужно (здесь есть помощь).

function url_is_image( $url ) {
    if ( ! filter_var( $url, FILTER_VALIDATE_URL ) ) {
        return FALSE;
    }
    $ext = array( 'jpeg', 'jpg', 'gif', 'png' );
    $info = (array) pathinfo( parse_url( $url, PHP_URL_PATH ) );
    return isset( $info['extension'] )
        && in_array( strtolower( $info['extension'] ), $ext, TRUE );
}

Довольно просто. Теперь добавим 3 хука, описанных в рабочем процессе выше:

add_filter( 'admin_post_thumbnail_html', 'thumbnail_url_field' );

add_action( 'save_post', 'thumbnail_url_field_save', 10, 2 );

add_filter( 'post_thumbnail_html', 'thumbnail_external_replace', 10, PHP_INT_MAX );

и соответствующие функции. Сначала та, которая выводит поле в админке:

function thumbnail_url_field( $html ) {
    global $post;
    $value = get_post_meta( $post->ID, '_thumbnail_ext_url', TRUE ) ? : "";
    $nonce = wp_create_nonce( 'thumbnail_ext_url_' . $post->ID . get_current_blog_id() );
    $html .= '<input type="hidden" name="thumbnail_ext_url_nonce" value="' 
        . esc_attr( $nonce ) . '">';
    $html .= '<div><p>' . __('Или', 'txtdomain') . '</p>';
    $html .= '<p>' . __( 'Введите URL внешнего изображения', 'txtdomain' ) . '</p>';
    $html .= '<p><input type="url" name="thumbnail_ext_url" value="' . $value . '"></p>';
    if ( ! empty($value) && url_is_image( $value ) ) {
        $html .= '<p><img style="max-width:150px;height:auto;" src="' 
            . esc_url($value) . '"></p>';
        $html .= '<p>' . __( 'Оставьте URL пустым, чтобы удалить.', 'txtdomain' ) . '</p>';
    }
    $html .= '</div>';
    return $html;
}

Обратите внимание, что я использовал 'txtdomain' как текстовый домен, но вы должны использовать зарегистрированный текстовый домен.

Вот как выглядит вывод, когда поле пустое:

Внешний URL для изображения записи: поле

А так оно выглядит после добавления URL изображения и сохранения/обновления записи:

Внешний URL для изображения записи: поле после заполнения и сохранения

Теперь, когда наш интерфейс админки готов, напишем функцию сохранения:

function thumbnail_url_field_save( $pid, $post ) {
    $cap = $post->post_type === 'page' ? 'edit_page' : 'edit_post';
    if (
        ! current_user_can( $cap, $pid )
        || ! post_type_supports( $post->post_type, 'thumbnail' )
        || defined( 'DOING_AUTOSAVE' )
    ) {
        return;
    }
    $action = 'thumbnail_ext_url_' . $pid . get_current_blog_id();
    $nonce = filter_input( INPUT_POST, 'thumbnail_ext_url_nonce', FILTER_SANITIZE_STRING );
    $url = filter_input( INPUT_POST,  'thumbnail_ext_url', FILTER_VALIDATE_URL );
    if (
        empty( $nonce )
        || ! wp_verify_nonce( $nonce, $action )
        || ( ! empty( $url ) && ! url_is_image( $url ) )
    ) {
        return;
    }
    if ( ! empty( $url ) ) {
        update_post_meta( $pid, '_thumbnail_ext_url', esc_url($url) );
        if ( ! get_post_meta( $pid, '_thumbnail_id', TRUE ) ) {
            update_post_meta( $pid, '_thumbnail_id', 'by_url' );
        }
    } elseif ( get_post_meta( $pid, '_thumbnail_ext_url', TRUE ) ) {
        delete_post_meta( $pid, '_thumbnail_ext_url' );
        if ( get_post_meta( $pid, '_thumbnail_id', TRUE ) === 'by_url' ) {
            delete_post_meta( $pid, '_thumbnail_id' );
        }
    }
}

Функция, после проверок безопасности, проверяет переданный URL и, если он корректен, сохраняет его в метаполе '_thumbnail_ext_url'. Если URL пустой, а метаполе было сохранено, оно удаляется, что позволяет убрать метаполе просто очистив поле внешнего URL.

Последнее, что нужно сделать — вывести HTML-разметку изображения записи, когда задано наше внешнее изображение:

function thumbnail_external_replace( $html, $post_id ) {
    $url =  get_post_meta( $post_id, '_thumbnail_ext_url', TRUE );
    if ( empty( $url ) || ! url_is_image( $url ) ) {
        return $html;
    }
    $alt = get_post_field( 'post_title', $post_id ) . ' ' .  __( 'изображение записи', 'txtdomain' );
    $attr = array( 'alt' => $alt );
    $attr = apply_filters( 'wp_get_attachment_image_attributes', $attr, NULL );
    $attr = array_map( 'esc_attr', $attr );
    $html = sprintf( '<img src="%s"', esc_url($url) );
    foreach ( $attr as $name => $value ) {
        $html .= " $name=" . '"' . $value . '"';
    }
    $html .= ' />';
    return $html;
}

Готово.

Что осталось сделать

В выводе изображения записи я не использовал атрибуты width или height, ни классы, которые обычно добавляет WordPress, такие как 'attachment-$size'. Это потому, что определение размера изображения требует дополнительной работы, которая замедлит загрузку страницы, особенно если у вас несколько изображений записи на странице.

Если вам нужны эти атрибуты, вы можете модифицировать мой код, добавив обработчик к фильтру wp_get_attachment_image_attributes' (это стандартный хук WordPress) или изменить мой код для определения размера изображения и вывода соответствующих атрибутов и классов.

Плагин Gist

Весь код, приведенный здесь, за исключением инициализации правильного текстового домена, доступен как полностью рабочий плагин в Gist здесь. Там код использует пространство имен, поэтому требует PHP 5.3+.

Примечания

Конечно, вы должны быть уверены, что у вас есть лицензия и разрешение на использование и хотлинкинг изображений на вашем сайте с внешних источников.

20 авг. 2014 г. 23:39:57
Комментарии

куда мне вставить этот код

Ankit Agrawal Ankit Agrawal
5 дек. 2018 г. 12:14:49

можете объяснить, какой именно код и на какую страницу мы должны написать. Я новичок в PHP/Wordpress, поэтому объясните, пожалуйста, пошагово. Спасибо

Ankit Agrawal Ankit Agrawal
10 дек. 2018 г. 15:09:43

@AnkitAgrawal посмотри здесь

gmazzap gmazzap
10 дек. 2018 г. 17:03:46

Не работает на версиях 5.4 и 5.5.

Ciprian Ciprian
10 июл. 2020 г. 18:22:56