EC CUBEのセッションをWordPressで引き継ぐやつ

利用したCMSのバージョン

* EC CUBE 2.13.5
* WordPress 4.2.3

WordPressの下に設置したEC CUBEのカート情報を、WordPress側でも表示するための作業メモです。
wp-admin と同階層に /shop/ ディレクトリを作成し、その中にEC CUBEを設置した状態となります。

セッションの引き継ぎが上手くいっていないのは以下のことが原因だと考えられます。

* 有効期限が切れている
* パスがずれている or 引き継ぎたいセッション情報の範囲が制限されている
* ドメインが違う

今回はパスの問題でした。

## EC CUBE側の設定

### カート情報をセッションに持たせる

shop/data/class_extends/page_extends/cart/LC_Page_Cart_Ex.php
コアからコピーしてきてセッション取得処理を追加。
$_SESSION['cartItems']にカート情報を持たせます。

```
class LC_Page_Cart_Ex extends LC_Page_Cart
{
    /**
     * Page を初期化する.
     *
     * @return void
     */
    function init()
    {
        parent::init();
    }

    /**
     * Page のプロセス.
     *
     * @return void
     */
    function process()
    {
//        parent::process();
        $this->action();
        $this->sendResponse();
    }

    /**
     * Page のアクション.
     *
     * @return void
     */
    public function action()
    {
        //決済処理中ステータスのロールバック
        $objPurchase = new SC_Helper_Purchase_Ex();
        $objPurchase->cancelPendingOrder(PENDING_ORDER_CANCEL_FLAG);

        $objCartSess = new SC_CartSession_Ex();
        $objSiteSess = new SC_SiteSession_Ex();
        $objCustomer = new SC_Customer_Ex();

        $objFormParam = $this->lfInitParam($_POST);
        $this->mode = $this->getMode();

        // モバイル対応
        if (SC_Display_Ex::detectDevice() == DEVICE_TYPE_MOBILE) {
            if (isset($_GET['cart_no'])) {
                $objFormParam->setValue('cart_no', $_GET['cart_no']);
            }
            if (isset($_GET['cartKey'])) {
                $objFormParam->setValue('cartKey', $_GET['cartKey']);
            }
        }

        $this->cartKeys = $objCartSess->getKeys();
        foreach ($this->cartKeys as $key) {
            // 商品購入中にカート内容が変更された。
            if ($objCartSess->getCancelPurchase($key)) {
                $this->tpl_message .= "商品購入中にカート内容が変更されましたので、お手数ですが購入手続きをやり直して下さい。\n";
            }
        }

        $cart_no = $objFormParam->getValue('cart_no');
        $cartKey = $objFormParam->getValue('cartKey');

        // エラーチェック
        $arrError = $objFormParam->checkError();
        if (isset($arrError) && !empty($arrError)) {
            SC_Utils_Ex::sfDispSiteError(CART_NOT_FOUND);
            SC_Response_Ex::actionExit();
        }

        $objFormParam4OpenCategoryTree =
            $this->lfInitParam4OpenCategoryTree($_REQUEST);
        if ($objFormParam4OpenCategoryTree->getValue('product_id')) {
            $arrQueryString = array(
                'product_id' => $objFormParam4OpenCategoryTree->getValue(
                    'product_id'),
            );
        } else {
            $arrQueryString = array(
                'category_id' => $objFormParam4OpenCategoryTree->getValue(
                    'category_id'),
            );
        }

        switch ($this->mode) {
            case 'confirm':
                // カート内情報の取得
                $cartList = $objCartSess->getCartList($cartKey);
                // カート商品が1件以上存在する場合
                if (count($cartList) > 0) {
                    // カートを購入モードに設定
                    $this->lfSetCurrentCart($objSiteSess, $objCartSess, $cartKey);

                    // 購入ページへ
                    SC_Response_Ex::sendRedirect(SHOPPING_URL);
                    SC_Response_Ex::actionExit();
                }
                break;
            case 'up'://1個追加
                $objCartSess->upQuantity($cart_no, $cartKey);

                SC_Response_Ex::reload($arrQueryString, true);
                SC_Response_Ex::actionExit();
                break;
            case 'down'://1個減らす
                $objCartSess->downQuantity($cart_no, $cartKey);

                SC_Response_Ex::reload($arrQueryString, true);
                SC_Response_Ex::actionExit();
                break;
            case 'setQuantity'://数量変更
                $objCartSess->setQuantity($objFormParam->getValue('quantity'), $cart_no, $cartKey);

                SC_Response_Ex::reload($arrQueryString, true);
                SC_Response_Ex::actionExit();
                break;
            case 'delete'://カートから削除
                $objCartSess->delProduct($cart_no, $cartKey);

                SC_Response_Ex::reload($arrQueryString, true);
                SC_Response_Ex::actionExit();
                break;
            default:
                break;
        }
        $this->arrInfo = SC_Helper_DB_Ex::sfGetBasisData();
        $totalIncTax = 0;
        foreach ($this->cartKeys as $key) {
            // カート集計処理
            $this->tpl_message .= $objCartSess->checkProducts($key);
            $this->tpl_total_inctax[$key] = $objCartSess->getAllProductsTotal($key);
            $totalIncTax += $this->tpl_total_inctax[$key];
            $this->tpl_total_tax[$key] = $objCartSess->getAllProductsTax($key);
            // ポイント合計
            $this->tpl_total_point[$key] = $objCartSess->getAllProductsPoint($key);

            $this->arrData[$key] = $objCartSess->calculate($key, $objCustomer);

            // 送料無料チェック
            $this->arrData[$key]['is_deliv_free'] = $objCartSess->isDelivFree($key);

            // 送料無料までの金額を計算
            $this->tpl_deliv_free[$key] = $this->arrInfo['free_rule'] - $this->tpl_total_inctax[$key];
        }

        //商品の合計金額をセット
        $this->tpl_all_total_inctax = $totalIncTax;

        $this->tpl_category_id =
            $objFormParam4OpenCategoryTree->getValue('category_id');
        $this->tpl_product_id =
            $objFormParam4OpenCategoryTree->getValue('product_id');

        // ログイン判定
        if ($objCustomer->isLoginSuccess(true)) {
            $this->tpl_login = true;
            $this->tpl_user_point = $objCustomer->getValue('point');
            $this->tpl_name = $objCustomer->getValue('name01');
        }

        // 前頁のURLを取得
        // TODO: SC_CartSession::setPrevURL()利用不可。
        $this->lfGetCartPrevUrl($_SESSION, $_SERVER['HTTP_REFERER']);
        $this->tpl_prev_url = (isset($_SESSION['cart_prev_url'])) ? $_SESSION['cart_prev_url'] : '';

        // 全てのカートの内容を取得する
        $this->cartItems = $objCartSess->getAllCartList();

        // [start]カスタマイズ
        // カート情報をセッションに持たせる
        $_SESSION['cartItems'] = $this->cartItems;
        // [end]カスタマイズ
    }
}
```

