EC-CUBE4でログイン成功時に直前まで見ていた画面へ戻る方法

EC-CUBE4ではログインする場合、EC-CUBE2とは違いログイン画面を経由させる必要があります。

また、ログイン成功後は必ずサイトのトップページへ戻ってしまいます。

サイトの作りにもよりますが、例えばログイン後は前に見ていた画面を表示して欲しいという要望があった場合、 以下のカスタマイズを行うことで実現可能となります。

EC-CUBE3では以下の記事で対応方法を書いています。

amidaike.hatenablog.com

EC-CUBE4.0.1を対象に説明します。

まず、MypageControllerのコンストラクタに対してRequestStackクラスを宣言します。

  • src/Eccube/Controller/Mypage/MypageController.php
・
・
・
use Symfony\Component\HttpFoundation\RequestStack;
・
・
・

/**
 * @var RequestStack
 */
protected $requestStack;


/**
 * MypageController constructor.
 *
 * @param OrderRepository $orderRepository
 * @param CustomerFavoriteProductRepository $customerFavoriteProductRepository
 * @param CartService $cartService
 * @param BaseInfoRepository $baseInfoRepository
 * @param PurchaseFlow $purchaseFlow
 * @param RequestStack $requestStack
 */
public function __construct(
    OrderRepository $orderRepository,
    CustomerFavoriteProductRepository $customerFavoriteProductRepository,
    CartService $cartService,
    BaseInfoRepository $baseInfoRepository,
    PurchaseFlow $purchaseFlow,
    RequestStack $requestStack
)
{
    $this->orderRepository = $orderRepository;
    $this->customerFavoriteProductRepository = $customerFavoriteProductRepository;
    $this->BaseInfo = $baseInfoRepository->get();
    $this->cartService = $cartService;
    $this->purchaseFlow = $purchaseFlow;
    $this->requestStack = $requestStack;
}

その後、MypageControllerにあるlogin関数を修正します。

/**
 * ログイン画面.
 *
 * @Route("/mypage/login", name="mypage_login")
 * @Template("Mypage/login.twig")
 */
public function login(Request $request, AuthenticationUtils $utils)
{
    if ($this->isGranted('IS_AUTHENTICATED_FULLY')) {
        log_info('認証済のためログイン処理をスキップ');

        return $this->redirectToRoute('mypage');
    }

    /* @var $form \Symfony\Component\Form\FormInterface */
    $builder = $this->formFactory
        ->createNamedBuilder('', CustomerLoginType::class);

    $builder->get('login_memory')->setData((bool)$request->getSession()->get('_security.login_memory'));

    if ($this->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
        $Customer = $this->getUser();
        if ($Customer instanceof Customer) {
            $builder->get('login_email')
                ->setData($Customer->getEmail());
        }
    }

    $event = new EventArgs(
        [
            'builder' => $builder,
        ],
        $request
    );
    $this->eventDispatcher->dispatch(EccubeEvents::FRONT_MYPAGE_MYPAGE_LOGIN_INITIALIZE, $event);

    $form = $builder->getForm();

    // ログイン前の画面へ戻す
    $error = $utils->getLastAuthenticationError();
    if (!$error) {
        // ログインエラーがなければ戻り先をセット
        $referer = $request->headers->get('referer');

        if ($referer) {
            // refererチェック
            $referers = parse_url($referer);
            if ($referers['host'] == $request->getHost()) {
                // ホストが同一であればrefererをセット
                $requestStackUri = $this->requestStack->getMasterRequest()->getUri();

                if ($request->getUri() == $requestStackUri) {
                    // ログイン画面遷移直前のuriをセット
                    $this->setLoginTargetPath($referer);
                } else {
                    // ログイン必須画面のuriをセット
                    $this->setLoginTargetPath($requestStackUri);
                }
            }
        }
    }

    return [
        'error' => $error,
        'form' => $form->createView(),
    ];
}

修正箇所は、

// ログイン前の画面へ戻す
$error = $utils->getLastAuthenticationError();
if (!$error) {
    // ログインエラーがなければ戻り先をセット
    $referer = $request->headers->get('referer');

    if ($referer) {
        // refererチェック
        $referers = parse_url($referer);
        if ($referers['host'] == $request->getHost()) {
            // ホストが同一であればrefererをセット
            $requestStackUri = $this->requestStack->getMasterRequest()->getUri();

            if ($request->getUri() == $requestStackUri) {
                // ログイン画面遷移直前のuriをセット
                $this->setLoginTargetPath($referer);
            } else {
                // ログイン必須画面のuriをセット
                $this->setLoginTargetPath($requestStackUri);
            }
        }
    }
}

