疑問1:そもそも関数wpcf7_get_request_uri()を変更せずに、uriを直打ちしなかったのはなぜか。

たとえば「/?page_id=333#wpcf7-f1539-p333-o1」をform actionの属性値として直接書き込む。

答え:実は、初めのうちは直打ちしていました。でも、なんかスマートじゃない。もうひとつあるサイト(志義ゼミナール)は、IDが異なるので別物を用意して書き換える必要があります。ちょっと面倒です。できれば、どちらのサイトのプラグインも全く同じものをコピペしたいです。メンテナンスを簡単にするためにも。そこで、直打ちはやめることにしました。

番外編その1に、メンテナンスを向上させるために、改変した内容まとめて別の関数にして、wpcf7_get_request_uri()内からrequire_onceで呼び出すように変更した内容を示します。これなら、プラグインがアップデートしても改変部分は別関数なので何もする必要はありません。require_onceで呼び出す部分だけを書き加えればOKです。実際はコピペですませます。

疑問2:なぜ、関数wpcf7_get_request_uri()を変更すればよいとわかったか?

いろんなサイトを見て参考にさせていただいています。しかし、なぜ、そのような解決策にたどり着いたのかを細かく記載されているサイトをあまり拝見したことがありません。

番外編その2に、疑問2の答えを可能な限り詳しく示しました。

4.番外1と番外2があります(備忘録的なもの)

(1)番外1(外部関数化)

(1−1)外部関数my_wpcf7_get_request_uri()の準備

基本的な内容は、wpcf7_get_request_uri()と同じですが、少し変数名などを変更しています。また、変数の中身を確認するために入れたechoはコメントアウトして残しています。あとで、動作テストをする時に再利用できるからです。

これを、my-functions.phpとして、functions.phpと同じディレクトリ(includes)に保存します。

(1−2)wpcf7_get_request_uri()内から呼び出す

functions.php内の、function wpcf7_get_request_uri()の内容を下記のように書き換える。ポイントは、require_onceでmy-functions.phpを呼び出しているところと、returnする値がmy_wpcf7_get_request_uri()で取得した値であるところです。元の内容は念のためにバックアップ用としてコメントアウトしておく。

my-functions.phpとfunctions.phpをサーバにアップして、動作確認して問題がなければ終了です。次回から、アップデートがあれば、function wpcf7_get_request_uri()の内容だけ上記のように書き換えればOKです。

(2)番外2(修正箇所の発見に向けて)

まず、WordpressのSSL化(つまりは、サイトのSSL化)をおこなったときカスタムパーマリンク(/%category%/%postname%/)では404が発生しサイトが表示されませんでした。そこで、デフォルトの/?p=123(ページID)を使って運用していました。そのときは、お問い合わせ(Contact Form 7)もちゃんと動作していました。

それでもssl.conf関係の設定をすることで、カスタムパーマリンクでもSSLで運用できるようになりました。

めでたくパーマリンクをカスタム構造(/%category%/%postname%/)にして運用していました。あるときCF7がアップデートしreCaptchaが利用できることに気付き、設定をして「お問い合わせ」の動作を確認すると、「送信」ボタンを押しても矢印がグルグル回っているだけで何もおきませんでした。「お問い合わせ」のパーマリンクは/contact/です。

そこで、パーマリンクをデフォルト(/?p=123)に戻し、「お問い合わせ」の動作を確認しました。つまり、この時点でカスタムパーマリンク(/contact/)では「お問い合わせ」のCF7が動作しないが、デフォルトのパーマリンク(/?p=123)ではCF7は動作するということです。

そこでhtmlのソースを表示て両者を比較してみました。CF7が実行される場所を注意して見ると図1、図2の458行目に違いがあることを発見しました。

<form action=”/?page_id=333#wpcf7-f1539-p333-o1″ method=”post” class=”wpcf7-form” novalidate=”novalidate”>

<form action=”/contact/#wpcf7-f1539-p333-o1″ method=”post” class=”wpcf7-form” novalidate=”novalidate”>

上が動作する場合、下が動作しない場合のhtmlです。

そこで、actionを出力しているphpを検索しましたがあまりにもたくさんヒットしたので、同じ行に出力されている属性のnovalidateを検索してみました。

私は、Ubuntuを利用しているので、端末からgrepを利用しました。(Windowsの方は、それなりのソフトでがんばってください。スミマセン;;;)

プラグインのcontact-form-7ディレクトリへ移動後、「grep -irn novalidate *」を実行します。3行目、4行目にincludes/contact-form.phpがヒットしました。

