wordpressプラグインをクラスベースで開発

wordpressでクラスを使ってカスタマイズする方法を自分なりにまとめてみます。
今回はプラグイン開発でクラスを使って分かったことや
自分が経験したハマりどころなどを中心に書いていきます。

#主な書き方

```例1.php
class Get_Post_Test {

	public function __construct() {
		add_action( 'wp', array( $this,'get_post_id_of_current' ) );
	}

	public function get_post_id_of_current () {
		$post_data = get_post();
		print_r($post_data->ID );
	}

}

$base_information = new Get_Post_Test();
```

##ポイントは以下

```
add_action( 'wp', array( $this,'get_post_id_of_current' ) );
```

add_action関数の第2引数を配列でわたしている
（通常は関数名を文字列形式構文で渡す。
例：add_action( 'wp', 'get_post_id_of_current' );
↑通常はこんな感じで渡す　）
これにより以下のように関数をprivateにするとエラーとなる。

```
private function get_post_id_of_current () {
```

privateというアクセス修飾子はクラス内からのアクセスを許可するもの
前述の例1.phpを再度確認してみるとコンストラクタを通ってはいるものの
実質的な呼び出しはadd_actionが行っている。
だから設定したフックのタイミングで実行されるし
アクセス修飾子もpublicでないと発火しない。

#クラスでカプセル化することのメリット
・他のプラグイン、テーマ、コアなどとの関数名のかぶりを回避できる。
・メソッド名が単純に記述できるのでわかりやすくなる。
・再利用性が上がる。
・セキュリティも向上する。

##デメリット
クラスのお作法を理解し、守らないと動かない。

#個人的にはまったこと
オブジェクト指向とプラグイン開発共に経験が薄い状態で
いきなりやったこともあり、冒頭に書いたadd_actionのところ
アクセス修飾子、フックなどが絡み合い、またほかの関数などもあったので
なかなか動かすことができなかった。（上記ソースは一部抜粋）

上記ソースのget_postというworpdress関数は投稿の情報を取得するというものだが
ソースが書かれている場所はプラグインディレクトリ。
通常はテーマ内テンプレやfunctionsで書けば読み込まれた時点で実行される、
なんてことはない関数だがプラグインディレクトリに配置する場合
wordpressの実行プロセスを理解し
適切なタイミングでフックを設定しないと動かない。
ちなみにget_postはinit,wp_loaded,shutdownなどのフックでは動かず
global $post変数がセットされるwpフックでのみ動かすことができた。
これはget_post関数が内部的にWP_Postオブジェクトを返しているというのも関連がありそう。

今回wordpressのカスタマイズはフックがみそという印象を受けた。

###プラガブル関数
[別投稿でも書かせていただきましたが](https://qiita.com/SwuBHj8aKGqBKHet/items/fd76291de21e1257eb1c)
プラガブル関数というものがあります。

これはwordpress標準の関数ですが
開発者がオーバーライドでき、プラグインの後に読み込まれるため
プラグインの中でただ書いても認識されません。

詳細は上記記事を見ていただければと思いますが
これもフックを利用することでもう一回読み込みに行くみたいなことができます。
プラグイン→プラガブル関数→initアクションフックのタイミングでプラグイン内の関数を実行
みたいな流れです。

#参考にさせていただいたページ
wordpressでのオブジェクト指向開発はまだまだ情報が少ない気がします。

[日本語](https://stein2nd.wordpress.com/2013/10/04/wordpress_and_oop/)
[原文](https://scotty-t.com/2012/07/09/wp-you-oop/)

翻訳していただいていたのが非常に助かりました。

##書籍
「wordpressプラグイン開発のバイブル」
書籍でプラグイン開発において直接クラスの書き方を教えてくれる貴重な本でした。

#注意点
プラグインにクラスだけ定義してテーマから使うようなケースで
require_onceは必要なかったので備忘録的にメモしておきます。

例えば

```plugins/myplugin/class.myplugin.php

class MY_Plugin {
    puglic function myfunction() {
        echo 'require_onceは必要ありません';
    }
}

```


```themes/mytheme/page.php

//require_once ('../../plugins/myplugin/class.myplugin.php');
//↑これは必要ない。requireで読み込んでしまうとプラグインで読み込まれているので２重に読み込まれた形になるためエラーとなる。

//以下の記述をしてプラグインを有効にするとプラグインのクラス内の関数を実行できる。
$my_plugin = new MY_Plugin();
$my_plugin->myfunction();

```

#今回わかったこと
・wordpressは手続き型関数で開発しやすいように作られている。初心者にはやりやすい。
・オブジェクト指向でプラグイン開発しようとするとフック、実行の流れを把握する必要がある。
　これは関数ごと、global変数などもそれぞれ違うためその都度確認する必要がある。
・プラガブル関数の癖
　┗プラグインの後に読み込まれる。
　┗オーバーライド可能。
　┗とはいえなるべくオーバーライドより、フックやクラスなどで対応するほうが良い。
　┗今後は増えない予定。
###・トレイトの使い方
関数が実行できないという状況でwordpressのグローバル変数を利用する
アプローチを考えていた時、トレイトが使えそうだということで試してみたらいけた。

```トレイト.php
trait Wpglobal
{
	public function get_current_post_id () {
		global $post;
		$current_post_id = $post->ID;
		echo $current_post_id;
	}
}

class Get_Post_Test {
	use Wpglobal;

	public function __construct() {
		add_action( 'wp', array( $this,'get_post_id_of_current' ) );
	}

	public function get_post_id_of_current () {
		$this->get_current_post_id();
	}
}

$base_information = new Get_Post_Test();
```

#今回生まれた疑問
・wordpressをカスタマイズする際はオブジェクト指向でやったほうがいいのか？
　手続き型でやったほうがいいのか？開発の規模、セキュリティレベルなどで
　判断することと思うが今後の流れはどちらなのか？
・wordpress標準関数を絡めると同時にフックも絡まることになる。
　フックが絡むとクラスのメンバメソッドでreturnを返すことが難しくなる。（やり方わからん）
　wordpress標準関数は素直にグローバルに書いたほうがいいのか？


#自分なりの書き方まとめテンプレ
セキュリティを少しでも向上させるためメンバメソッドを
プライベートにするべく以下のように考えてみました。
突っ込みありましたら是非お願いいたします。

```テンプレ.php

class Get_Post_Test {

	public function __construct() {
		add_action( 'wp', array( $this,'my_bridge' ) );
	}

	public function my_bridge () {
		$this->get_post_id_of_current ();
		$this->my_function1();
		$this->my_function2();
	}

	private function get_post_id_of_current () {
		$post_data = get_post();
		print_r($post_data->ID );
	}

	private function my_function1 () {
		echo "1";
	}

	private function my_function2 () {
		echo "2";
	}

}

$base_information = new Get_Post_Test();

```