return [
    'error' => $error,
    'form' => $form->createView(),
];

になります。ログイン前のrefererを取得し、ログイン成功時に直前まで見ていた画面へ戻すようにしています。ただし、ログインが必要な画面を直接指定された場合、refererを取得するとログインに成功してもrefererで指定した画面に遷移してしまうため、

$this->requestStack->getMasterRequest()->getUri();

と本来指定されているURLを取得し、比較する事でログイン成功後の遷移先を変更するようにセットしています。

refererが取得できない環境は諦めてください。

あと、login.twigも変更する必要があります。以下のソースをlogin.twigのform内に追加します。

  • src/Eccube/Resource/template/default/Mypage/login.twig
<form name="login_mypage" id="login_mypage" method="post" action="{{ url('mypage_login') }}">
{% if app.session.flashBag.has('eccube.login.target.path') %}
    {% for targetPath in app.session.flashBag.peek('eccube.login.target.path') %}
        <input type="hidden" name="_target_path" value="{{ targetPath }}" />
    {% endfor %}
{% endif %}

以上の対応でログイン成功後は、直前まで見ていた画面へ遷移するようになります。

EC-CUBE4でメンテナンスモード有効時でも管理者でログインしていればフロント画面を表示できるようにする方法

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

EC-CUBE4.0.1から新たにメンテナンス機能が利用できるようになりました。

github.com

今回の機能でメンテナンス管理画面が簡単に行えるようになりましたが、フロント画面の確認が出来なくなります。

そこで、管理者でログインしていればフロント画面が表示できるという機能を以下のPull Requestで作成しています。

github.com

変更点はこのPull Requestを見てもらえれば良いのですが、コメントにもあるようにこのprだと、 プラグインのインストール時等にキャッシュを再生成時に失敗する恐れがあるということなので推奨していません。

ただし、キャッシュ再生成等の仕組みを理解している方であれば便利な機能となりますので利用できる方は限られますが参考にしてください。

EC-CUBE4でページ管理から画面作成時にURLからuser_dataを無くす方法

EC-CUBE Advent Calendar 2018 18日目の記事です。

EC-CUBE4にあるページ管理より新しいページを作成した場合、URLには必ずuser_dataが含まれます。

http://example.com/user_data/hoge

というようになります。

user_dataは別にあっても問題はありませんが、今までカスタマイズしてきた要望の一つとしてuser_dataを無くしたいという方もいました。 そこでこのuser_dataをなくす方法を説明します。

EC-CUBE4.0.1を対象にします。

EC-CUBE4からはEC-CUBE3と異なり、URL定義はアノテーションへと変更されました。そのため、対象となるアノテーションを変更します。

まず、UserDataControllerにあるuser_dataを定義しているルーティングの箇所を変更します。

  • src/Eccube/Controller/UserDataController.php
/**
 * @Route("/%eccube_user_data_route%/{route}", name="user_data", requirements={"route": "([0-9a-zA-Z_\-]+\/?)+(?<!\/)"})
 */

から

/**
 * @Route("/{route}", name="user_data", requirements={"route": "^(?=([0-9a-zA-Z_\-]+\/?)+(?<!\/))(?!logout|%eccube_admin_route%/logout|install).*$"})
 */

%eccube_user_data_route% を無くし、ログアウトも除外できるように追加します。

また、管理画面でのURL表記を変更するため、page_edit.twigも修正します。

  • Resource/template/admin/Content/page_edit.twig
・91行目
{{ url('homepage') }}{{ eccube_config.eccube_user_data_route }}/
↓
{{ url('homepage') }}

こちらはuser_dataを表示上からなくしているだけです。 以上の作業を行うことで、ページ管理から新たなページを作成した場合、URLからuser_dataはなくなります。

[追記] もう一箇所修正する箇所がありました。プラグイン利用時にプラグイン側でルーティングの定義をされていた場合、 先にUserDataControllerが参照されてしまい正常に動作しません。

