2014年11月1日土曜日

Welcartにおけるredirect処理 1/3

WordPressを利用しECサイトを構築するためのPlug-in Welcartにおける備忘録

このプラグインで構築したサイトで利用する送信ボタンやカートに入れるボタンといったリンク類においてのページ遷移処理が分かりにくかったのでまとめる。

解説の最終目標

独自に作った固定ページのフォーム内のボタンから、Welcartのredirect処理を通じて テンプレートとなる.phpファイルを読み込み、ページを表示する事とします。

はじめに

まず、Welcartにおけるページ遷移処理を解説するサンプルとしては
wc_templates\wc_new_member_page.phpを選んだ。
このファイルは、新規入会フォーム画面を表示しているファイルである。
[Welcart ライブデモ]では"新規ご入会はこちら"などをクリックすることで 表示されるページ
[新規入会フォーム]がそれである。
このファイルからフォームを生成しているhtmlを探すと
    <form action="<?php echo apply_filters('usces_filter_newmember_form_action', usces_url('member', 'return')); ?>" method="post" onKeyDown="if (event.keyCode == 13) {return false;}">
        ・・・中略・・・
        <div class="send"><?php usces_newmember_button($member_regmode); ?></div>
        <?php do_action('usces_action_newmember_page_inform'); ?>
    </form>
とあり、例えばlocalhostの場合は
http://localhost/wordpress/?page_id=55&page=newmember
といったURLがformのaction属性に指定されているのが分かる。このURLは、新規入会フォーム自身を表示する際にrequestするURLと同じである。つまり、このフォームは"送信する"ボタンを押すと、自分自身をrequestするという動作をしている。

リクエストへの応答を登録する

次に少し話が飛ぶが、あるリクエストに対してどう応答するかを登録する処理を見ていく。この登録手続きが
plugins\usc-e-shop\classes\usceshop.class.php
内に定義されているregist_actionメソッドである。

regist_actionメソッド

このメソッドはusces_register_actionを呼び、各々の応答を登録する処理をしている。新規入会フォームで送信するボタンを押したときに呼び出される処理は
    function regist_action(){
        ・・・他の挙動を登録する処理・・・
        // 新規入会フォームで送信するボタンを押したときの挙動
        usces_register_action('regmember', 'request', 'regmember', NULL, 'regmember');
        ・・・他の挙動を登録する処理・・・
    }
として登録されている。

usces_register_actionメソッド

function usces_register_action($handle, $type, $key, $value, $function){
    global $usces_action;
    $usces_action[$handle] = array('type'=>$type, 'key'=>$key, 'value'=>$value, 'function'=>$function);
}
usces_register_actionメソッドはglobalな$usces_actionに$handleをキーとして
array('type'=>$type, 'key'=>$key, 'value'=>$value, 'function'=>$function)
を登録している。新規入会フォームで送信するボタンを押したときの処理は、
$usces_action['regmember'] =
    array('type'=>'request', 'key'=>'regmember', 'value'=>NULL, 'function'=>'regmember')
と登録される。

usces_register_actionメソッドはどこで呼ばれているか

では、紹介した登録手続きを行うusces_register_actionメソッドがどこから呼ばれているかを探してみると
\wp-content\plugins\usc-e-shop\usc-e-shop.phpで
<?php
/*
Plugin Name: Welcart e-Commerce
Plugin URI: http://www.welcart.com/
Description: Welcart builds the management system with a net shop on Wordpress.
Version: 1.3.16
Author: Collne inc.
Author URI: http://www.welcart.com/
*/
・・・中略・・・
global $usces;
$usces = new usc_e_shop();
$usces->regist_action();
として呼び出されていることが分かる。
このusc-e-shop.phpファイルは、welcartプラグインの最初のファイルで、プラグインをWordPressに認識させるために必要なファイルであり、プラグインを有効にするとこの中のPHPファイルが実行されるようになる。
つまり、Welcartプラグインが有効になると、regist_actionメソッドが実行され、先に紹介した
$usces_action['regmember']
といった登録も行われることが分かる。

さて、登録はできた。じゃあ、呼び出しているのはどこだ???

結論から先に言うと、今まで行ってきた登録を適宜呼び出しを行っているのは
wp-content\plugins\usc-e-shop\classes\usceshop.class.phpにある
ad_controllerメソッドである。このメソッドが$usces_actionに登録された内容によって、必要に応じて処理を進めている。

ad_controllerメソッドはどこから呼ばれる?

話をad_controllerメソッドの内容に進める前に、このメソッドはどこから呼ばれているのかを見ていきたい。この関数は
wp-content\plugins\usc-e-shop\classes\usceshop.class.php
に定義されているmainメソッドから呼ばれている。
このメインメソッドは
wp-content\plugins\usc-e-shop\includes\default_filters.php
内で
add_action( 'init', array(&$usces, 'main'), 10);
とフックされ、'init'アクションにフックされていることが分かる。この'init'アクションは
WordPress日本語Codexによると

WordPressの読み込みが完了し、ヘッダーが送信される前に実行する。$_GET や $_POST トリガーを妨害するために使える。

とある。要は、WordPressの読み込みが完了して、ページを表示する前に呼び出しがされるアクションである。
この'init'アクションにmainメソッドをフックしているadd_actionが書かれているdefault_filters.phpは、先ほども紹介した Welcartプラグインの最初のファイル、usc-e-shop.phpからrequire_onceされている。
require_once(USCES_PLUGIN_DIR."/includes/default_filters.php");
よってプラグインが有効であれば結果的に、ページが表示される前にmainメソッド内のad_controllerが実行されることが分かる。

