ワードプレス管理者の「ページ」の下に新しいページを追加し、いくつかのカスタムフィールドを追加しました。また、ページエディタにアップロード画像フィールドを追加できるようにしたいのですが、カスタムフィールドを使用してこれを行う方法はありますか?
それとも、この能力が必要な場合に私がとる必要がある別の方向がありますか?
ワードプレス管理者の「ページ」の下に新しいページを追加し、いくつかのカスタムフィールドを追加しました。また、ページエディタにアップロード画像フィールドを追加できるようにしたいのですが、カスタムフィールドを使用してこれを行う方法はありますか?
それとも、この能力が必要な場合に私がとる必要がある別の方向がありますか?
回答:
ファイルのアップロードについて詳しく知りたい方は、主要なトピックと問題点をカバーする簡単な入門書をご覧ください。これは、Linuxボックス上のWordPress 3.0を念頭に置いて記述されており、コードは概念を教えるための基本的な概要にすぎません。ここの何人かの人々は実装の改善のためのアドバイスを提供できると確信しています。
画像を投稿に関連付けるには、少なくとも3つの方法があります:post_metaフィールドを使用して画像パスを保存する、post_metaフィールドを使用して画像のメディアライブラリIDを保存する(詳細は後述)、または添付ファイルとして投稿に画像を割り当てる。この例では、post_metaフィールドを使用して画像のメディアライブラリIDを保存します。YMMV。
デフォルトでは、WordPressの作成および編集フォームにはenctypeがありません。ファイルをアップロードする場合は、フォームタグに「enctype = 'multipart / form-data'」を追加する必要があります。追加しないと、$ _ FILESコレクションはまったくプッシュされません。WordPress 3.0には、そのためのフックがあります。一部の以前のバージョン(詳細は不明)では、formタグを文字列で置き換える必要があります。
function xxxx_add_edit_form_multipart_encoding() {
echo ' enctype="multipart/form-data"';
}
add_action('post_edit_form_tag', 'xxxx_add_edit_form_multipart_encoding');
メタボックスの作成については、ほとんどの人が既にその方法を知っていると思われるため、ここでは詳しく説明しませんが、ファイルフィールドを含む単純なメタボックスのみが必要だと言います。以下の例では、既存の画像を検索し、存在する場合はそれを表示するためのコードを含めています。また、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アクションにフックすることでファイルのアップロードを処理します。以下にコメントの多い関数を含めましたが、それが使用する2つの主要なWordPress関数に注意したいと思います。
wp_handle_upload()は、アップロードの処理のすべての魔法を実行します。$ _FILES配列のフィールドへの参照とオプションの配列を渡すだけです(これらについてあまり心配しないでください。設定する必要がある唯一の重要なものはtest_form = falseです。信頼してください)。ただし、この関数は、アップロードされたファイルをメディアライブラリに追加しません。単にアップロードを実行し、新しいファイルのパス(および、便利なことに完全なURLも)を返します。問題がある場合は、エラーを返します。
wp_insert_attachment()は画像をメディアライブラリーに追加し、適切なサムネイルをすべて生成します。オプション(タイトル、投稿ステータスなど)の配列と、アップロードしたファイルへのローカルパス(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 / uploadsフォルダーが存在し、apache:apacheによって所有されていることを確認します。その場合、権限を744に設定でき、すべてが正常に機能するはずです。所有権は重要です。ディレクトリが適切に所有されていない場合、パーマを777に設定しても役に立たない場合があります。
また、htaccessファイルを使用してアップロードおよび実行されるファイルの種類を制限することも検討する必要があります。これにより、画像ではないファイルをアップロードしたり、画像を装ったスクリプトを実行したりできなくなります。おそらくより信頼できる情報を得るためにこれをグーグルで検索する必要がありますが、次のような単純なファイルタイプの制限を行うことができます。
<Files ^(*.jpeg|*.jpg|*.png|*.gif)>
order deny,allow
deny from all
</Files>
if ( ! function_exists( 'wp_handle_upload' ) ) require_once( ABSPATH . 'wp-admin/includes/file.php' );
@MathSmathが提供したコードは正しいです。ただし、多くのアップロードフィールドを処理する場合、または複数のファイルをアップロードする場合は、多くのファイルを変更する必要があります。
また、ファイルのアップロードにWordPressメディアライブラリを使用していません(これは、舞台裏ですべての汚い作業を行います)。
Meta Boxのようなプラグインをご覧になることをお勧めします。プラグインは、ファイルをアップロードする両方の方法をサポートしています。
特に複数のアップロードを作成する場合は、コードの記述と保守の労力を削減できます。
免責事項:私はMeta Boxの著者です。