つまり、novalidateはcontact-form.phpの320行目と327行目で見つかっています。さっそく、contact-form.phpを覗いてみましょう。

ここで、actionが表示されている323行目を見ると、$urlという変数に「お問い合わせ」ページのURLが取得されているよです。(はじめは321行目に$url = /?page_id=333#wpcf7-f1539-p333-o1 と直打ちしていました。)

そこで、contact-form.php内で$urlを検索すると271行目に$urlを関数wpcf7_get_request_uri()で取得していることが分かります。

次に、grep -irn wpcf7_get_request_uri * を実行してみます。includes/functions.php内167行目にあるようです。

includes/functions.phpを覗いてみます。

add_query_arg関数で「お問い合わせ」ページのurlを取得しているようですね。add_query_arg関数を調べると引数に与えた値でパラメータクエリを造ってurlを生成するようです。つまり、

add_guery_arg(array(‘page_id’=> $id ),’/’);とすることで「/?page_id=xxxx」が取得できそうです。さっそく、次のように$id = ‘333’をセットして見ました。

「お問い合わせ」のhtmlソースを見ると、actionの属性値に「/?page_id=333」が取得されています

しかし、これでは$idを直打ちしているに過ぎません。そこで、get_the_ID()でページIDを取得させてみることにしました。

「お問い合わせ」のhtmlソースを見ると、actionの属性値に「/」のみ取得されています。つまり、IDの333は取得されていません。したがって、CF7は動作しませんでした。

そこで、$id,$request_uriに取得された値をechoで出力させます。ここで、$idの場所を関数の上部に移動させました。if文内にあると、(3)$idが未定義となってしまうからです。

出力が2箇所に分かれています。htmlの先頭部分とCF7が呼び出された部分に出力されました。

455行目でCF7が呼ばれています。

どうも、プラグインの呼び出しにはタイミングがあるようです。ちょっと調べた限りではfunctions.phpより先にプラグインが呼び出されるそうです。今回は、ブラウザがhtmlを読み込む前にプラグインが実行され、その後htmlが読み込まれた後にCF7が実行される箇所(from action部分)でまた読み込まれているようです。2回読み込まれているように見えます。

htmlが読み込まれる前なのでページは表示されていません。だからget_the_ID()ではそのページIDは取得できないので、(1)$idは空です。しかし、そのあとの$request_uri = add_query_arg( array(‘page_id’=> $id ),’/’ );では、「/」のみがurlとして取得されます。(2)$request_uri=/となります。(3)(3)$id=(3)get_the_ID()=(3)$request_uri=/となります。

次に、CF7が読み込まれる部分(455行目あたり)では、再びget_the_ID()が呼ばれ、今度はページが表示されているのでページIDの333が取得されます。$request_uriは空ではない($request_uri=/だから)ので、180行目のif内はスキップされ、$request_uriの中身は「/」のままとなります。

したがって、(1)$id=333(3)$id=333(3)get_the_ID()=333(3)$request_uri=/となっています。(2)$request_uri=/は、スキップされたので表示されません。

そこで、プラグイン(CF7)が実行される直前まで$request_uri=”のままでいて欲しいので、

if ( empty( $request_uri ) ) { }内にさらに、$idを判定して$request_uri=”を返すようにしました。それが下記のコードです。

お問い合わせのhtmlが読み込まれる前です。(2-1)$request_uri=となって、$request_uriの中身は空のままです。

お問い合わせのhtml458行目付近を見ると、(2−2)$request_uri=/?page_id=333や(3)$request_uri=/?page_id=333が取得されています。意図通りの挙動です。

動作確認をし、ちゃんとCF7が正常な挙動を示しました。

プラグインの読み込まれるタイミングはそれぞれ異なる?

CF7が動作しなかったので、インストールされている全てのプラグインを停止してコンフリクトを疑いましたが解決に至りませんでした。他にもグーグル先生にお尋ねしてプラグインの動作不良やCF7の動作不良の解決策をいろいろと調べて試しましたが解決は至りませんでした。

今回、プラグインが読み込まれるタイミングが2回あることに気づきました。この挙動がわかったことで一気に解決に至りました。今までは、プラグインが指定された箇所で初めて読み込まれるとばかり思っていました。CF7は、まず最初にブラウザがhtmlを読み込む前に呼ばれるようです。したがって、お問い合わページに関係なく、どのページを表示しても最初に読み込まれechoが出力されました。そして、次にCF7が設置された箇所で読み込まれます。

どうも、プラグインによってこの挙動は異なるようです。もし、プラグインが意図した通りに動作しない場合はechoで出力を追ってみるといいかも。(当たり前か?)