WordPress:投稿専用画面からユーザーにアイキャッチ画像付きで自由投稿させる

  • ダッシュボード外の投稿フォームを作る
  • 登録ユーザーが投稿できる
  • アイキャッチ画像をアップロードできる

いわばユーザ登録型画像掲示板のような仕様をWordpressで実現したのでそのメモ。

投稿処理

http://takahashifumiki.com/web/programing/2173/
こちらのWordpressの投稿の基本に沿う。
※紹介されているソースには一部ミスがあるので注意。

ちなみに自分の場合、カスタム投稿タイプは設定せず通常の投稿にしたかったので「post_type」はpostとしている。

素直に沿えば通常投稿できるので細かくは割愛。
以下は上記内容ができている前提。

ファイルアップロード

上記の投稿処理に従い、フォーム用テンプレート page-create-thread.php を作っている前提として、そちらのフォームから画像を投稿できるようにする。

page-create-thread.php
1
2
3
4
5
6
7
<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 に画像アップの処理を加える。
テキストバリデーションと投稿処理の間に入れると良い。

create-thread.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
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. 記事とメディアファイルを関連付ける

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 に処理を加える。

create-thread.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
//アイキャッチ設定
$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のやり方で。

page-create-thread.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
<?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();
?>
create-thread.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
<?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>';
  }
}
?>

筆者について

KaBuKi
ゲームとジョジョを愛するファミッ子世代。好きな言葉は「機能美」。
公私ともにWebサービスを作る系男子。