EC-CUBE4でDBへの時間をUTCで保存させないようにする方法

EC-CUBE4から国際化対応が行われており、DBの時間の持たせ方もUTCに対応されています。

データ型の変更 by chihiro-adachi · Pull Request #2185 · EC-CUBE/ec-cube · GitHub

海外なども見据えたサイトであればこのままで問題ありませんが、日本国内のみを対象としており、別システム連携があって直接DBを参照する場合、UTCだと何かと不便な時があるため、UTCで保存させない方法を説明します。

修正方法は非常に簡単で、

  • app/config/eccube/packages/doctrine.yaml
        types:
             datetime: 'Eccube\Doctrine\DBAL\Types\UTCDateTimeType'
             datetimetz: 'Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType'

と表記されている箇所を、

#        types:
#            datetime: 'Eccube\Doctrine\DBAL\Types\UTCDateTimeType'
#            datetimetz: 'Eccube\Doctrine\DBAL\Types\UTCDateTimeTzType'

コメントアウトするだけです。

これを行うことでDBに保存される時間はUTCでは無くなります。

既に本番運用されている方でも、この修正を加えてもDBの時刻がUTCで保存されなくなるだけなので、状況に応じて変更してください。

EC-CUBE4でトップページ等以外はログインを必須にする簡易的な会員制サイトを作る方法

EC-CUBE Advent Calendar 2020 22日目の記事です。

お客さんの要望で会員制のクローズドサイトを作成したいという要望が時々あります。

クローズドサイトといっても完全にクローズドにするのか、トップページと会員登録だけ公開しておくのか、専用IDを別途発行して対応するのかなど色々とあります。

今回は、トップページと会員登録だけを公開した会員制サイトのカスタマイズを紹介します。

ログインが必要となる処理の設定

ログインを必須とするのは、EccubeExtensionクラスに定義を追加するだけで対応可能です。EccubeExtensionクラスは同名のものがあるのでパスを確認するようにしてください。

  • src/Eccube/DependencyInjection/EccubeExtension.php
