Làm cách nào tôi có thể thêm trường tải lên hình ảnh trực tiếp vào bảng ghi tùy chỉnh?


62

Tôi đã thêm một trang mới trong "Trang" trong quản trị viên wordpress và thêm một số trường tùy chỉnh. Tôi cũng muốn có thể thêm trường hình ảnh tải lên vào trình chỉnh sửa trang - có cách nào để thực hiện việc này qua trường tùy chỉnh không?

Hoặc có một hướng khác tôi cần phải thực hiện nếu tôi cần khả năng này?


kiểm tra plugin tdo-
Forms

Câu hỏi này có lẽ có liên quan: wordpress.stackexchange.com/questions/4291/
triệt

Câu trả lời:


108

Đối với bất kỳ ai muốn biết thêm về tải lên tệp, đây là một bản tóm tắt nhanh về các chủ đề chính và các điểm đau. Điều này được viết với WordPress 3.0 trên hộp Linux và mã chỉ là một tổng quan cơ bản để dạy các khái niệm. Tôi chắc rằng một số người ở đây có thể cung cấp lời khuyên để cải thiện việc thực hiện.

Phác thảo phương pháp cơ bản của bạn

Có ít nhất ba cách để liên kết hình ảnh với bài đăng: sử dụng trường post_meta để lưu đường dẫn hình ảnh, sử dụng trường post_meta để lưu trữ ID thư viện phương tiện của hình ảnh (nhiều hơn về sau) hoặc gán hình ảnh cho bài đăng dưới dạng tệp đính kèm . Ví dụ này sẽ sử dụng trường post_meta để lưu trữ ID thư viện phương tiện của hình ảnh. YMMV.

Mã hóa nhiều phần

Theo mặc định, các biểu mẫu tạo và chỉnh sửa của WordPress không có mã hóa. Nếu bạn muốn tải lên một tệp, bạn sẽ cần thêm "enctype = 'Multipart / form-data'" vào thẻ biểu mẫu - nếu không thì bộ sưu tập $ _FILES sẽ không bị đẩy qua. Trong WordPress 3.0, có một cái móc cho điều đó. Trong một số phiên bản trước (không chắc chắn về chi tiết cụ thể), bạn phải xâu chuỗi thay thế thẻ biểu mẫu.

function xxxx_add_edit_form_multipart_encoding() {

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

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

Tạo Meta Box và Trường tải lên

Tôi sẽ không đi sâu vào việc tạo các hộp meta vì hầu hết các bạn có thể đã biết cách thực hiện, nhưng tôi sẽ chỉ nói rằng bạn chỉ cần một hộp meta đơn giản có trường tệp trong đó. Trong ví dụ dưới đây, tôi đã bao gồm một số mã để tìm kiếm một hình ảnh hiện có và hiển thị nó nếu có. Tôi cũng đã bao gồm một số chức năng lỗi / phản hồi đơn giản vượt qua lỗi sử dụng trường post_meta. Bạn sẽ muốn thay đổi điều này để sử dụng lớp WP_Error ... nó chỉ để trình diễn.

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');

Xử lý tải lên tệp

Đây là một vấn đề lớn - thực sự xử lý việc tải lên tệp bằng cách nối vào hành động save_post. Tôi đã bao gồm một chức năng được bình luận nhiều dưới đây, nhưng tôi muốn lưu ý hai chức năng chính của WordPress mà nó sử dụng:

wp_handle_upload () thực hiện tất cả các phép thuật, tốt, xử lý việc tải lên. Bạn chỉ cần chuyển tham chiếu đến trường của mình trong mảng $ _FILES và một loạt các tùy chọn (đừng quá lo lắng về những điều này - điều quan trọng duy nhất bạn cần đặt là test_form = false. Hãy tin tôi). Tuy nhiên, chức năng này không thêm tệp đã tải lên vào thư viện phương tiện. Nó chỉ đơn thuần là tải lên và trả về đường dẫn của tệp mới (và, một cách khéo léo, URL đầy đủ là tốt). Nếu có vấn đề, nó sẽ trả về lỗi.

wp_insert_attachment () thêm hình ảnh vào thư viện phương tiện và tạo tất cả các hình thu nhỏ thích hợp. Bạn chỉ cần truyền cho nó một loạt các tùy chọn (tiêu đề, trạng thái bài đăng, v.v.) và đường dẫn ĐỊA PHƯƠNG (không phải URL) cho tệp bạn vừa tải lên. Điều tuyệt vời khi đưa hình ảnh của bạn vào thư viện phương tiện là bạn có thể dễ dàng xóa tất cả các tệp sau đó bằng cách gọi wp_delete_attachment và gửi ID thư viện phương tiện của vật phẩm (mà tôi đang thực hiện trong chức năng bên dưới). Với chức năng này, bạn cũng sẽ cần sử dụng wp_generate_attachment_metadata () và wp_update_attachment_metadata (), thực hiện chính xác những gì bạn mong đợi - tạo siêu dữ liệu cho mục phương tiện.

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);