そのため、Kernel.phpにあるconfigureRoutes関数の内容を一部変更します。

  • src/Eccube/Kernel.php
// 有効なプラグインのルーティングをインポートする.
$plugins = $container->getParameter('eccube.plugins.enabled');
$pluginDir = $this->getProjectDir().'/app/Plugin';
foreach ($plugins as $plugin) {
    $dir = $pluginDir.'/'.$plugin.'/Controller';
    if (file_exists($dir)) {
        $builder = $routes->import($dir, '/', 'annotation');
        $builder->setSchemes($scheme);
    }
}

と記述されている箇所を152行目に移動させて以下の様にします。

  • src/Eccube/Kernel.phpのconfigureRoutes変更後
protected function configureRoutes(RouteCollectionBuilder $routes)
{
    $container = $this->getContainer();

    $scheme = ['https', 'http'];
    $forceSSL = $container->getParameter('eccube_force_ssl');
    if ($forceSSL) {
        $scheme = 'https';
    }
    $routes->setSchemes($scheme);

    $confDir = $this->getProjectDir().'/app/config/eccube';
    if (is_dir($confDir.'/routes/')) {
        $builder = $routes->import($confDir.'/routes/*'.self::CONFIG_EXTS, '/', 'glob');
        $builder->setSchemes($scheme);
    }
    if (is_dir($confDir.'/routes/'.$this->environment)) {
        $builder = $routes->import($confDir.'/routes/'.$this->environment.'/**/*'.self::CONFIG_EXTS, '/', 'glob');
        $builder->setSchemes($scheme);
    }

    // 有効なプラグインのルーティングをインポートする.
    $plugins = $container->getParameter('eccube.plugins.enabled');
    $pluginDir = $this->getProjectDir().'/app/Plugin';
    foreach ($plugins as $plugin) {
        $dir = $pluginDir.'/'.$plugin.'/Controller';
        if (file_exists($dir)) {
            $builder = $routes->import($dir, '/', 'annotation');
            $builder->setSchemes($scheme);
        }
    }

    $builder = $routes->import($confDir.'/routes'.self::CONFIG_EXTS, '/', 'glob');
    $builder->setSchemes($scheme);
    $builder = $routes->import($confDir.'/routes_'.$this->environment.self::CONFIG_EXTS, '/', 'glob');
    $builder->setSchemes($scheme);

}

上記のようにルーティングの読み出す順序を変更することで対応可能です。

EC-CUBE3の時は色々とめんどくさいことをしなければいけませんでしたが、EC-CUBE4では簡単にできます。

amidaike.hatenablog.com

上記対応を行っても反映されないなどがあれば、[ECCUBEROOT]/var/cache ディレクトリを削除してからお試しください。

必要な方には必要なカスタマイズだと思いますので、user_dataをURLから無くしてしまいたい!という方は是非ご利用ください。

ローカル環境でEC-CUBEをhttpsで動かす方法

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

前回の記事で、EC-CUBE4のインストール方法について書きました。

EC-CUBE4をMAMPにインストールする方法とインストール画面の設定方法 - AmidaikeBlog

インストール方法は慣れてしまえば簡単なのですが、ローカルでEC-CUBE3、4を動かすにはどのようにすれば良いのか悩みます。

DockerやVagrantMAMP、XAMMPやビルトインウェブサーバー等があり、EC-CUBE4からは

bin/console server:run

というコマンドが用意されています。

それぞれ慣れている方法で実行してもらえれば良いのですが、SSLを利用したいとなった時にはめんどくさい思いが必要になります。

ローカルで開発時にはSSLなんて必要ないと思われますが、決済や他サービスとの連携時にはhttpsでないと連携できないサービスも増えてきていますので、どうしてもhttpsを利用せざるを得ないという状況が発生してしまいます。

その場合、どうすれば良いかとなりますが、つい先日以下のスライドが発表がされました。

speakerdeck.com

Symfonyが新たにSymfony Cloudと呼ばれるサービスを開始し、その一つしてSymfony CLIというものが提供されています。 それを利用することでローカルでもSSL環境が簡単に利用できるようになります。

実際の利用方法は以下となります。

1.SymfoyCLIツールのダウンロード

OSの環境に合わせて下記URLよりダウンロードします。

symfony.com

2.SSLの設定

証明書をインストールするため、下記コマンドを実行します。