ad_controllerの中身を見てみよう

さて、ここまでで、$usces_actionに登録された内容に従ってad_controllerメソッドがページを表示する前に何かやっていることは説明したが、ここからad_controllerメソッドの中身を見ていこうと思う。

ad_controllerメソッド

ad_controllerメソッドは、
    function ad_controller(){
        global $usces_action;
            ・・・中略・・・
            $action_array = array('inCart', 'upButton',
            ・・・中略・・・
            'regmember',
            ・・・中略・・・
            ,'front_ajax');
            $flg = 0;
            $res = true;
            foreach( $usces_action as $handle => $action ){
                extract($action);
のように$usces_actionに登録された内容を$handle => $actionに分解し、foreachにて各々処理しようとしている。
話を単純にするために、
usces_register_action('regmember', 'request', 'regmember', NULL, 'regmember');
だけがされていた場合に話を限定すると、ここまでの処理で、
$handle = 'regmember'
$type = 'request'
$key = 'regmember'
$value = NULL
$function = 'regmember'
となることが分かる。続くコードは、
                    case 'post':
                        ・・・中略・・・
                        break;
                    case 'get':
                        ・・・中略・・・
                        break;
                    case 'request':
                        if( empty($value) ){
                            if( isset($_REQUEST[$key]) ){
                                if(in_array($handle, $action_array)){
                                    $res = call_user_func(array($this, $function));
                                }else{
                                    $res = call_user_func($function);
                                }
                                $flg = 1;
                            }
                        }else{
                            if( isset($_REQUEST[$key]) && $_REQUEST[$key] == $value ){
                                if(in_array($handle, $action_array)){
                                    $res = call_user_func(array($this, $function));
                                }else{
                                    $res = call_user_func($function);
                                }
                                $flg = 1;
                            }
                        }
                        break;
と、なっており、
$_REQUEST[$key]に値がセットされているときに、call_user_funcメソッドを使い、$functionの名前の関数をコールしていることが分かる。
ここで、もう一度、「新規入会フォームで送信するボタンを押したとき」の処理を見てみると、
    <form action="<?php echo apply_filters('usces_filter_newmember_form_action', usces_url('member', 'return')); ?>" method="post" onKeyDown="if (event.keyCode == 13) {return false;}">
        ・・・中略・・・
        <div class="send"><?php usces_newmember_button($member_regmode); ?></div>
        <?php do_action('usces_action_newmember_page_inform'); ?>
    </form>
となっており、ここのusces_newmember_buttonメソッドは、
$newmemberbutton = '<input name="regmember" type="submit" value="' . __('transmit a message', 'usces') . '" />';
となっており、$_REQUEST['regmember']をセットしているのが分かる。よって、call_user_funcメソッドにより、$uscesクラスのregmemberメソッドがコールされるのである。

regmemberメソッドを軽くひもとく

さて、ここまでで呼び出された、regmemberメソッドが何を行っているかを詳細に説明してしまうと、少々、ページ遷移処理の話から脱線してしまうので割愛するが、以下がコード全体である。
    function regmember(){
        global $wp_query;
        $res = $this->regist_member();
        if( 'editmemberform' == $res ){
            $this->page = 'editmemberform';
            add_filter('yoast-ga-push-after-pageview', 'usces_trackPageview_editmemberform');
        }elseif( 'newcompletion' == $res ){
            $this->page = 'newcompletion';
            add_filter('yoast-ga-push-after-pageview', 'usces_trackPageview_newcompletion');
        }else{
            $this->page = $res;
        }
        add_action('the_post', array($this, 'action_memberFilter'));
        add_action('template_redirect', array($this, 'template_redirect'));
    }
要は、このメソッドは新規入会フォームで入力された$_POSTを受け取り、バリデーションを行い、問題がなければデータベースへの登録を行っている。そして、登録が問題なく行われた場合
$usces->pageを$this->page = 'newcompletion';
としている。そして、最後に
add_action('template_redirect', array($this, 'template_redirect'));
として、'template_redirect'アクションにtemplate_redirectメソッドをフックしている。この'template_redirect'アクションはページが読み込まれてテンプレートを取得する直前に実行されるフックです。そのタイミングで$uscesクラスのtemplate_redirectメソッドがコールされることが分かります。

template_redirectメソッド

さて、長い長い旅の先にようやくここまで来ましたが、ここが最後です。
このメソッドは、$usces->pageが'newcompletion'のときに、
                        if( file_exists(get_stylesheet_directory() . '/wc_templates/member/wc_member_completion_page.php') ){
                            include(get_stylesheet_directory() . '/wc_templates/member/wc_member_completion_page.php');
                            exit;
                        }
となっており、/wc_templates/member/wc_member_completion_page.phpが存在していれば、そのファイルを読み込んでいます。
wc_member_completion_page.phpは「新規ご入会有難うございます。」の書かれた新規入会完了ページを表示するファイルであり、これで、新規入会フォームから、データベース登録処理などを経て、無事、完了ページへ遷移することができました。

冒険はまだまだ続く

少々、長い説明となり、ご自身でもソースを追っていただくことは避けられないかと思いますが、この解説がWelcartを読み解く一助となればと思います。
次回は、今回解析した内容を使って、自作の固定ページからwelcartのredirect処理を使って、特定のphpファイルを読み込みページを表示させてみようと思います。

参考

PHPによるWordPressカスタマイズブック―3.x対応 p.194~あたり

0 件のコメント:

コメントを投稿