Quyền, quyền sở hữu và bảo mật

Nếu bạn gặp khó khăn khi tải lên, nó có thể phải làm với quyền. Tôi không phải là chuyên gia về cấu hình máy chủ, vì vậy hãy sửa cho tôi nếu phần này không ổn.

Trước tiên, hãy đảm bảo thư mục wp-content / upload của bạn tồn tại và được sở hữu bởi apache: apache. Nếu vậy, bạn sẽ có thể đặt quyền thành 744 và mọi thứ sẽ hoạt động. Quyền sở hữu rất quan trọng - thậm chí cài đặt cho phép 777 đôi khi sẽ không giúp ích nếu thư mục không được sở hữu đúng cách.

Bạn cũng nên xem xét việc giới hạn các loại tệp được tải lên và thực thi bằng tệp htaccess. Điều này ngăn mọi người tải lên các tệp không phải là hình ảnh và thực thi các tập lệnh được ngụy trang thành hình ảnh. Bạn có thể nên google cái này để biết thêm thông tin có thẩm quyền, nhưng bạn có thể thực hiện giới hạn loại tệp đơn giản như thế này:

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

Cảm ơn MathSmath rất nhiều! Đúng thứ tôi cần. Tôi ước tôi có thể cung cấp thêm danh tiếng cho câu trả lời này!
Michal Mau

Giải thích tuyệt vời! Điều DUY NHẤT mà tôi đánh giá cao bạn mở rộng là làm thế nào để các tệp được tải lên cụ thể không thể truy cập được từ công chúng. Nói cách khác, nếu bạn muốn tạo một loại bài đăng cụ thể trong đó tất cả các tệp được tải lên chỉ có thể được truy cập bởi người dùng có khả năng cụ thể. Bạn có thể vui lòng giải thích về điều này?
NetConstructor.com

3
Đối với bất kỳ ai muốn tải lên các tệp trên frontend, bạn sẽ cần bao gồm mã sau đây để có quyền truy cập vào hàm wp_handle_upload ():if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
Nick Budden

@ NetConstructor.com Tôi đề nghị bạn tạo một câu hỏi vì nó nằm ngoài phạm vi của câu trả lời này.
hitautodesturation

0

Mã mà @MathSmath cung cấp là đúng. Tuy nhiên, nếu bạn xử lý nhiều trường tải lên hoặc muốn tải lên nhiều tệp, thì bạn phải sửa đổi nó rất nhiều.

Bên cạnh đó, nó không sử dụng thư viện phương tiện WordPress để tải lên các tệp (tất cả các công việc bẩn thỉu phía sau hậu trường).

Tôi khuyên bạn nên xem một plugin như Meta Box . Plugin hỗ trợ cả hai cách để tải tệp lên:

  • Thông qua HTML5 input[type="file"], sử dụng một mã tương tự ở trên (xem tài liệu ) và
  • Thông qua Thư viện phương tiện WordPress (xem tài liệu ).

Nó có thể giúp bạn giảm công sức viết và duy trì mã, đặc biệt là khi bạn muốn tạo nhiều video tải lên.

Tuyên bố miễn trừ trách nhiệm: Tôi là tác giả của Meta Box.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.