WordPress:投稿専用画面からユーザーにアイキャッチ画像付きで自由投稿させる
- ダッシュボード外の投稿フォームを作る
- 登録ユーザーが投稿できる
- アイキャッチ画像をアップロードできる
いわばユーザ登録型画像掲示板のような仕様をWordpressで実現したのでそのメモ。
投稿処理
http://takahashifumiki.com/web/programing/2173/
こちらのWordpressの投稿の基本に沿う。
※紹介されているソースには一部ミスがあるので注意。
ちなみに自分の場合、カスタム投稿タイプは設定せず通常の投稿にしたかったので「post_type」はpostとしている。
素直に沿えば通常投稿できるので細かくは割愛。
以下は上記内容ができている前提。
ファイルアップロード
上記の投稿処理に従い、フォーム用テンプレート page-create-thread.php を作っている前提として、そちらのフォームから画像を投稿できるようにする。
<form action="<?php the_permalink();?>" enctype="multipart/form-data" method="post"> ~ <tr> <th><label>画像</label></th> <td><input type="file" name="image" /></td> </tr> ~
formタグに enctype=”multipart/form-data”を追加し、フォーム内には input type=file を追加する。
次に投稿処理を行う create-thread.php に画像アップの処理を加える。
テキストバリデーションと投稿処理の間に入れると良い。
if (isset($_FILES['image']['error']) && is_int($_FILES['image']['error'])) {
// ファイルバリデーション
if (!$_FILES['image']['error']) {
// サイズ上限チェック
if ($_FILES['image']['size'] > 1000000) {
$create_thread_error[] = 'ファイルサイズが大きすぎます。';
}
// getimagesizeを利用しMIMEタイプをチェック
$imageInfo = getimagesize($_FILES['image']['tmp_name']);
list($orig_width, $orig_height, $image_type) = $imageInfo;
if ($imageInfo === false) {
$create_thread_error[] = '画像ファイルではありません。';
} else {
$ext = substr($_FILES['image']['name'], strrpos($_FILES['image']['name'], '.') + 1);
if (false === $ext = array_search(
$imageInfo['mime'],
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
),
true
)) {
$create_thread_error[] = '画像形式が未対応です。';
}
}
$user = wp_get_current_user();
$upload_dir = wp_upload_dir();
$image_url = $upload_dir['path'] . '/'. $user->get('user_login').'-'. date(YmdHis) .'.'. $ext;
if (!move_uploaded_file($_FILES['image']['tmp_name'],$image_url)) {
$create_thread_error[] = 'ファイル保存時にエラーが発生しました。';
}
} else {
$create_thread_error[] = 'ファイルが選択されていません。';
}
}最後のエラー文で画像の投稿は必須としているが、そこはご自由に。
画像の名前も上書きが発生しないよう「ユーザID年月日時分秒.jpg」みたくしていますが、そこもご自由に。
アップした画像をアイキャッチ画像にする
前提として、Wordpress内の投稿処理の順序は下記になる。
- 記事を投稿する
- メディアファイル(画像)をアップロードする
- 記事とメディアファイルを関連付ける
1、2の処理は上記までで行っているので、3のステップにあたる。
http://wordpress.stackexchange.com/questions/40301/how-do-i-set-a-featured-image-thumbnail-by-image-url-when-using-wp-insert-post
上記を参考に create-thread.php に処理を加える。
//アイキャッチ設定
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
if(wp_mkdir_p($upload_dir['path']))
$file = $upload_dir['path'] . '/' . $filename;
else
$file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );画像のアップロードは済んでいるので、その画像URLを指定するだけで参考元まんまで動く。
ソース
参考までに自分がテストで作って動作したソースを丸々掲載。
セッション処理も加えてますが、そこは普通にPHPのやり方で。
<?php
/**
* Template Name: スレッド投稿フォーム
*/
get_header(); ?>
<?php
if(is_user_logged_in()): //Login check
$user = wp_get_current_user();
?>
<?php //echo $title ?>
<form action="<?php the_permalink();?>" method="post" enctype="multipart/form-data">
<?php
// セッション処理
session_start();
require_once "functions/definition.php";
$content_txt = "";
ini_set("session.bug_compat_42", 0);
ini_set("session.bug_compat_warn", 0);
if(isset($_SESSION[TITLE])) $content_txt = $_SESSION[TITLE];
if(isset($_SESSION[CONTENT])) $content_txt = $_SESSION[CONTENT];
show_thread_error();
wp_nonce_field('create_thread');
?>
<table class="form-table">
<tbody>
<tr>
<th><label for="title">タイトル</label></th>
<td><input id="title" type="text" name="title" value="<?php echo $title_txt; ?>" /></td>
</tr>
<tr>
<th><label>画像</label></th>
<td><input type="file" name="image" /></td>
</tr>
<tr>
<th><label>カテゴリー</label></th>
<td><?php wp_dropdown_categories(); ?></td>
</tr>
<tr>
<th><label for="content">コメント</label></th>
<td><textarea id="content" name="content"><?php echo $content_txt; ?></textarea></td>
</tr>
</tbody>
</table>
<p class="submit"><input type="submit" value="投稿する" /></p>
</form>
<?php else: //Login check else ?>
<p><a href="<?php echo wp_login_url(get_permalink()); ?>">ログイン</a>してください。</p>
<?php
endif; //Login check
get_footer();
?><?php
/**
* テンプレートが読み込まれる直前で実行される
*/
global $create_thread_error;
$create_thread_error = array();
// セッション処理
session_start();
require_once "definition.php";
$_SESSION[TITLE] = $_POST[TITLE];
$_SESSION[CONTENT] = $_POST[CONTENT];
// 投稿する
function _my_create_thread(){
if(
is_page('create-thread') //create-thredページチェック
&&
is_user_logged_in() //ログインチェック
&&
isset($_POST['_wpnonce']) //wpnonceチェック
&&
wp_verify_nonce($_POST['_wpnonce'], 'create_thread') //wpnoceベリファイ
){
// バリデーション
global $create_thread_error;
if(!isset($_POST['title']) || empty($_POST['title'])){
$create_thread_error[] = 'タイトルが空白です。';
}
if(!isset($_POST['content']) || empty($_POST['content'])){
$create_thread_error[] = '本文が空です。';
}
if (isset($_FILES['image']['error']) && is_int($_FILES['image']['error'])) {
// ファイルバリデーション
if (!$_FILES['image']['error']) {
// サイズ上限チェック
if ($_FILES['image']['size'] > 1000000) {
$create_thread_error[] = 'ファイルサイズが大きすぎます。';
}
// getimagesizeを利用しMIMEタイプをチェック
$imageInfo = getimagesize($_FILES['image']['tmp_name']);
list($orig_width, $orig_height, $image_type) = $imageInfo;
if ($imageInfo === false) {
$create_thread_error[] = '画像ファイルではありません。';
} else {
$ext = substr($_FILES['image']['name'], strrpos($_FILES['image']['name'], '.') + 1);
if (false === $ext = array_search(
$imageInfo['mime'],
array(
'jpg' => 'image/jpeg',
'png' => 'image/png',
'gif' => 'image/gif',
),
true
)) {
$create_thread_error[] = '画像形式が未対応です。';
}
}
$user = wp_get_current_user();
$upload_dir = wp_upload_dir();
$image_url = $upload_dir['path'] . '/'. $user->get('user_login').'-'. date(YmdHis) .'.'. $ext;
if (!move_uploaded_file($_FILES['image']['tmp_name'],$image_url)) {
$create_thread_error[] = 'ファイル保存時にエラーが発生しました。';
}
} else {
$create_thread_error[] = 'ファイルが選択されていません。';
}
}
//エラーが無ければ投稿処理
if(empty($create_thread_error)){
$post_id = wp_insert_post(array(
'post_title' => (string)$_POST['title'],
'post_content' => (string)$_POST['content'],
'post_status' => 'publish',
'post_author' => get_current_user_id(),
'post_type' => 'post',
'post_category' => array(intval($_POST['cat']))
), true);
//アイキャッチ設定
$image_data = file_get_contents($image_url);
$filename = basename($image_url);
if(wp_mkdir_p($upload_dir['path']))
$file = $upload_dir['path'] . '/' . $filename;
else
$file = $upload_dir['basedir'] . '/' . $filename;
file_put_contents($file, $image_data);
$wp_filetype = wp_check_filetype($filename, null );
$attachment = array(
'post_mime_type' => $wp_filetype['type'],
'post_title' => sanitize_file_name($filename),
'post_content' => '',
'post_status' => 'inherit'
);
$attach_id = wp_insert_attachment( $attachment, $file, $post_id );
require_once(ABSPATH . 'wp-admin/includes/image.php');
$attach_data = wp_generate_attachment_metadata( $attach_id, $file );
wp_update_attachment_metadata( $attach_id, $attach_data );
set_post_thumbnail( $post_id, $attach_id );
//データの挿入に成功していたら移動
if(!is_wp_error($post_id)){
//ページを移動
header('Location: '.get_permalink($post_id));
die();
} else {
$create_thread_error[] = '投稿時にエラーが発生しました。'.$post_id->get_error_message();
}
}
}
}
add_action('template_redirect', '_my_create_thread');
/**
* スレッド作成画面でエラーがあれば表示
* @global array $create_thread_error
*/
function show_thread_error(){
global $create_thread_error;
if(!empty($create_thread_error)){
echo '<div id="error">';
echo implode('<br />', $create_thread_error);
echo '</div>';
}
}
?>筆者について
- ゲームとジョジョを愛するファミッ子世代。好きな言葉は「機能美」。
公私ともにWebサービスを作る系男子。
最近の投稿
運用2017.03.03nginxのkusanagiにLet’sEncryptをかけてるとiOSで表示されない問題の解決
運用2016.07.22分かりにくい「クリエイティブコモンズ」をシンプルに言うと
WordPress2016.07.12新しいWordPress「Calypso」を試した
Design2016.03.09Win10アプリのデザインガイドラインが素晴らしい
こんにちは。
こちらの記事を参考にオリジナル画像アップローダを自分のテーマにて盛り込もうと思っています。こちらのコードで作成されたアップローダーはwordpressのuploadsディレクトリではなく、テーマに別途「imgフォルダ」を作成してそこに格納するようにしたいのですが、可能でしょうか?
wp_upload_dir
を
bloginfo(‘template_directory’).’/img’;
としているのですが、エラーがでてしまいます。
uploads以外の指定のフォルダにアップロードはできないでしょうか?
ご教授いただければ助かります。
遅レスで申しわけありませんがコメントありがとうございます。
実際試したわけではありませんが思いつく原因として、bloginfo(‘template_directory’)だとhttp~からの絶対URLになるので、そこが怪しいです。
画像アップ後のテンポラリファイルから他フォルダへの移動はサーバ内操作になるので、相対パス(サーバーパス)じゃないとダメじゃないかなーと。
bloginfoの値を変数にとってURLを加工すれば実現できそうに思います。
こちらを参考に勉強させてもらっていますが、なかなかうまくいきません。
質問なのですが、definition.phpというファイルを読み込んでいるのは、通常必要ないものなのでしょうか?
あと、create-thread.phpを読み込んでいる気配が無いのですがどこで読み込むのでしょうか?
参考URLにfunction.phpに以下を記載するとありますが、
get_template_part(‘functions/create-thread’);
これでcreate-thread.phpを読み込んでいることになるのでしょうか?
>モンさん
レス遅れ申しわけありません。
> 質問なのですが、definition.phpというファイルを読み込んでいるのは、通常必要ないものなのでしょうか?
すいません、アイキャッチ画像を変更させるだけのカスタマイズならば definition.php は不要になります。
フォームを入力した後のセッション保持処理のためだけのファイルなので省いてもらっても動作的には問題ありません。
> あと、create-thread.phpを読み込んでいる気配が無いのですがどこで読み込むのでしょうか?
仰られている通り「get_template_part(‘functions/create-thread’);」で読み込んでいます。
この辺りは普通にPHPの記述方法になります。
はじめまして。
こちらの記事を参考の画像投稿フォームを製作させて頂いています。
>>紹介されているソースには一部ミスがあるので注意。
とのことですが、どの部分のことなのでしょうか?
教えて頂けると助かります。
ご質問ありがとうございます。
とはいえさすがに1年以上前の内容なので、どこにミスがあったのか覚えてません…当時具体的に書かなかった自分が呪わしいです。
紹介先のソースをトレースされて正常に実行できているなら、紹介先ですでに直されている可能性もあるのですが、トレースした上で動かなければ気付ける内容でした(自分は実際それで気付きました)
回答になっておらず申し訳ありませんが、トレースした上で異常が出るならば若干のデバッグで気付ける内容だと思うので実践を試してみてください。
丁度自分がやりたいことの解説を書いてくださり、大変助かっております。解説ありがとうございます。
ご相談がございます。
画像がメディアライブラリに追加されているところまでは確認できたのですがアイキャッチとして設定がされません。
カスタム投稿タイプを設定している以外、あまり大きな違いはないのですが、アイキャッチに設定されない要因をご存知でしたらご教示いただきたいです。
ソースコード
↓
http://climbi.com/static/6095-0.txt
ご質問ありがとうございます。
2年前の内容なので今のWPで通用するか確証とれませんが、アイキャッチ設定だけうまくいかないならば、提示いただいたソース112行目の「set_post_thumbnail」の挙動を確認してみてください。
https://goo.gl/2ltavS
・set_post_thumbnailがfalseで返っていないか
・$post_id、$attach_idの中身は正しく渡せているか
このくらいかなぁと思います。
早速のご返信ありがとうございます。
おっしゃるとおり「set_post_thumbnail」がうまく動作していませんでした。
set_post_thumbnail( $id, $attach_id );
に修正したところ、正しくアイキャッチが表示されるようになりました。
解決したようで幸いです!
この記事のおかげで実装出来ました。ありがとうございます。
二点ほどご質問させてください。
カスタムポストタイプへの投稿時にタクソミソーの投稿はどうすればよろしいでしょうか?
‘post_type’ => ‘test’,
//’post_category’ => array(intval($_POST[‘cat’]))
‘tax_input’ => array(intval($_POST[‘cat’]))
この様に修正しましたがタクソミソーが空で投稿されます。
もし、よろしければご教授お願いします。
ご質問ありがとうございます。
タクソノミーは「そんな用語見たことあるな」くらいで使ったことが無いので実用的な回答では無いかもしれませんが、気になったので少しググッたらまず下記のような記事が。
https://ja.forums.wordpress.org/topic/146957
解決してないようなのでもうチョイ調べると「wp_insert_post」の注意事項に「tax_input」への挿入について記述がありました。
http://goo.gl/taQHZW
「wp_set_object_terms()」を使ってあらためてpostに対してタクソノミーをセットする感じでしょうか。お試しいただければと思います。
省略
‘tax_input’ => array(‘test_cat’ => array(intval($_POST[‘cat’])))
),
true);
$postid = wp_insert_post( $post );
if($postid !=0){
wp_set_object_terms( $postid, array(intval($_POST[‘cat’])), ‘test_cat’ );
この様に書いたら無事出来ました。助かりました。ありがとうございます。
}
解決したようで幸いです!