symfony server:ca:install

実行後、

ls ~/.symfony/certs/

default.p12 rootCA-key.pem  rootCA.pem

が含まれていれば問題ありません。

3.サーバを起動

環境が整いましたので、以下のコマンドを実行してサーバを起動します。

  • EC-CUBE3の場合

[ECCUBEROOT]/html

まで移動し、

symfony server:start

を実行します。

  • EC-CUBE4の場合

[ECCUBEROOT]

まで移動し、

symfony server:start

を実行します。

4.ブラウザで確認

https://127.0.0.1:8000

にアクセスし、EC-CUBEの画面が表示されれば成功です。

以上がローカルでhttpsを動かす方法となります。

httpsがローカル環境で必要な方は是非お使いください。

EC-CUBE4をMAMPにインストールする方法とインストール画面の設定方法

EC-CUBE Advent Calendar 201 4日目の記事です。

2018年10月11日に待望のEC-CUBE4がリリースされました。

www.ec-cube.net

その後、2018年12月3日に早速EC-CUBE 4.0.1がリリースされました。

www.ec-cube.net

そろそろEC-CUBE4を利用しているという話も聞きますので、 4日目はMacの方限定になりますがMAMPに対してEC-CUBE4をインストールする方法を書きます。 WindowsにもMAMPは用意されていますので、読み替えたら利用できると思います。

MAMPのダウンロード、インストール


MAMP & MAMP PRO

MAMPはダウンロードしてインストールするだけですので説明は省きます。
(記事の時点でMAMP PRO5.2を利用しています。)

MAMPをダウンロード後、インストールすると/ApplicationディレクトリにMAMPディレクトリが作成されます。 MAMP PROというディレクトリも作成されますが今回は普通のMAMPを使います。

php.iniの設定


ダウンロードしたらphp.iniのtimezoneの変更をしてください。
EC-CUBE4ではPHP7.1.3以上が推奨されていますので、 MAMPに入っているPHP 7.2.10を使います。

/Applications/MAMP/bin/php/php7.2.10/conf/php.ini

php.iniにあるtimezoneを

date.timezone = Asia/Tokyo

に変更してください。

EC-CUBE4のダウンロード


本来の目的であるEC-CUBE4をインストールしてみましょう。 本日時点でEC-CUBE4.0.1が最新なのでそれを想定して説明します。

早速下記URLよりVersion 4.0.1をダウンロードしてください。zipでもtarでもどちらでも構いません。

EC-CUBEダウンロード | ECサイト構築・リニューアルは「ECオープンプラットフォームEC-CUBE」

データベースの作成


事前にデータベースが必要なのでMAMPを実行し、phpMyAdminへアクセスします。

http://localhost:8888/phpMyAdmin

「データベース」タブを選択し、 以下のデータベースの内容を作成してください。

データベース名:eccube4
照合順序:utf8_general_ci

今回はEC-CUBE4のインストールのみなのでMAMPのデフォルトで設定されているrootユーザのままインストールします。

EC-CUBE4のインストール


ダウンロードしたEC-CUBE4を先ほどインストールしたMAMPのhtdocsにコピーします。
(解凍したEC-CUBEディレクトリ名をeccube-4.0.1からeccubeに変更します。)

/Applications/MAMP/htdocs/eccube

コピー終了後、ブラウザより

http://localhost:8888/eccube/

へアクセスしてください。

そうするとEC-CUBE4のインストール画面が表示されますので、「次へ進む」ボタンを押します。
「送信を承諾する」はチェックしてもしなくてもどちらでも構いません。 f:id:amidaike:20181204020821p:plain

権限チェックがされますので、問題がなければ「次へ進む」を押します。 f:id:amidaike:20181204020940p:plain

サイトの設定画面が表示されます。こちらはサイト名や管理者用メールアドレス等の情報を入力します。 f:id:amidaike:20181204021010p:plain

それぞれの項目の説明は以下の通りです。

  • あなたの店名 : サイト名
  • メールアドレス : 管理者用のメールアドレス
  • 管理画面ログインID : 管理画面にログインするID
  • 管理画面パスワード : 管理画面にログインするパスワード
  • 管理画面のディレクトリ名 : 管理画面のURL(4.0.1からはadminが利用できなくなりました。)
  • サイトへのアクセスSSL : httpsで接続させるかどうかのチェック
  • 管理画面のIP制限 : 設定すると決まったIPアドレスまたはドメインからしか接続不可能
  • メールの設定 : 4からはSMTPの設定しかできませんので環境に合わせて設定

