ฉันจะเพิ่มฟิลด์การอัพโหลดรูปภาพโดยตรงไปยังแผงการเขียนที่กำหนดเองได้อย่างไร


62

ฉันได้เพิ่มหน้าใหม่ภายใต้ "หน้า" ในผู้ดูแลระบบ wordpress และเพิ่มเขตข้อมูลที่กำหนดเองหลายแห่ง ฉันต้องการเพิ่มเขตข้อมูลรูปภาพที่อัปโหลดไปยังเครื่องมือแก้ไขหน้า - มีวิธีการผ่านทางฟิลด์ที่กำหนดเองหรือไม่

หรือมีทิศทางอื่นที่ฉันต้องใช้ถ้าฉันต้องการความสามารถนี้?


ตรวจสอบปลั๊กอิน tdo รูปแบบที่อาจจะเป็นทางออกที่ง่าย
bueltge

คำถามนี้อาจเกี่ยวข้องกัน: wordpress.stackexchange.com/questions/4291/…
hakre

คำตอบ:


108

สำหรับผู้ที่ต้องการทราบข้อมูลเพิ่มเติมเกี่ยวกับการอัปโหลดไฟล์ต่อไปนี้เป็นไพรเมอร์ด่วนที่ครอบคลุมหัวข้อสำคัญและจุดปวด สิ่งนี้เขียนด้วย WordPress 3.0 บนกล่อง Linux ในใจและรหัสเป็นเพียงภาพรวมพื้นฐานเพื่อสอนแนวคิด ฉันแน่ใจว่าบางคนที่นี่สามารถให้คำแนะนำในการปรับปรุงการใช้งาน

สรุปแนวทางพื้นฐานของคุณ

มีอย่างน้อยสามวิธีในการเชื่อมโยงรูปภาพกับโพสต์: ใช้ฟิลด์ post_meta เพื่อจัดเก็บพา ธ รูปภาพโดยใช้ฟิลด์ post_meta เพื่อจัดเก็บ ID ไลบรารีสื่อรูปภาพของรูปภาพ (เพิ่มเติมในภายหลัง) หรือกำหนดรูปภาพให้กับโพสต์เป็นสิ่งที่แนบ . ตัวอย่างนี้จะใช้ฟิลด์ post_meta เพื่อเก็บ ID ไลบรารีสื่อของรูปภาพ YMMV

การเข้ารหัส Multipart

ตามค่าเริ่มต้น WordPress 'สร้างและแก้ไขแบบฟอร์มไม่มีประเภท หากคุณต้องการอัปโหลดไฟล์คุณจะต้องเพิ่ม "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');

สร้างกล่อง Meta และเขตข้อมูลอัปโหลด

ฉันจะไม่ไปไกลในการสร้างเมตาบ็อกเพราะคุณส่วนใหญ่คงรู้แล้วว่าจะต้องทำยังไง แต่ฉันแค่บอกว่าคุณต้องใช้เมตาบ็อกซ์ธรรมดา ๆ ที่มีฟิลด์ไฟล์อยู่เท่านั้น ในตัวอย่างด้านล่างฉันได้รวมรหัสบางส่วนเพื่อค้นหาภาพที่มีอยู่และแสดงถ้ามีอยู่ ฉันได้รวมฟังก์ชันข้อผิดพลาด / ข้อเสนอแนะง่ายๆที่ส่งผ่านข้อผิดพลาดโดยใช้ฟิลด์ 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="' . $existing_image_url . '" />';
        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 ฉันได้รวมฟังก์ชั่นที่มีการแสดงความคิดเห็นไว้ด้านล่าง แต่ฉันต้องการที่จะทราบว่าฟังก์ชั่น 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 / upload ของคุณมีอยู่และเป็นของ apache: apache ถ้าเป็นเช่นนั้นคุณควรสามารถกำหนดสิทธิ์เป็น 744 และทุกอย่างจะทำงานได้ ความเป็นเจ้าของมีความสำคัญแม้บางครั้งการตั้งค่า Perms เป็น 777 จะไม่ช่วยถ้าไดเรกทอรีไม่ได้เป็นเจ้าของอย่างถูกต้อง

คุณควรพิจารณา จำกัด ประเภทของไฟล์ที่อัพโหลดและดำเนินการโดยใช้ไฟล์ htaccess วิธีนี้ช่วยป้องกันไม่ให้ผู้คนอัพโหลดไฟล์ที่ไม่ใช่ภาพและเรียกใช้งานสคริปต์ที่ปลอมตัวเป็นรูปภาพ คุณน่าจะเป็น google นี่สำหรับข้อมูลที่เชื่อถือได้มากขึ้น แต่คุณสามารถกำหนดประเภทไฟล์แบบง่าย ๆ ได้ดังนี้:

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

ขอบคุณมาก MathSmath! สิ่งที่ฉันต้องการ ฉันหวังว่าฉันจะมอบความรุ่งโรจน์ให้กับคำตอบนี้ได้มากขึ้น!
Michal Mau

คำอธิบายที่ยอดเยี่ยม! สิ่งเดียวที่ฉันขอขอบคุณที่คุณขยายอย่างมากคือวิธีทำให้ไฟล์ที่อัปโหลดเฉพาะไม่สามารถเข้าถึงได้จากสาธารณะ กล่าวอีกนัยหนึ่งถ้าคุณต้องการสร้างโพสต์ประเภทเฉพาะที่ผู้ใช้สามารถเข้าถึงไฟล์ที่อัพโหลดทั้งหมดได้ คุณช่วยอธิบายเรื่องนี้ได้ไหม
NetConstructor.com

3
สำหรับทุกคนที่ต้องการอัปโหลดไฟล์ที่ส่วนหน้าคุณจะต้องรวมรหัสต่อไปนี้เพื่อให้สามารถเข้าถึงฟังก์ชั่น wp_handle_upload ():if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
Nick Budden

@ NetConstructor.com ฉันขอแนะนำให้คุณสร้างคำถามเนื่องจากอยู่นอกขอบเขตของคำตอบนี้
hitautodestruct

0

รหัสที่ @MathSmath ที่ระบุนั้นถูกต้อง อย่างไรก็ตามหากคุณจัดการกับฟิลด์การอัปโหลดจำนวนมากหรือต้องการอัปโหลดไฟล์หลายไฟล์คุณจะต้องแก้ไขเป็นจำนวนมาก

นอกจากนี้มันไม่ได้ใช้ไลบรารีสื่อของ WordPress สำหรับการอัปโหลดไฟล์ (ซึ่งทั้งหมดทำงานสกปรกหลังฉาก)

ผมขอแนะนำให้คุณใช้เวลาดูที่ปลั๊กอินเช่นกล่อง Meta ปลั๊กอินสนับสนุนการอัปโหลดไฟล์ทั้งสองวิธี:

  • ผ่าน HTML5 input[type="file"]ซึ่งใช้รหัสที่คล้ายกันด้านบน (ดูเอกสาร ) และ
  • ผ่าน WordPress Media Library (ดูเอกสาร )

มันสามารถช่วยคุณลดความพยายามในการเขียนและรักษารหัสโดยเฉพาะเมื่อคุณต้องการสร้างการอัปโหลดหลายครั้ง

ข้อจำกัดความรับผิดชอบ: ฉันเป็นผู้เขียน Meta Box

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.