web-dev-qa-db-de.com

Wie kann ich ein Bild-Upload-Feld direkt zu einem benutzerdefinierten Schreibfeld hinzufügen?

Ich habe eine neue Seite unter "Seiten" im WordPress-Administrator hinzugefügt und mehrere benutzerdefinierte Felder hinzugefügt. Ich möchte auch ein Upload-Bildfeld zum Seiteneditor hinzufügen können. Gibt es eine Möglichkeit, dies über benutzerdefinierte Felder zu tun?

Oder muss ich eine andere Richtung einschlagen, wenn ich diese Fähigkeit brauche?

61
Will

Für alle, die mehr über das Hochladen von Dateien erfahren möchten, finden Sie hier eine kurze Einführung zu den wichtigsten Themen und Schwachstellen. Dies ist mit WordPress 3.0 auf einer Linux-Box geschrieben und der Code ist nur eine grundlegende Übersicht, um die Konzepte zu vermitteln. Ich bin sicher, dass einige Leute hier Ratschläge zur Verbesserung der Implementierung geben könnten.

Skizzieren Sie Ihren grundlegenden Ansatz

Es gibt mindestens drei Möglichkeiten, Bilder mit Beiträgen zu verknüpfen: Verwenden eines Felds post_meta zum Speichern des Bildpfads, Verwenden eines Felds post_meta zum Speichern der Medienbibliotheks-ID des Bildes (dazu später mehr) oder Zuweisen des Bildes zum Beitrag als Anhang . In diesem Beispiel wird ein Feld post_meta verwendet, um die Medienbibliotheks-ID des Bildes zu speichern. YMMV.

Multipart-Codierung

Standardmäßig haben die Formulare zum Erstellen und Bearbeiten von WordPress keinen Enctype. Wenn Sie eine Datei hochladen möchten, müssen Sie dem Formular-Tag ein "enctype = 'multipart/form-data'" hinzufügen - andernfalls wird die $ _FILES-Auflistung überhaupt nicht durchgeschoben. In WordPress 3.0 gibt es dafür einen Haken. In einigen Vorgängerversionen (ohne genaue Angaben) müssen Sie den Formular-Tag durch einen String ersetzen.

function xxxx_add_edit_form_multipart_encoding() {

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

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

Erstellen Sie die Meta-Box und das Upload-Feld

Ich werde nicht weit gehen, um Meta-Boxen zu erstellen, da die meisten von Ihnen wahrscheinlich bereits wissen, wie es geht, aber ich sage nur, dass Sie nur eine einfache Meta-Box mit einem Dateifeld benötigen. Im folgenden Beispiel habe ich Code eingefügt, um nach einem vorhandenen Bild zu suchen und es anzuzeigen, falls eines vorhanden ist. Ich habe auch einige einfache Fehler-/Feedback-Funktionen hinzugefügt, die Fehler mithilfe eines post_meta-Felds übergeben. Sie sollten dies ändern, um die WP_Error-Klasse zu verwenden. Dies dient nur zu Demonstrationszwecken.

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

Handhabung des Dateiuploads

Dies ist die große Aufgabe, bei der das Hochladen der Datei durch Einbinden in die Aktion save_post erfolgt. Ich habe unten eine stark kommentierte Funktion eingefügt, möchte jedoch die beiden wichtigsten WordPress-Funktionen erwähnen, die sie verwendet:

wp_handle_upload () erledigt die Magie des Uploads. Übergeben Sie ihm einfach einen Verweis auf Ihr Feld im Array $ _FILES und eine Reihe von Optionen (machen Sie sich darüber keine Sorgen - Sie müssen nur test_form = false festlegen. Vertrauen Sie mir). Diese Funktion fügt die hochgeladene Datei jedoch nicht zur Medienbibliothek hinzu. Es wird lediglich der Upload durchgeführt und der Pfad der neuen Datei (und handlich auch die vollständige URL) zurückgegeben. Wenn es ein Problem gibt, wird ein Fehler zurückgegeben.

wp_insert_attachment () fügt das Bild der Medienbibliothek hinzu und generiert alle entsprechenden Miniaturansichten. Sie übergeben ihm lediglich eine Reihe von Optionen (Titel, Post-Status usw.) und den LOKALEN Pfad (nicht die URL) zu der Datei, die Sie gerade hochgeladen haben. Das Tolle am Einfügen Ihrer Bilder in die Medienbibliothek ist, dass Sie später alle Dateien problemlos löschen können, indem Sie wp_delete_attachment aufrufen und ihm die Medienbibliotheks-ID des Elements übergeben (was ich in der folgenden Funktion mache). Mit dieser Funktion müssen Sie auch wp_generate_attachment_metadata () und wp_update_attachment_metadata () verwenden, die genau das tun, was Sie erwarten - Metadaten für das Medienelement generieren.

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

Berechtigungen, Eigentum und Sicherheit

Wenn Sie Probleme beim Hochladen haben, hat dies möglicherweise mit Berechtigungen zu tun. Ich bin kein Experte für Serverkonfiguration, also bitte korrigieren Sie mich, wenn dieser Teil wackelig ist.

Stellen Sie zunächst sicher, dass Ihr Ordner "wp-content/uploads" vorhanden ist und Apache gehört: apache. In diesem Fall sollten Sie die Berechtigungen auf 744 setzen können und alles sollte funktionieren. Die Inhaberschaft ist wichtig - selbst das Festlegen von Perms auf 777 hilft manchmal nicht, wenn das Verzeichnis nicht in ordnungsgemäßem Besitz ist.

Sie sollten auch in Betracht ziehen, die Dateitypen zu beschränken, die mithilfe einer htaccess-Datei hochgeladen und ausgeführt werden. Auf diese Weise wird verhindert, dass Benutzer Dateien hochladen, die keine Bilder sind, und als Bilder getarnte Skripts ausführen. Sie sollten dies wahrscheinlich googeln, um weitere maßgebliche Informationen zu erhalten, aber Sie können eine einfache Einschränkung des Dateityps wie folgt vornehmen:

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

Der von @MathSmath bereitgestellte Code ist richtig. Wenn Sie jedoch mit vielen Upload-Feldern arbeiten oder mehrere Dateien hochladen möchten, müssen Sie diese häufig ändern.

Außerdem wird die WordPress-Medienbibliothek nicht zum Hochladen von Dateien verwendet (was die ganze Drecksarbeit hinter den Kulissen erledigt).

Ich würde vorschlagen, dass Sie sich ein Plugin wie Meta Box ansehen. Das Plugin unterstützt beide Möglichkeiten zum Hochladen von Dateien:

  • Über HTML5 input[type="file"], der oben einen ähnlichen Code verwendet (siehe docs ) und
  • Über die WordPress Media Library (siehe docs ).

Dies kann Ihnen dabei helfen, den Aufwand für das Schreiben und Verwalten des Codes zu verringern, insbesondere wenn Sie mehrere Uploads erstellen möchten.

Haftungsausschluss: Ich bin der Autor von Meta Box.

0
Anh Tran