Como posso adicionar um campo de upload de imagem diretamente a um painel de gravação personalizado?


62

Adicionei uma nova página em "Páginas" no administrador do wordpress e adicionei vários campos personalizados. Eu também gostaria de poder adicionar um campo de imagem de upload ao editor de páginas - existe alguma maneira de fazer isso através de campos personalizados?

Ou há uma direção diferente que preciso tomar se precisar dessa capacidade?


verificar o plugin formas tdo, talvez esta seja a solução fácil
bueltge

Esta questão está provavelmente relacionada: wordpress.stackexchange.com/questions/4291/…
hakre

Respostas:


108

Para quem deseja saber mais sobre o upload de arquivos, aqui está uma cartilha rápida que aborda os principais tópicos e pontos problemáticos. Isso foi escrito com o WordPress 3.0 em uma caixa do Linux em mente, e o código é apenas uma visão geral básica para ensinar os conceitos. Tenho certeza de que algumas pessoas aqui podem oferecer conselhos para melhorar a implementação.

Descreva sua abordagem básica

Há pelo menos três maneiras de associar imagens a postagens: usar um campo post_meta para armazenar o caminho da imagem, usar um campo post_meta para armazenar o ID da biblioteca de mídia da imagem (mais sobre isso mais tarde) ou atribuir a imagem à postagem como um anexo . Este exemplo usará um campo post_meta para armazenar o ID da biblioteca de mídia da imagem. YMMV.

Codificação multipartes

Por padrão, os formulários de criação e edição do WordPress não têm nenhum tipo de código. Se você quiser fazer upload de um arquivo, precisará adicionar um "enctype = 'multipart / form-data'" à tag do formulário - caso contrário, a coleção $ _FILES não será pressionada. No WordPress 3.0, há um gancho para isso. Em algumas versões anteriores (não tenho certeza dos detalhes), você precisa substituir a tag de formulário por string.

function xxxx_add_edit_form_multipart_encoding() {

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

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

Crie o campo Meta Box e Upload

Não vou muito longe na criação de meta boxes, pois a maioria de vocês provavelmente já sabe como fazê-lo, mas vou apenas dizer que você só precisa de uma meta box simples com um campo de arquivo. No exemplo abaixo, incluímos um código para procurar uma imagem existente e exibi-la, se houver. Também incluí algumas funcionalidades simples de erro / feedback que passam erros usando um campo post_meta. Você vai querer mudar isso para usar a classe WP_Error ... é apenas para demonstração.

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

Manipulando o Upload de Arquivos

Esse é o grande problema - na verdade, manipular o upload do arquivo conectando-se à ação save_post. Eu incluí uma função com muitos comentários abaixo, mas gostaria de observar as duas principais funções do WordPress que ele usa:

wp_handle_upload () faz toda a mágica de lidar com o upload. Você apenas passa uma referência ao seu campo na matriz $ _FILES e uma variedade de opções (não se preocupe muito com elas - a única importante que você precisa definir é test_form = false. Confie em mim). Essa função, no entanto, não adiciona o arquivo carregado à biblioteca de mídia. Ele simplesmente faz o upload e retorna o caminho do novo arquivo (e, comodamente, o URL completo). Se houver algum problema, ele retornará um erro.

wp_insert_attachment () adiciona a imagem à biblioteca de mídia e gera todas as miniaturas apropriadas. Você apenas passa uma variedade de opções (título, status da postagem, etc.) e o caminho LOCAL (não URL) para o arquivo que você acabou de enviar. O melhor de colocar suas imagens na biblioteca de mídia é que você pode excluir facilmente todos os arquivos posteriormente, chamando wp_delete_attachment e passando o ID da biblioteca de mídia do item (o que eu estou fazendo na função abaixo). Com essa função, você também precisará usar wp_generate_attachment_metadata () e wp_update_attachment_metadata (), que fazem exatamente o que você espera que eles façam - gerar metadados para o item de mídia.

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

Permissões, Propriedade e Segurança

Se você tiver problemas para fazer o upload, isso pode ter a ver com permissões. Eu não sou especialista em configuração de servidor, por favor, corrija-me se esta parte for instável.

Primeiro, verifique se a pasta wp-content / uploads existe e pertence ao apache: apache. Nesse caso, você deve poder definir as permissões para 744 e tudo deve funcionar. A propriedade é importante - até mesmo a configuração de permissões para 777 às vezes não ajudará se o diretório não for de propriedade adequada.

Você também deve limitar os tipos de arquivos carregados e executados usando um arquivo htaccess. Isso evita que as pessoas enviem arquivos que não são imagens e executem scripts disfarçados de imagens. Você provavelmente deve pesquisar no Google isso para obter informações mais autoritativas, mas pode limitar o tipo de arquivo simples como este:

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

Muito obrigado MathSmath! Apenas o que eu precisava. Eu gostaria de poder dar mais elogios a esta resposta!
Michal Mau

Excelente explicação! A ÚNICA coisa na qual eu gostaria muito que você expandisse é como tornar arquivos públicos específicos inacessíveis ao público. Em outras palavras, se você quiser criar um tipo de postagem específico, em que todos os arquivos enviados sejam acessíveis apenas por usuários com um recurso específico. Você poderia, por favor, elaborar isso?
NetConstructor.com

3
Para quem quiser fazer upload de arquivos no frontend, você precisará incluir o seguinte código para ter acesso à função wp_handle_upload ():if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
Nick Budden

@ NetConstructor.com Sugiro que você crie uma pergunta, pois isso está muito fora do escopo desta resposta.
Html # hitautodestruct # 03

0

O código que o @MathSmath forneceu está correto. No entanto, se você lida com muitos campos de upload ou deseja carregar vários arquivos, é necessário modificá-lo bastante.

Além disso, ele não utiliza a biblioteca de mídia do WordPress para fazer upload de arquivos (o que faz todo o trabalho sujo nos bastidores).

Eu sugiro que você dê uma olhada em um plugin como o Meta Box . O plug-in suporta as duas maneiras de fazer upload de arquivos:

  • Via HTML5 input[type="file"], que usa um código semelhante acima (consulte a documentação ) e
  • Via Biblioteca de mídia do WordPress (consulte a documentação ).

Isso pode ajudá-lo a reduzir o esforço de escrever e manter o código, especialmente quando você deseja criar vários uploads.

Disclaimer: Eu sou o autor de Meta Box.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.