下記は実際に入力した内容となります。
f:id:amidaike:20181204021026p:plain

入力が完了すると次はデータベースの設定となります。 f:id:amidaike:20181204021128p:plain

今回はmysqlを利用するのでmysqlを選択し、以下のように入力します。 f:id:amidaike:20181204021147p:plain

設定が完了すればデータベースの初期化を行います。 f:id:amidaike:20181204021206p:plain

完了しました画面が表示されれば、インストールは無事に完了です。
f:id:amidaike:20181204021225p:plain

「管理画面を表示」ボタンを押すと管理画面が表示されます。 こちらの画面では、先ほど設定したログインID、パスワードを入力し「ログイン」ボタンを押します。 f:id:amidaike:20181204021251p:plain

無事にログインできれば管理画面のトップページが表示されます。 f:id:amidaike:20181204021317p:plain

また、

http://localhost:8888/eccube/

へアクセスするとトップページが表示されます。 f:id:amidaike:20181204021343p:plain

3系から管理画面、フロント画面ともにイメージが変わっていますが、3系を利用されている方であればすぐに慣れると思います。

以上でEC-CUBE4でのインストール作業は完了です。

なお、EC-CUBE4はMAMPなどを用意しなくてもローカルで動作させる方法はあるのですが、 ドキュメントが見当たらないので見つけたらリンクをはっておきます。

EC-CUBE3で帳票プラグインを利用してフロントでも出力できるようにする方法

EC-CUBE3では帳票出力はプラグインとして提供されています。

管理画面からはプラグインをインストールするだけですぐに利用できますが、フロントからでも帳票を出力したいとう要望が時々あります。 帳票の内容が同じでよければ以下のように対応するだけで実現可能です。

前提として、帳票プラグインを有効にしておく必要がありますのでご注意ください。 対象バージョンはEC-CUBE3.0.15となりますが、他のバージョンでも動作すると思います。

  • src/Eccube/Resource/template/default/Mypage/index.twig の修正

マイページの購入一覧画面で帳票出力リンクを表示したい場合、以下のソースをデザインに合わせて適当な場所へ追加します。

{% if Order.OrderStatus.id == app.config.order_deliv %}
    <p><a href="{{ url('mypage_history_print', {'id': Order.id}) }}" target="print">帳票出力</a></p>
{% endif %}

if文を使っているのは、ステータスが発送済みの時だけ出力できるようにしています。

  • src/Eccube/Resource/template/default/Mypage/history.twig の修正

同様に購入履歴の詳細画面でも帳票出力リンクを用意します。

{% if Order.OrderStatus.id == app.config.order_deliv %}
    <p><a href="{{ url('mypage_history_print', {'id': Order.id}) }}" target="print">帳票出力</a></p>
{% endif %}

記述する内容は上記と同じです。

  • src/Eccube/ControllerProvider/FrontControllerProvider.php へURLを定義

帳票を出力すためのURL定義を行います。記述する場所はどこでも構いません。

$c->match('/mypage/history_print/{id}', '\Eccube\Controller\Mypage\MypageController::historyPrint')->bind('mypage_history_print');

ここの部分はプロジェクトに合わせて変更しても構いません。

  • src/Eccube/Controller/Mypage/MypageController.php へ帳票出力関数を追加

実際に帳票を出力するための関数を記述します。本来であればプラグインのものを再利用できれば良いのですが、色々と考慮する必要があるため新たに作成しています。

<?php
/**
 * 印刷画面を表示
 *
 * @param Application $app
 * @param Request $request
 * @param $id
 * @return \Symfony\Component\HttpFoundation\Response
 * @throws \Doctrine\ORM\OptimisticLockException
 */