// SSL強制時は, httpsのみにアクセス制限する
$accessControl = [
  ['path' => '^/%eccube_admin_route%/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/%eccube_admin_route%/', 'roles' => 'ROLE_ADMIN'],
  ['path' => '^/mypage/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/mypage/withdraw_complete', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/mypage/change', 'roles' => 'IS_AUTHENTICATED_FULLY'],
  ['path' => '^/mypage/', 'roles' => 'ROLE_USER'],
];

ここの定義にログイン必須にするための処理を追加します。

// SSL強制時は, httpsのみにアクセス制限する
$accessControl = [
  ['path' => '^/%eccube_admin_route%/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/%eccube_admin_route%/', 'roles' => 'ROLE_ADMIN'],
  ['path' => '^/mypage/login', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/mypage/withdraw_complete', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'],
  ['path' => '^/mypage/change', 'roles' => 'IS_AUTHENTICATED_FULLY'],
  ['path' => '^/mypage/', 'roles' => 'ROLE_USER'],
  // 定義追加
  ['path' => '^/$', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], // トップページはログイン不要
  ['path' => '^/entry', 'roles' => 'IS_AUTHENTICATED_ANONYMOUSLY'], // 会員登録ページはログイン不要
  ['path' => '^/', 'roles' => 'ROLE_USER'], // 全ページログイン必須
];

この処理を追加後、トップページと会員登録ページ以外にアクセスしてログイン画面が表示されれば設定完了です。

特定商取引やプライバシーポリシーなども除外する場合、上記に定義を追加するだけです。

パスの部分はURLを設定する様にしてください。

権限について

EC-CUBEではログインを行うのに権限が存在しており、

  • IS_AUTHENTICATED_ANONYMOUSLY : ログインなしでのアクセス可
  • IS_AUTHENTICATED_FULLY : 会員ログインが必要
  • ROLE_USER : 会員ログインが必要
  • ROLE_ADMIN : 管理者ログインが必要

というようになっています。先ほど設定したIS_AUTHENTICATED_ANONYMOUSLYなどは権限のことを表しています。

ROLE_USERIS_AUTHENTICATED_FULLYの違いですが、ログイン時に自動ログイン(REMEMBERME)にチェックをいれてログインしている時に動作が異なります。

  • ROLE_USER : 自動ログイン済の場合はログイン不要
  • IS_AUTHENTICATED_FULLY : 自動ログインされていてもログインが必要

という動作になります。EC-CUBEでは会員情報変更時のこの権限を利用しています。

以上で簡単に会員サイトを作る仕組みを用意しましたが、このままであれば会員登録されると誰でも見れるサイトになってしまいますので、会員登録された場合、管理画面側で本登録をさせるというカスタマイズを行えばよりクローズドなサイトが出来上がります。

その方法は後日説明します。

EC-CUBE4でCSVファイル出力時に数値項目へ'.00'を付与させない方法

EC-CUBE Advent Calendar 2020 20日目の記事です。

EC-CUBE4で注文CSVダウンロードした時に数値項目(金額など)に.00が付与されてダウンロードされます。

国際化対応されているので小数点以下が付与されても別に気にしなくても良いのですが、偶に外部連携時に不要なことがあります。

今回は付与しない方法の説明です。

CsvExportServiceの変更

今回は一部の箇所を変更するのみです。

  • src/Eccube/Service/CsvExportService.php
/**
 * CSV出力項目と比較し, 合致するデータを返す.
 *
 * @param \Eccube\Entity\Csv $Csv
 * @param $entity
 *
 * @return string|null
 */
public function getData(Csv $Csv, $entity)
{
    // エンティティ名が一致するかどうかチェック.
    $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
    $entityName = ClassUtils::getClass($entity);
    if ($csvEntityName !== $entityName) {
        return null;
    }

    // カラム名がエンティティに存在するかどうかをチェック.
    if (!$entity->offsetExists($Csv->getFieldName())) {
        return null;
    }

    // データを取得.
    $data = $entity->offsetGet($Csv->getFieldName());

    // one to one の場合は, dtb_csv.reference_field_name, 合致する結果を取得する.
    if ($data instanceof \Eccube\Entity\AbstractEntity) {
        if (EntityUtil::isNotEmpty($data)) {
            return $data->offsetGet($Csv->getReferenceFieldName());
        }
    } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
        // one to manyの場合は, カンマ区切りに変換する.
        $array = [];
        foreach ($data as $elem) {
            if (EntityUtil::isNotEmpty($elem)) {
                $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
            }
        }

        return implode($this->eccubeConfig['eccube_csv_export_multidata_separator'], $array);
    } elseif ($data instanceof \DateTime) {
        // datetimeの場合は文字列に変換する.
        return $data->format($this->eccubeConfig['eccube_csv_export_date_format']);
    } else {
        // スカラ値の場合はそのまま.
        return $data;
    }

    return null;
}

となっています、がそれを

/**
 * CSV出力項目と比較し, 合致するデータを返す.
 *
 * @param \Eccube\Entity\Csv $Csv
 * @param $entity
 *
 * @return string|null
 */
