問題描述

我在 WordPress 管理員的”Pages” 中新增了一個新頁面,並新增了幾個自定義欄位。我也希望能夠將一個上傳影像欄位新增到頁面編輯器 – 有沒有辦法透過 custom-fields?

或者如果我需要這個能力,還有不同的方向嗎?

最佳解決方案

對於任何想要了解更多檔案上傳的人來說,這裡是一個簡要的介紹主要話題和痛點的介紹。這是在 Linux 盒子上寫的 WordPress 3.0,程式碼只是教授概念的基本概述。我相信這裡的一些人可以提供改進實施的建議。

概述您的基本方法

將影像與帖子相關聯至少有三種方法:使用 post_meta 欄位儲存影像路徑,使用 post_meta 欄位來儲存影像的媒體庫 ID(稍後再更新),或將影像分配給帖子作為附件。此示例將使用 post_meta 欄位來儲存影像的媒體庫 ID 。 YMMV 。

多部分編碼

預設情況下,WordPress 建立& 編輯表單沒有 enctype 。如果要上傳檔案,則需要將”enctype=’multipart/form-data'” 新增到表單標籤中,否則 $ _FILES 集合將不會被推送。在 WordPress 3.0 中,有一個鉤子。在某些以前的版本 (不確定具體細節) 中,您必須將字串替換為表單標籤。

function xxxx_add_edit_form_multipart_encoding() {

    echo ' enctype="multipart/form-data"';

}
add_action('post_edit_form_tag', 'xxxx_add_edit_form_multipart_encoding');

建立元框和上傳欄位

我不會去建立元框,因為大多數人可能已經知道如何做,但我只想說,你只需要一個簡單的元框,其中包含一個檔案欄位。在下面的示例中,我已經新增了一些程式碼來查詢現有的影像,如果存在,則顯示它。我還包括一些簡單的錯誤/反饋功能,可以使用 post_meta 欄位傳遞錯誤。你會想改變它來使用 WP_Error 類… 它只是為了演示。

function xxxx_render_image_attachment_box($post) {

    // See if there's an existing image. (We're associating images with posts by saving the image's 'attachment id' as a post meta value)
    // Incidentally, this is also how you'd find any uploaded files for display on the frontend.
    $existing_image_id = get_post_meta($post->ID,'_xxxx_attached_image', true);
    if(is_numeric($existing_image_id)) {

        echo '<div>';
            $arr_existing_image = wp_get_attachment_image_src($existing_image_id, 'large');
            $existing_image_url = $arr_existing_image[0];
            echo '<img src="'%20.%20$existing_image_url%20.%20'" />';
        echo '</div>';

    }

    // If there is an existing image, show it
    if($existing_image_id) {

        echo '<div>Attached Image ID: ' . $existing_image_id . '</div>';

    }

    echo 'Upload an image: <input type="file" name="xxxx_image" id="xxxx_image" />';

    // See if there's a status message to display (we're using this to show errors during the upload process, though we should probably be using the WP_error class)
    $status_message = get_post_meta($post->ID,'_xxxx_attached_image_upload_feedback', true);

    // Show an error message if there is one
    if($status_message) {

        echo '<div class="upload_status_message">';
            echo $status_message;
        echo '</div>';

    }

    // Put in a hidden flag. This helps differentiate between manual saves and auto-saves (in auto-saves, the file wouldn't be passed).
    echo '<input type="hidden" name="xxxx_manual_save_flag" value="true" />';

}



function xxxx_setup_meta_boxes() {

    // Add the box to a particular custom content type page
    add_meta_box('xxxx_image_box', 'Upload Image', 'xxxx_render_image_attachment_box', 'post', 'normal', 'high');

}
add_action('admin_init','xxxx_setup_meta_boxes');

處理檔案上傳

這是大的 – 透過掛接到 save_post 操作來實際處理檔案上傳。我已經在下面新增了一個 heavily-commented 功能,但是我想注意它使用的兩個關鍵的 WordPress 功能:

