Come posso aggiungere un campo di caricamento delle immagini direttamente a un pannello di scrittura personalizzato?


62

Ho aggiunto una nuova pagina in "Pagine" nell'amministratore di wordpress e ho aggiunto diversi campi personalizzati. Vorrei anche essere in grado di aggiungere un campo di caricamento dell'immagine all'editor di pagine: esiste un modo per farlo tramite campi personalizzati?

O c'è una direzione diversa che devo prendere se ho bisogno di questa capacità?


controlla il plugin tdo-forms, forse questa è la soluzione facile
bueltge

Questa domanda è probabilmente correlata: wordpress.stackexchange.com/questions/4291/…
hakre,

Risposte:


108

Per chiunque voglia saperne di più sul caricamento dei file, ecco un breve resoconto che tratta gli argomenti principali e i punti deboli. Questo è scritto con WordPress 3.0 su una scatola Linux in mente, e il codice è solo una panoramica di base per insegnare i concetti. Sono sicuro che alcune persone qui potrebbero offrire consigli per migliorare l'implementazione.

Descrivi il tuo approccio di base

Esistono almeno tre modi per associare le immagini ai post: utilizzare un campo post_meta per memorizzare il percorso dell'immagine, utilizzare un campo post_meta per memorizzare l'ID della libreria multimediale dell'immagine (ne parleremo più avanti) o assegnare l'immagine al post come allegato . In questo esempio verrà utilizzato un campo post_meta per memorizzare l'ID della libreria multimediale dell'immagine. YMMV.

Codifica multipart

Per impostazione predefinita, i moduli di creazione e modifica di WordPress non hanno un tipo. Se si desidera caricare un file, è necessario aggiungere un "enctype = 'multipart / form-data'" al tag del modulo, altrimenti la raccolta $ _FILES non verrà eseguita. In WordPress 3.0, c'è un gancio per quello. In alcune versioni precedenti (non sono sicuro delle specifiche) è necessario sostituire la stringa del tag del modulo.

function xxxx_add_edit_form_multipart_encoding() {

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

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

Crea la Meta Box e carica il campo

Non andrò molto lontano nella creazione di meta-box poiché molti di voi probabilmente già sanno come farlo, ma dirò solo che hai solo bisogno di un semplice meta-box con un campo file al suo interno. Nell'esempio seguente ho incluso del codice per cercare un'immagine esistente e visualizzarla se ne esiste una. Ho anche incluso alcune semplici funzionalità di errore / feedback che passano gli errori usando un campo post_meta. Ti consigliamo di cambiarlo per usare la classe WP_Error ... è solo per dimostrazione.

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

Gestire il caricamento del file

Questa è la più importante: gestire effettivamente il caricamento del file collegandosi all'azione save_post. Di seguito ho incluso una funzione fortemente commentata, ma vorrei notare le due funzioni chiave di WordPress che utilizza:

wp_handle_upload () fa tutta la magia di gestire il caricamento. Basta passare un riferimento al tuo campo nell'array $ _FILES e una matrice di opzioni (non preoccuparti troppo di questi: l'unico importante che devi impostare è test_form = false. Fidati di me). Questa funzione, tuttavia, non aggiunge il file caricato al catalogo multimediale. Esegue semplicemente il caricamento e restituisce il percorso del nuovo file (e, comodamente, anche l'URL completo). Se c'è un problema, restituisce un errore.

wp_insert_attachment () aggiunge l'immagine alla libreria multimediale e genera tutte le anteprime appropriate. Basta passare una serie di opzioni (titolo, stato dei post, ecc.) E il percorso LOCALE (non URL) al file appena caricato. La cosa grandiosa di mettere le tue immagini nel catalogo multimediale è che puoi facilmente eliminare tutti i file in un secondo momento chiamando wp_delete_attachment e passandogli l'ID del catalogo multimediale dell'elemento (cosa che sto facendo nella funzione di seguito). Con questa funzione, dovrai anche utilizzare wp_generate_attachment_metadata () e wp_update_attachment_metadata (), che fanno esattamente ciò che ti aspetteresti che facciano: generare metadati per l'elemento multimediale.

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

Autorizzazioni, proprietà e sicurezza

Se hai problemi con il caricamento, potrebbe avere a che fare con le autorizzazioni. Non sono un esperto di configurazione del server, quindi per favore correggimi se questa parte è traballante.

Innanzitutto, assicurati che la cartella wp-content / uploads esista e sia di proprietà di apache: apache. In tal caso, dovresti essere in grado di impostare le autorizzazioni su 744 e tutto dovrebbe funzionare. La proprietà è importante: anche l'impostazione dei permessi su 777 a volte non aiuta se la directory non è correttamente posseduta.

Dovresti anche considerare di limitare i tipi di file caricati ed eseguiti usando un file htaccess. Ciò impedisce alle persone di caricare file che non sono immagini e di eseguire script mascherati da immagini. Probabilmente dovresti cercarlo su Google per informazioni più autorevoli, ma puoi fare un semplice tipo di file limitando in questo modo:

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

Grazie mille MathSmath! Proprio quello di cui avevo bisogno. Vorrei poter dare più voti positivi a questa risposta!
Michal Mau,

Spiegazione eccellente! L'unica cosa su cui ti sarei molto grato di espandermi è come rendere inaccessibili al pubblico specifici file caricati. In altre parole, se si desidera creare un tipo di post specifico in cui tutti i file caricati siano accessibili solo agli utenti con una capacità specifica. Potresti per favore approfondire questo?
NetConstructor.com il

3
Per tutti coloro che desiderano caricare file sul frontend, è necessario includere il seguente codice per poter accedere alla funzione wp_handle_upload ():if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
Nick Budden,

@ NetConstructor.com Ti suggerisco di creare una domanda che è molto al di fuori dell'ambito di questa risposta.
Hitautodestruct

0

Il codice fornito da @MathSmath è corretto. Tuttavia, se gestisci molti campi di caricamento o desideri caricare più file, devi modificarlo molto.

Inoltre, non utilizza la libreria multimediale di WordPress per il caricamento di file (che fa tutto il lavoro sporco dietro la scena).

Ti suggerirei di dare un'occhiata a un plugin come Meta Box . Il plugin supporta entrambi i modi per caricare file:

  • Tramite HTML5 input[type="file"], che utilizza un codice simile sopra (vedi documenti ) e
  • Tramite la libreria multimediale di WordPress (vedi documenti ).

Può aiutarti a ridurre lo sforzo di scrittura e manutenzione del codice, soprattutto quando desideri creare più caricamenti.

Disclaimer: sono l'autore di Meta Box.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.