wordpressでフロントからメディアに画像を投稿する方法

先日マッチングサイトでフロントから画像投稿をできるようにしたときに結構時間がかかったので覚書


まずは登録フォームを作成する

【登録フォームページ】

```html
<form method="POST" action="" enctype="multipart/form-data">
	<dl>
		<dt>画像</dt>
		<dd>
			<p><img id="preview" src=""></p>
			<p><input type="file" id="myImage" name="myImage" value="" accept="image/png,image/jpeg"><input type="hidden" id="img_url" name="img_url" value=""></p>
		</dd>
	</dl>
</form>
<script>
$(function(){
	$('#myImage').on('change', function (e) {
		console.log($(this).prop('files')[0]);
		var reader = new FileReader();
		reader.onload = function (e) {
			$("#preview").attr('src', e.target.result);
			$("#img_url").val(e.target.result);
		}
		reader.readAsDataURL(e.target.files[0]);
	});
});
</script>
```

確認ページを挟む場合は一度画像をサーバーに仮で置かなければファイルデータを受け渡しできない

【確認ページ】

```php
<?php
session_start();
if(!empty($_FILES['myImage'])){

        // ①現在時刻を取得
        $now = date("YmdHis");
        
        // ③$_FILESデータを変数pictureに入れる
        foreach($files as $key => $var){
            $picture[$key] = $var;
        }
        
        // ④画像のバリデーション
        $finfo = finfo_open(FILEINFO_MIME_TYPE);
        list($mime,$ext) = explode("/",finfo_file($finfo, $picture["tmp_name"]));

        // 画像を仮で置くディレクトリ
        $target = __DIR__.'/tmp/';
        
        
        // ⑤$_FILES内のファイルデータを名前を変えて仮のディレクトリ（tmp）に移す
        move_uploaded_file($picture['tmp_name'], $target.$now."_picture.".$ext);

        // ⑥アウトプット用の変数に画像データを格納
        $output_file['name'] = $picture['name'];

        // ⑦アウトプット用の変数のtmp_nameの値を仮のディレクトリ内のファイル名に設定する
        $output_file['tmp_name'] =  $now."_picture.".$ext;

        // ⑧アウトプット用の変数のurlに確認画面で表示するための画像urlを格納する
        $output_file['url'] =  $target.$now."_picture.".$ext;

        finfo_close($finfo);

        //SESSIONに仮置きの画像のデータを入れる
        $_SESSION['output'] = $output_file;
}

?>

<form method="POST" action="">
	<dl>
		<dt>画像</dt>
		<dd><?php if(isset($_POST['img_url'])){echo '<img src="'.$_POST['img_url'].'">';}?></dd>
	</dl>
	<button>登録</button>
</form>

```

確認ページを挟まないのであればサーバーに仮置きしなくてもOK

【登録するPHP】

```php
<?php
session_start();

//まずはwordpressの関数を使えるようにする
require_once('../../../../wp-load.php');
require_once(ABSPATH . 'wp-admin/includes/media.php');
require_once(ABSPATH . 'wp-admin/includes/file.php');
require_once(ABSPATH . 'wp-admin/includes/image.php');


/*↓↓↓↓↓↓↓↓↓↓↓↓↓画像のアップロード↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓↓*/

// アップロード用ディレクトリのパスを取得。
$wp_upload_dir = wp_upload_dir();

//　もしもアップロード用ディレクトリがなければ作成
if(!file_exists($wp_upload_dir['path'])){
	mkdir($wp_upload_dir['path']);
}

//名前がダブってる時の措置
$img_info = pathinfo($_SESSION['output']['name']);
$img_name = $img_info['filename'];
$i = 1;
while(!empty($_SESSION['output'])){
	if(file_exists($wp_upload_dir['path'].'/'.$img_name.'.'.$img_info['extension'])){
		$img_name = $img_info['filename'] . '-' . $i;
		$i++;
	}else{
		break;
	}
}

//名前のダブりがなくなったところで仮置きのファイルをwordpressのアップロードディレクトリに移動
rename($_SESSION['output']['url'],$wp_upload_dir['path'].'/'.$img_name.'.'.$img_info['extension']);


// $filename はアップロード用ディレクトリにあるファイルのパス。
$filename = Date('Y').'/'.Date('m').'/'.$img_name.'.'.$img_info['extension'];

// ファイルの種類をチェックする。これを 'post_mime_type' に使う。
$filetype = wp_check_filetype( basename( $filename ), null );

// 添付ファイル用の投稿データの配列を準備。
$attachment = array(
	'guid'           => $wp_upload_dir['url'] . '/' . basename( $filename ), 
	'post_mime_type' => $filetype['type'],
	'post_title'     => preg_replace( '/\.[^.]+$/', '', basename( $filename ) ),
	'post_content'   => '',
	'post_status'    => 'inherit'
);

// 添付ファイルを追加。
$attach_id = wp_insert_attachment( $attachment, $filename, 0 );

// 添付ファイルのメタデータを生成し、データベースを更新。
$attach_data = wp_generate_attachment_metadata( $attach_id, $wp_upload_dir['path'].'/'.$_SESSION['output']['name'] );
wp_update_attachment_metadata( $attach_id, $attach_data );

/*↑↑↑↑↑↑↑↑↑↑↑↑↑↑画像のアップロード↑↑↑↑↑↑↑↑↑↑↑↑↑↑*/


?>
```

上記で登録画像がメディアに登録される。

固定の投稿に紐づけたい場合はwp_insert_attachmentの第3引数を投稿IDに変更