問題描述

我知道有從遠程 URL 獲取圖像並在本地存儲的插件。我只是想知道是否可能不將圖像存儲在媒體庫中,但將其用作精選圖像?

最佳解決方案

是的,這是可能的,很簡單。

這是我建議的工作流程

  1. 在某個地方放置一個 UI 來插入特徵圖像的 URL 。可能最好的選擇是使用'admin_post_thumbnail_html'過濾器鈎

  2. 使用'save_post'動作掛鈎來保存 URL(在安全性和驗證程序之後) 在自定義後期元

  3. 使用'post_thumbnail_html'過濾器鈎子輸出正確的<img> 標記,覆蓋默認值,如果需要特徵圖像的帖子具有外部特徵圖像的後期元素

要工作,此工作流程需要使用 get_the_post_thumnbail()the_post_thumbnail()功能在模板中顯示特徵圖像。

此外,當我們設置外部 URL 的元數據時,我們必須確保'_thumbnail_id'元值具有 non-empty 值,否則 has_post_thumbnail()將只返回只有外部特徵圖像的帖子。

事實上,通過我們的工作流程,一個職位有可能同時具有標準的本地特徵圖像和一組,在這種情況下,將使用外部功能。

為了實現我們的工作流程,我們需要一個函數來驗證用作外部特徵圖像的 URL,因為我們必須確保它是一個有效的圖像 URL 。

有不同的方法來做這個任務; 這裏我使用一個非常簡單的方式,只看網址,而不下載圖像。這僅適用於靜態圖像 URL,並且不會驗證圖像​​是否真實存在,但速度很快。如果需要 (here 是一些幫助),將其修改為更高級的東西。

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>' . __('Or', 'txtdomain') . '</p>';
    $html .= '<p>' . __( 'Enter the url for external image', '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>' . __( 'Leave url blank to remove.', 'txtdomain' ) . '</p>';
    }
    $html .= '</div>';
    return $html;
}

請注意,我使用'txtdomain'作為文本域,但您應該使用正確的註冊文本域。

這是輸出如何看起來空:

這是添加圖像 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 字段來清除元數據。

當我們的外部圖像網址設置在元中時,最後要做的是輸出特色圖像標記:

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 ) . ' ' .  __( 'thumbnail', '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;
}

我們完了。

剩下什麼

在特色圖像輸出中,我沒有使用 widthheight 屬性,也不使用 WordPress 通常添加的類,如'attachment-$size'。這是因為嗅探圖像的大小需要額外的工作,這將減慢頁面加載速度,特別是如果您在頁面中有多個特色圖像。

如果您需要這些屬性,可以使用我的代碼向 wp_get_attachment_image_attributes'過濾器添加回調 (它是一個 standard WordPress hook),也可以改變我的代碼來嗅探圖像大小並輸出相關的屬性和類。

插件 Gist

在這裏發佈的所有代碼,除了添加適當的文本域初始化之外,可以作為 Gist here 中的 full-working 插件。那裏的代碼使用了一個命名空間,所以它需要 PHP 5.3+。

説明

當然,您應該確保您擁有使用許可和授權的權限,並將您的站點中的圖像與外部圖像進行熱鏈接。

參考文獻

注:本文內容整合自 Google/Baidu/Bing 輔助翻譯的英文資料結果。如果您對結果不滿意,可以加入我們改善翻譯效果:薇曉朵技術論壇。