public function getData(Csv $Csv, $entity)
{
    // エンティティ名が一致するかどうかチェック.
    $csvEntityName = str_replace('\\\\', '\\', $Csv->getEntityName());
    $entityName = ClassUtils::getClass($entity);
    if ($csvEntityName !== $entityName) {
        return null;
    }

    // カラム名がエンティティに存在するかどうかをチェック.
    if (!$entity->offsetExists($Csv->getFieldName())) {
        return null;
    }

    // データを取得.
    $data = $entity->offsetGet($Csv->getFieldName());

    // one to one の場合は, dtb_csv.reference_field_name, 合致する結果を取得する.
    if ($data instanceof \Eccube\Entity\AbstractEntity) {
        if (EntityUtil::isNotEmpty($data)) {
            return $data->offsetGet($Csv->getReferenceFieldName());
        }
    } elseif ($data instanceof \Doctrine\Common\Collections\Collection) {
        // one to manyの場合は, カンマ区切りに変換する.
        $array = [];
        foreach ($data as $elem) {
            if (EntityUtil::isNotEmpty($elem)) {
                $array[] = $elem->offsetGet($Csv->getReferenceFieldName());
            }
        }

        return implode($this->eccubeConfig['eccube_csv_export_multidata_separator'], $array);
    } elseif ($data instanceof \DateTime) {
        // datetimeの場合は文字列に変換する.
        return $data->format($this->eccubeConfig['eccube_csv_export_date_format']);
    } else {
        // スカラ値の場合はそのまま.
        if (is_string($data)) {
            $data = preg_replace('/\.0+$/', '', $data);
        }
        return $data;
    }

    return null;
}

に変更するだけで対応可能です。

変更箇所は

// スカラ値の場合はそのまま.
if (is_string($data)) {
    $data = preg_replace('/\.0+$/', '', $data);
}

になります。

特に対応する箇所でもないのですが、必要な方はこの記述を追加してください。

EC-CUBE4でポイント履歴を作成する方法

EC-CUBE Advent Calendar 2020 19日目の記事です。

EC-CUBE4ではEC-CUBE3系で無くなったポイント機能が標準で搭載されています。

このポイント機能ですが、ポイント利用とポイント付与しかなくポイント履歴機能は存在しません。

時々お客さんによってはポイント履歴が欲しいと言われることがありますので、今回はポイント履歴を作成します。

今回の変更は複雑な箇所も多いため慣れていない方はお気をつけください。

会員登録時と商品レビュー公開時にも自動ポイント付与及びポイント履歴として表示させるようにカスタマイズも可能ですが今回は省きます。

続きを読む

EC-CUBE4でメールアドレスではなく任意のユーザー名でログインする方法

EC-CUBE Advent Calendar 2020 17日目の記事です。

時々お客さんからの要望で、メールアドレスだけではなく任意のユーザー名でログインさせたいという要望があります。 もっと詰めていくと、会員登録時には「任意のユーザー名」「メールアドレス」「パスワード」だけで登録させたいというものまであります。

その場合、住所はどのタイミングで入力させるのかというと購入画面で入力させるようにすれば良いということですが、購入画面で購入者情報と配送情報を入力させる方法は別の機会に説明します。

今回は会員登録画面を「ユーザー名」「メールアドレス」「パスワード」だけの項目にし、ユーザー名でもログインできる方法を説明します。

続きを読む

EC-CUBE4とWordPressを連携する方法

EC-CUBE Advent Calendar 2020 15日目の記事です。

EC-CUBE4でWordPressの記事を取得する方法を先日書きました。

EC-CUBE4でWordPressの投稿記事を簡単に出力する方法 - AmidaikeBlog

今回は記事を取得するのではなく、WordPressからEC-CUBE4の関数やEC-CUBE4からWordPressの関数を利用できる方法を説明します。

ちなみにEC-CUBE2系はこちらの記事を参考にしてください。

qiita.com

今回は前回とは異なり、EC-CUBE4とWordPressは同階層にインストールするようにします。

というように、同一ドメイン、同階層でEC-CUBE4とWordPressが動作されている事を想定しています。

続きを読む

EC-CUBE4でお問い合わせ内容をDBへ保存する方法

EC-CUBE Advent Calendar 2020 11日目の記事です。

EC-CUBE4のお問い合わせフォームの内容は標準ではメールアドレスしか送られません。

ただ、お客様によっては時々お問い合わせフォームの内容をDBへ保存しておきたいという方がいます。

今回はお問い合わせフォームの内容をDBへ保存する方法を説明します。

続きを読む