wp_handle_upload() 執行所有的魔術,好的,處理上傳。你只需要在 $ _FILES 陣列中傳遞一個對你的欄位的引用,並且選擇一個陣列 (不要太擔心這些 – 你需要設定的唯一重要的一個是 test_form = false 。但是,此功能不會將上傳的檔案新增到媒體庫。它只是上傳並返回新檔案的路徑 (並且,並且,方便地,完整的 URL) 。如果有問題,它會返回一個錯誤。

wp_insert_attachment() 將影像新增到媒體庫,並生成所有適當的縮圖。您只需傳遞一系列選項 (標題,帖子狀態等) 和 LOCAL 路徑 (而不是 URL) 到您剛剛上傳的檔案。將影像放在媒體庫中的好東西是,您可以稍後透過呼叫 wp_delete_attachment 並傳遞專案的媒體庫 ID(我在下面的功能中) 來輕鬆刪除所有檔案。使用此功能,您還需要使用 wp_generate_attachment_metadata() 和 wp_update_attachment_metadata(),它們完全按照您期望的方式執行 – 為媒體項生成後設資料。

function xxxx_update_post($post_id, $post) {

    // Get the post type. Since this function will run for ALL post saves (no matter what post type), we need to know this.
    // It's also important to note that the save_post action can runs multiple times on every post save, so you need to check and make sure the
    // post type in the passed object isn't "revision"
    $post_type = $post->post_type;

    // Make sure our flag is in there, otherwise it's an autosave and we should bail.
    if($post_id && isset($_POST['xxxx_manual_save_flag'])) {

        // Logic to handle specific post types
        switch($post_type) {

            // If this is a post. You can change this case to reflect your custom post slug
            case 'post':

                // HANDLE THE FILE UPLOAD

                // If the upload field has a file in it
                if(isset($_FILES['xxxx_image']) && ($_FILES['xxxx_image']['size'] > 0)) {

                    // Get the type of the uploaded file. This is returned as "type/extension"
                    $arr_file_type = wp_check_filetype(basename($_FILES['xxxx_image']['name']));
                    $uploaded_file_type = $arr_file_type['type'];

                    // Set an array containing a list of acceptable formats
                    $allowed_file_types = array('image/jpg','image/jpeg','image/gif','image/png');

                    // If the uploaded file is the right format
                    if(in_array($uploaded_file_type, $allowed_file_types)) {

                        // Options array for the wp_handle_upload function. 'test_upload' => false
                        $upload_overrides = array( 'test_form' => false );

                        // Handle the upload using WP's wp_handle_upload function. Takes the posted file and an options array
                        $uploaded_file = wp_handle_upload($_FILES['xxxx_image'], $upload_overrides);

                        // If the wp_handle_upload call returned a local path for the image
                        if(isset($uploaded_file['file'])) {

                            // The wp_insert_attachment function needs the literal system path, which was passed back from wp_handle_upload
                            $file_name_and_location = $uploaded_file['file'];

                            // Generate a title for the image that'll be used in the media library
                            $file_title_for_media_library = 'your title here';

                            // Set up options array to add this file as an attachment
                            $attachment = array(
                                'post_mime_type' => $uploaded_file_type,
                                'post_title' => 'Uploaded image ' . addslashes($file_title_for_media_library),
                                'post_content' => '',
                                'post_status' => 'inherit'
                            );

                            // Run the wp_insert_attachment function. This adds the file to the media library and generates the thumbnails. If you wanted to attch this image to a post, you could pass the post id as a third param and it'd magically happen.
                            $attach_id = wp_insert_attachment( $attachment, $file_name_and_location );
                            require_once(ABSPATH . "wp-admin" . '/includes/image.php');
                            $attach_data = wp_generate_attachment_metadata( $attach_id, $file_name_and_location );
                            wp_update_attachment_metadata($attach_id,  $attach_data);

                            // Before we update the post meta, trash any previously uploaded image for this post.
                            // You might not want this behavior, depending on how you're using the uploaded images.
                            $existing_uploaded_image = (int) get_post_meta($post_id,'_xxxx_attached_image', true);
                            if(is_numeric($existing_uploaded_image)) {
                                wp_delete_attachment($existing_uploaded_image);
                            }

                            // Now, update the post meta to associate the new image with the post
                            update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                            // Set the feedback flag to false, since the upload was successful
                            $upload_feedback = false;


                        } else { // wp_handle_upload returned some kind of error. the return does contain error details, so you can use it here if you want.

                            $upload_feedback = 'There was a problem with your upload.';
                            update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                        }

                    } else { // wrong file type

                        $upload_feedback = 'Please upload only image files (jpg, gif or png).';
                        update_post_meta($post_id,'_xxxx_attached_image',$attach_id);

                    }

                } else { // No file was passed

                    $upload_feedback = false;

                }

                // Update the post meta with any feedback
                update_post_meta($post_id,'_xxxx_attached_image_upload_feedback',$upload_feedback);

            break;

            default:

        } // End switch

    return;

} // End if manual save flag

    return;

}
add_action('save_post','xxxx_update_post',1,2);

許可權,所有權和安全性

如果您無法上傳,可能與許可權有關。我不是伺服器配置的專家,所以請糾正我,如果這部分是愚蠢的。

首先,確保您的 wp-content / uploads 資料夾存在,並由 apache 擁有:apache 。如果是這樣,您應該可以將許可權設定為 744,並且所有內容都應該可以正常工作。所有權是重要的 – 即使設定為 777,如果目錄沒有正確擁有,有時也不會有幫助。

您還應考慮使用 htaccess 檔案限制上傳和執行的檔案型別。這可以防止人們上傳不是影像的檔案,也不會執行偽裝成影像的指令碼。你應該可以 google 這個更權威的資訊,但你可以這樣做簡單的檔案型別限制:

<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>

參考文獻

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