public function historyPrint(Application $app, Request $request, $id)
{
    /* @var $softDeleteFilter \Eccube\Doctrine\Filter\SoftDeleteFilter */
    $softDeleteFilter = $app['orm.em']->getFilters()->getFilter('soft_delete');
    $softDeleteFilter->setExcludes(array(
        'Eccube\Entity\ProductClass',
    ));

    $app['orm.em']->getFilters()->enable('incomplete_order_status_hidden');

    /* @var $Order \Eccube\Entity\Order */
    $Order = $app['eccube.repository.order']->findOneBy(array(
        'id' => $id,
        'Customer' => $app->user(),
    ));

    if (!$Order) {
        throw new NotFoundHttpException();
    }

    // 発送済みしか表示させない
    if ($Order->getOrderStatus()->getId() != $app['config']['order_deliv']) {
        throw new AccessDeniedHttpException();
    }

    // 購入情報からPDFを作成する
    $arrData = array(
        'issue_date' => new \DateTime(),
        'ids' => $Order->getId(),
        'title' => 'XXXXX明細書',
        'message1' => 'このたびはお買上げいただきありがとうございます。',
        'message2' => '下記の内容にて納品させていただきます。',
        'message3' => 'ご確認くださいますよう、お願いいたします。',
        'note1' => '',
        'note2' => '',
        'note3' => '',
    );

    $status = $app['orderpdf.service.order_pdf']->makePdf($arrData);

    // 異常終了した場合の処理
    if (!$status) {
        throw new AccessDeniedHttpException();
    }

    // ダウンロードする
    $response = new Response(
        $app['orderpdf.service.order_pdf']->outputPdf(),
        200,
        array('content-type' => 'application/pdf')
    );

    // レスポンスヘッダーにContent-Dispositionをセットし、ファイル名を指定
    $response->headers->set('Content-Disposition', 'inline; filename="'.$app['orderpdf.service.order_pdf']->getPdfFileName().'"');
    // $response->headers->set('Content-Disposition', 'attachment; filename="'.$app['orderpdf.service.order_pdf']->getPdfFileName().'"');

    return $response;
}

上記を記述すると管理画面と同じ帳票が出力できるようになります。

下記の部分ですが、PDFをブラウザ上に表示させるか、ダウンロードさせたいかの違いだけですので、用途に合わせてコメントアウトを変更してください。

$response->headers->set('Content-Disposition', 'inline; filename="'.$app['orderpdf.service.order_pdf']->getPdfFileName().'"');
// $response->headers->set('Content-Disposition', 'attachment; filename="'.$app['orderpdf.service.order_pdf']->getPdfFileName().'"');

以上でフロントからでも帳票出力が可能となりますので、もしフロントでも帳票出力させたいという方は参考にしてください。

EC-CUBE2からEC-CUBE3へバージョンアップ後のmod_rewrite設定について

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

EC-CUBE2系からEC-CUBE3系へバージョンアップされたという方も中にはいるかもしれませんが、EC-CUBE2系から3系は内部構造もそうですがURLも変更されています。

URLが変更になるということは、長い間運用されていた方にとってはSEOとしては致命的なものとなりますし、別サイト等からリンクされていたら全て404になってしまいます。それを防ぐためにmod_rewriteを使ってリダイレクトさせる方法を以下に書きます。

EC-CUBE3.0.15を利用しています。

一番大事なページはやはり商品詳細ページとなります。

ECCUBEROOT/html/.htacccess

に以下を記述してください。

記述する場所は、 <IfModule mod_rewrite.c> に囲まれている箇所となります。

RewriteCond %{REQUEST_URI} products/detail.php
RewriteCond %{QUERY_STRING} ^product_id=([0-9]+)
RewriteRule ^(.*)$ /products/detail/%1? [R=301,L]

詳しい説明は省きますがこちらを記述することで今まで2系で利用されていたURLが3系の商品詳細画面へリダイレクトされます。 また、商品一覧は以下の通りです。

RewriteRule ^products/list.php(.*)$ /products/list$1 [R=301,L]

こちらは比較的簡単ですね。

その他のページについては一つずつ2系のurlを3系に合わせて変更していくだけです。

RewriteRule ^guide/privacy.php /help/privacy [R=301,L]

と一つずつ設定してください。 また独自にページを作成されていた時でも独自ページのURLを記述するだけで対応可能です。

また、URLを変更したいという時でも、

RewriteRule ^brand /guide/brand [R=301,L]

というように変更後のURLへリダイレクト設定を記述するだけです。

以上がmod_rewrite設定になります。広告を出稿していてURL変更が大変だという方などはこちらの設定を記述しておけば特に変更する必要はありません。もし動作しないなどがありましたらコメントをください。