Advanced Custom Fieldでフロントエンドの投稿フォームを作る方法

最近は、Wordpressを使った変わった案件が多いです。
顧客管理システムやファイルサーバー、求人サイトなど
どれもWordpressの純正機能では限界を感じるものばかりです。

コーポレートサイトももちろん、そういった案件もサポートしてくれるのは
Advanced Custom Fieldというプラグインです。現在は有料版のver5も
リリースされておりまして、買う価値のあるプラグインです。ver4であれば
無料でも使えます。今回紹介する内容は、残念ながら**有料版限定**になりますので、
ご注意下さい。

オフィシャルサイトはこちら
http://www.advancedcustomfields.com/

プラグインの本来の目的は、Wordpressのカスタムフィールドを拡張して
使いやすくすることですが、今回はあんまり知られていない別な使い方を
紹介しようと思います。

## ACFに投稿フォームを出力させる便利な関数がある
通常は、Wordpressのユーザーとして管理画面にログインして、投稿を行います。
しかし、ユーザー登録なしで投稿してもらいたいときや、
Wordpressの使用感を表に出したくない時に`acf_form`関数が非常に便利です。

ドキュメントページはこちらです。
http://www.advancedcustomfields.com/resources/acf_form/

英語で関数の引数が紹介されていますので、日本語で簡単な説明をつけておきます。

```php
<?php acf_form( $options ); ?>
```

`$options`で指定できるパラメータは下記の通りです。

* `id` フォームを識別するための文字列です。変えることは滅多にありません。
* `post_id` 既存の投稿を編集する場合は、投稿のIDを指定します。新規投稿の場合は`new_post`にします。
* `new_post` post_idをnew_postにした場合にこちらのパラメータが有効になります。新規投稿のパラメータを指定します。[wp_insert_post](https://codex.wordpress.org/Function_Reference/wp_insert_post)の`$post`パラメータと同じものを指定できます。
* `field_groups` 通常は、その投稿に紐付けられているすべてのカスタムフィールドが表示されますので、特定のグループのみを表示させたい場合はこちらにグループIDを配列形式で指定します。
* `fields` 原理は`field_groups`と同じですが、グループではなくフィールドの個別指定ができます。配列にフィールドのkeyかIDを指定できます。
* `post_title` 投稿のタイトルを編集できるようにするかどうかを決めるパラメータです。デフォルトではfalseです。
* `post_content` 投稿の本文を編集できるようにするかどうかを決めるパラメータです。こちらもデフォルトではfalseです。
* `form` formタグを出力するかどうかを決めます。デフォルトではtrueです。
* `form_attributes` formタグの属性(classやdataなど)を追加できます。配列で指定できます。
* `return` 投稿保存後にリダイレクトするURLを指定できます。%post_url%は投稿のパーマリンクに置き換わるそうです。デフォルトでは、現在のURLにupdated=trueパラメータが追加されたものになります。
* `html_before_fields` 各フィールドの前にHTMLを指定できます。
* `html_after_fields ` 各フィールドの後にHTMLを指定できます。
* `submit_value` 保存／更新 ボタンに表示する文字列を指定できます。
* `updated_message` 投稿の保存後に表示されるメッセージを指定できます。
* `label_placement` フィールドラベルの表示位置です。topかleftを指定できます。デフォルトはtopです。
* `instruction_placement` フィールド説明文の表示位置を指定できます。ラベルの下はlabelで、フィールドの下はfieldです。
* `field_el` フィールドを囲むタグの指定です。`div, tr, ul, ol, dl`を指定できます。デフォルトはdivです。

## 実際にフォームを作ってみる
```php:index.php
<?php acf_form_head(); ?>
<!DOCTYPE html>
<html lang="ja">
	<head>
		<meta charset="UTF-8">
		<title>acf_formのテスト</title>

		<?php wp_head(); ?>

		<link rel="stylesheet" type="text/css" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css">
		<style>
			.acf-form-submit{
				text-align: center;
			}
		</style>
	</head>
	<body>
		<div class="container">
			<h2>テストフォーム</h2>
			<?php acf_form(array(
				"post_id" => "new_post",
				"post_title" => true,
				"post_content" => true,
				"updated_message" => "投稿を作成しました！"
			)); ?>
		</div>

		<?php wp_footer(); ?>
		
		<script>
			(function($){
				$(function(){
					$(".acf-form-submit input[type='submit']").addClass("btn btn-success").css("width", "30%");
				});
			})(jQuery);
		</script>
	</body>
</html>
```

結果はこちらです。
![スクリーンショット 2015-04-09 11.12.59.jpg](https://qiita-image-store.s3.amazonaws.com/0/74723/7cd656c4-6aa4-302b-38d1-4c9fd9dca1c5.jpeg)


余計なコードも入ってますが、無視でお願いします。重要なのは**2箇所のみ**です。

* **acf_form_head()** : フォームが送信された時に、投稿を実際に保存してくれる部分になります。また、フォームに必要なCSSやJSなどのリソースを読み込んでくれます。テンプレートの出力が発生する前に置くことがポイントです。
* **acf_form** : フォームのソースを出力していくれる関数

## 保存時に何らかのアクションを起こしたい
投稿時に決まった処理をしたいこともありますよね。IPやブラウザ情報などを
カスタムフィールドに保存したり、何らかのフックを呼び出したり。そんなときのために
ACF側で下記のフックが用意されています。

フックのドキュメントはこちら
http://www.advancedcustomfields.com/resources/acfsave_post/

wordpressのフィルターやフックの使い方はこちらでわかりやすくまとまっています。
http://liginc.co.jp/web/wp/customize/92030

では、投稿が作成される際の`acf/save_post`フックを使ってみましょう。

```php:functions.php
<?php

	add_action("acf/save_post", "add_author_information", 1);
	function add_author_information( $post_id ){
		$browser = $_SERVER["HTTP_USER_AGENT"];
		$ip = $_SERVER["REMOTE_ADDR"];

		update_post_meta($post_id, "author_browser", $browser);
		update_post_meta($post_id, "author_ip", $ip);
	}

?>
```
上記のコードは、投稿保存時にユーザーのIPアドレスとブラウザ情報を
カスタムフィールドに保存するシンプルなものです。
フォームで送られてきた情報は、`$_POST["acf"]`に入りますので
一度`print_r`すると良いと思います。

フックのProirityに当たる数字ですが、実は意味を持っています。
1の場合は、カスタムフィールドが保存される前に呼び出され、20の場合は
保存後に呼び出されます。なので、1の状態では`get_field("hoge", $post_id)`を
使ってもnullしか返ってきません。

## 他のAPIドキュメント
興味を持った方は他のドキュメントも確認してみてください。
http://www.advancedcustomfields.com/resources