### セッションのパスの設定

EC CUBE側で持っているセッションID「ECSESSID」は /shop/ ディレクトリ内でしかデフォルトで利用できないため、ルート直下でも利用できるようにセッションのパスを変更します。
パスの情報はconfigのものを呼び出してきていいと思います。今回は直書きしました。

shop/data/class_extends/sessionfactory_extends/SC_SessionFactory_UseCookie_Ex.php

```
    public function initSession()
    {
        ini_set('session.cache_limiter', 'none');
        // (session.auto_start などで)セッションが開始されていた場合に備えて閉じる。(FIXME: 保存する必要はない。破棄で良い。)
        session_write_close();
        
        // [start]コアのカスタマイズ
        // セッションのパスを "/shop/" から "/" へ変更
        // "/shop/" になっていると WordPress側に ECSESSID が引き継がれないため
        session_set_cookie_params(0, '/', DOMAIN_NAME);
        // [end]コアのカスタマイズ
        
        // セッション開始
        // FIXME EC-CUBE をネストしてインストールした場合を考慮して、一意とすべき
        session_name('ECSESSID');
        session_start();
    }
```    

## WordPress側の設定

EC CUBE側から取得してきたセッションをフッターに表示させてみます。
セッションID「ECSESSID」を元に、EC CUBE の dtb_session テーブルの情報を取得します。

wp-content/themes/テーマ名/footer.php
wp_footer() の下に以下のコードを追加します。

```
<?php
// EC-CUBE の設置しているDBに接続
// 今回はWordPressとEC CUBEの設置しているDBを別にしています
$another_wpdb = new wpdb('DBユーザー', 'DBパスワード', 'DB名', 'ホスト');
// ECSESSID を元に、EC-CUBE の dtb_session テーブルの情報を取得
$result = $another_wpdb->get_row("SELECT * FROM `dtb_session` where sess_id = '" . $_COOKIE['ECSESSID'] . "'");
?>
```

これで ECSESSID を元にカート内のセッション情報は一応取得できているのですが、
DB内のデータがシリアライズされているため、アンシリアライズしてあげたいです。
$result->sess_data をそのままアンシリアライズしたいのですが、"|" で情報が区切られてしまってアンシリアライズがうまくいかないため、
一度 explode() を利用して "|" で区切って配列にし直します。

```
<?php
// EC-CUBE の設置しているDBに接続
// 今回はWordPressとEC CUBEの設置しているDBを別にしています
$another_wpdb = new wpdb('DBユーザー', 'DBパスワード', 'DB名', 'ホスト');
// ECSESSID を元に、EC-CUBE の dtb_session テーブルの情報を取得
$result = $another_wpdb->get_row("SELECT * FROM `dtb_session` where sess_id = '" . $_COOKIE['ECSESSID'] . "'");

$cart = explode('|', $result->sess_data);
?>
```

そして配列に入れ直したものをアンシリアライズします。
今回、$cart[6] に入っている情報にカート情報を持っていたのですが、EC CUBEのバージョンとかでこの辺は差異があるのかもしれません。

```
<?php
// EC-CUBE の設置しているDBに接続
// 今回はWordPressとEC CUBEの設置しているDBを別にしています
$another_wpdb = new wpdb('DBユーザー', 'DBパスワード', 'DB名', 'ホスト');
// ECSESSID を元に、EC-CUBE の dtb_session テーブルの情報を取得
$result = $another_wpdb->get_row("SELECT * FROM `dtb_session` where sess_id = '" . $_COOKIE['ECSESSID'] . "'");

$cart = explode('|', $result->sess_data);
// アンシリアライズしたカート情報を表示してみる
var_dump(unserialize($cart[6]));
?>
```

var_dumpしたカート情報が 「...」 とかで省略されている場合には、php.iniに以下を追加してあげれば表示されるのではないかと思います。

```
xdebug.var_display_max_children = -1
xdebug.var_display_max_data = -1
xdebug.var_display_max_depth = -1
```

以上となります。

EC CUBE下に設置した WordPress のセッションは比較的かんたんに取得できるようですが、逆のパターンは面倒かもしれないです。笑