Home > CMS・ブログツール

CMS・ブログツール Archive

保護中: 【EC-CUBE】お問い合わせの管理・返信機能追加(その2)

この投稿はパスワードで保護されています。表示するにはパスワードを入力してください:


保護中: 【EC-CUBE】お問い合わせの管理・返信機能追加

この投稿はパスワードで保護されています。表示するにはパスワードを入力してください:


【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その3

さて、最後です。(は~、疲れた;)
最後にテンプレ関係を直していきます。

【ステップ3】

・/data/Smarty/templates/default/admin/customer/index.tpl (L146あたり)

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員状態</td>
                                <td bgcolor=”#ffffff” width=”499″ colspan=”3″><!–{html_checkboxes name=”status” options=$arrStatus separator=”&nbsp;” selected=$arrForm.status}–></td>
                            </tr>
                             <tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員ランク</td>
                                <td bgcolor=”#ffffff” width=”499″ colspan=”3″><!–{html_checkboxes name=”customer_rank” options=$arrCustomer_rank separator=”&nbsp;” selected=$arrForm.customer_rank}–></td>
                            </tr>

・/data/Smarty/templates/default/admin/customer/edit.tpl (L126あたり)

        <table width=”678″ border=”0″ cellspacing=”1″ cellpadding=”8″ summary=” “>

         <tr>
          <td bgcolor=”#f2f1ec” width=”190″>顧客ID<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″><!–{$list_data.customer_id|escape}–></td>
         </tr>
         <tr>
          <td bgcolor=”#f2f1ec” width=”190″>会員状態<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″>
           <span><!–{$arrErr.status}–></span>
           <input type=”radio” name=”status”value=1 id=”no_mem” <!–{if $list_data.status == 1}–> checked=”checked” <!–{/if}–> <!–{if $list_data.status == 2}–>disabled<!–{/if}–>><label for=”no_mem”>仮会員</label>
           <input type=”radio” name=”status”value=2 id=”mem”<!–{if $list_data.status == 2}–> checked=”checked” <!–{/if}–>><label for=”mem”>本会員</label>
          </td>
         </tr>

 <tr>
          <td bgcolor=”#f2f1ec” width=”190″>会員ランク<span> *</span></td>
          <td bgcolor=”#ffffff” width=”527″>
           <span><!–{$arrErr.customer_rank}–></span>
           <!–{html_radios name=”customer_rank” options=$arrCustomer_rank separator=” ” selected=$list_data.customer_rank}–>
          </td>
         </tr>

・/data/Smarty/templates/default/admin/customer/edit_confirm.tpl (L100あたり)

<td width=”190″ bgcolor=”#f2f1ec”>
      会員状態<span> *</span></td>
<td width=”527″ bgcolor=”#ffffff”>
      <!–{if $arrForm.status == 1}–>仮会員<!–{else}–>本会員<!–{/if}–>

</td>
<td width=”190″ bgcolor=”#f2f1ec”>
      会員ランク<span> *</span></td>
<td width=”527″ bgcolor=”#ffffff”>
      <!–{if $arrForm.customer_rank == 5}–>ランク5<!–{elseif $arrForm.customer_rank == 4}–>ランク4<!–{elseif $arrForm.customer_rank == 3}–>ランク3<!–{elseif $arrForm.customer_rank == 2}–>ランク2<!–{else}–>ランク1<!–{/if}–></td>
 

・/data/Smarty/templates/default/admin/mail/index.tpl (L145あたり)

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>会員ランク</td>
                                <td bgcolor=”#ffffff” colspan=”3″>
                                    <!–{if $arrErr.customer_rank}–><span><!–{$arrErr.customer_rank}–></span><!–{/if}–>
                                    <span style=”<!–{$arrErr.customer_rank|sfGetErrorColor}–>”>
                                   <!–{html_checkboxes_ex name=”customer_rank” options=$arrCustomer_rank separator=”&nbsp;” selected=$list_data.customer_rank}–>
                                    </span>
                                </td>
                            </tr>

<tr>
                                <td bgcolor=”#f2f1ec” width=”110″>メールアドレス</td>
                                <td bgcolor=”#ffffff” colspan=”3″>
                                    <!–{if $arrErr.email}–><span><!–{$arrErr.email}–></span><!–{/if}–>
                                    <span style=”<!–{$arrErr.email|sfGetErrorColor}–>”>
                                    <input type=”text” name=”email” maxlength=”<!–{$smarty.const.STEXT_LEN}–>” value=”<!–{$list_data.email|escape}–>” size=”60″    style=”<!–{$arrErr.email|sfGetErrorColor}–>”/>
                                    </span>
                                </td>
                            </tr>

・/data/Smarty/templates/default/admin/mail/query.tpl (L132あたり)

<tr>
           <td bgcolor=”#f0f0f0″ width=”110″>会員ランク</td>
           <td bgcolor=”#ffffff” width=”507″ colspan=”3″><!–{$list_data.customer_rank_disp|default:”(未指定)”}–></td>
          </tr>

<tr>
           <td bgcolor=”#f0f0f0″ width=”110″>メールアドレス</td>
           <td bgcolor=”#ffffff” width=”507″ colspan=”3″><!–{$list_data.email|escape|default:”(未指定)”}–></td>
          </tr>

以上です。
実は、テストは、コミュ版でやっていて、あとから、正式版の対応するソースを探したので、もしかしたら、漏れとかあるかもしれません。多分大丈夫と思いますが、もし、有って気づいたら直します。

【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その2

【ステップ2】

・/data/class/SC_CustomerList.php (L122あたり)

//性別
if (!isset($this->arrSql['sex'])) $this->arrSql['sex'] = “”;
if ( is_array( $this->arrSql['sex'] ) ){
$arrSexVal = $this->setItemTerm( $this->arrSql['sex'] ,”sex” );
foreach ($arrSexVal as $data) {
$this->arrVal[] = $data;
}
}

//会員ランク
if (!isset($this->arrSql['customer_rank'])) $this->arrSql['customer_rank'] = “”;
if ( is_array( $this->arrSql['customer_rank'] ) ){
$arrCustomer_rankVal = $this->setItemTerm( $this->arrSql['customer_rank'] ,”customer_rank” );
foreach ($arrCustomer_rankVal as $data) {
$this->arrVal[] = $data;
}
}

//職業

(L360あたり)

// 検索用SQL
function getList() {
$this->select = “SELECT customer_id,name01,name02,kana01,kana02,sex,email,tel01,tel02,tel03,pref,status,customer_rank FROM dtb_customer “;
return $this->getSql(0);
}

(L395あたり)

function getMailMagazineColumn($is_mobile= false) {
if($is_mobile == true) {
$email_column = “dtb_customer.email_mobile as email”;
} else {
$email_column = “dtb_customer.email”;
}

$column =”dtb_customer.customer_id,
dtb_customer.name01,
dtb_customer.name02,
dtb_customer.kana01,
dtb_customer.kana02,
dtb_customer.sex,
$email_column,
dtb_customer.tel01,
dtb_customer.tel02,
dtb_customer.tel03,
dtb_customer.pref,
dtb_customer.create_date,
dtb_customer.mailmaga_flg,
dtb_customer.customer_rank”;
return $column;
}

・/data/class/helper/SC_Helper_DB.php (L366あたり)

// 価格の登録
$objCustomer = new SC_Customer();
$objQuery = new SC_Query();
if($objCustomer->isLoginSuccess()) {
$customer_rank = $objCustomer->getValue(‘customer_rank’);
$discount_rank = $objQuery->get(“mtb_customer_discount”, “name”, “rank=?”, array($customer_rank));
if ($discount_rank != “”) {
if ($arrData['price02'] != “”) {
$objCartSess->setProductValue($arrCart['id'], ‘price’, $arrData['price02']*$discount_rank);
$objPage->arrProductsClass[$cnt]['uniq_price'] = $arrData['price02']*$discount_rank;
} else {
$objCartSess->setProductValue($arrCart['id'], ‘price’, $arrData['price01']*$discount_rank);
$objPage->arrProductsClass[$cnt]['uniq_price'] = $arrData['price01']*$discount_rank;
}
}else{
if ($arrData['price02'] != “”) {
$objCartSess->setProductValue($arrCart['id'], ‘price’, $arrData['price02']);
$objPage->arrProductsClass[$cnt]['uniq_price'] = $arrData['price02'];
} else {
$objCartSess->setProductValue($arrCart['id'], ‘price’, $arrData['price01']);
$objPage->arrProductsClass[$cnt]['uniq_price'] = $arrData['price01'];
}
}
}

※最後の「}」を忘れないように注意!

・/data/class/helper/SC_Helper_CSV.php(L53あたり)
※これは、もしかしたら不要かも。。。

* デフォルトコンストラクタ.
*/
function SC_Helper_CSV() {
$this->init();

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”,
array(“pref_id”, “pref_name”, “rank”));
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrDISP = $masterData->getMasterData(“mtb_disp”);
$this->arrRECOMMEND = $masterData->getMasterData(“mtb_recommend”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
}

・/data/class/page/admin/customer/SC_Page_Admin_Customer.php (L62あたり)

$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrJob["不明"] = “不明”;
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrPageRows = $masterData->getMasterData(“mtb_page_rows”);
$this->arrMAILMAGATYPE = $masterData->getMasterData(“mtb_mail_magazine_type”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
$this->arrHtmlmail[''] = “すべて”;

(L154あたり)

25 => array(“sql” => “cast(create_date as date) AS create_date”,
“csv” => “create_date”,
“header” => “登録日”),
26 => array(“sql” => “cast(update_date as date) AS update_date”,
“csv” => “update_date”,
“header” => “更新日”),
27 => array(“sql” => “customer_rank”,
“csv” => “customer_rank”,
“header” => “会員ランク”)

);
}

※26 =>・・・の最後に、「,」が入っています。お見逃し無く。
(L188あたり)

// 検索ワードの引き継ぎ
foreach ($_POST as $key => $val) {
switch($key) {
case ‘sex’:
case ‘status’:
case ‘customer_rank’:
$this->arrHidden[$key] = SC_Utils_Ex::sfMergeParamCheckBoxes($val);
if(!is_array($val)) {
$this->arrForm[$key] = split(“-”, $val);
}
break;

・/data/class/page/admin/customer/SC_Page_Admin_Customer_Edit.php(L58あたり)

function init() {
parent::init();
$this->tpl_mainpage = ‘customer/edit.tpl’;
$this->tpl_mainno = ‘customer’;
$this->tpl_subnavi = ‘customer/subnavi.tpl’;
$this->tpl_subno = ‘index’;
$this->tpl_pager = TEMPLATE_DIR . ‘admin/pager.tpl’;
$this->tpl_subtitle = ‘顧客マスタ’;

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”, array(“pref_id”, “pref_name”, “rank”));
$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrReminder = $masterData->getMasterData(“mtb_reminder”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
}

(L109あたり)

array( “column” => “reminder”, “convert” => “n” ),
array( “column” => “reminder_answer”, “convert” => “aKV” ),
array( “column” => “mailmaga_flg”, “convert” => “n” ),
array( “column” => “note”, “convert” => “aKV” ),
array( “column” => “point”, “convert” => “n” ),
array( “column” => “status”, “convert” => “n” ),
array( “column” => “customer_rank”, “convert” => “n” )
);

(L320あたり)

$objErr->doFunc(array(“ご性別”, “sex”) ,array(“SELECT_CHECK”, “NUM_CHECK”));
$objErr->doFunc(array(“ご職業”, “job”) ,array(“NUM_CHECK”));
$objErr->doFunc(array(“会員ランク”, “customer_rank”) ,array(“SELECT_CHECK”, “NUM_CHECK”));
if ($array["password"] != DEFAULT_PASSWORD) {
$objErr->doFunc(array(“パスワード”, ‘password’, PASSWORD_LEN1, PASSWORD_LEN2), array(“EXIST_CHECK”, “ALNUM_CHECK”, “NUM_RANGE_CHECK”));
}

・/data/class/page/admin/mail/SC_Page_Admin_Mail.php (L57あたり)

$masterData = new SC_DB_MasterData_Ex();
$this->arrPref = $masterData->getMasterData(“mtb_pref”, array(“pref_id”, “pref_name”, “rank”));
$this->arrJob = $masterData->getMasterData(“mtb_job”);
$this->arrJob["不明"] = “不明”;
$this->arrSex = $masterData->getMasterData(“mtb_sex”);
$this->arrCustomer_rank = $masterData->getMasterData(“mtb_customer_rank”);
$this->arrMailType = $masterData->getMasterData(“mtb_mail_type”);
$this->arrPageRows = $masterData->getMasterData(“mtb_page_rows”);
// ページナビ用

(L96あたり)

//—- 検索項目
$this->arrSearchColumn = array(
array( “column” => “name”, “convert” => “aKV”),
array( “column” => “pref”, “convert” => “n” ),
array( “column” => “kana”, “convert” => “CKV”),
array( “column” => “sex”, “convert” => “” ),
array( “column” => “customer_rank”, “convert” => “” ),
array( “column” => “tel”, “convert” => “n” ),
array( “column” => “job”, “convert” => “” ),
array( “column” => “email”, “convert” => “a” ),

(L191あたり)

// 配信形式
$list_data['htmlmail_disp'] = $this->arrHtmlmail[$list_data['htmlmail']];

// 性別の変換
if (count($list_data['sex']) > 0) {
foreach($list_data['sex'] as $key => $val){
$list_data['sex'][$key] = $this->arrSex[$val];
$sex_disp .= $list_data['sex'][$key] . ” “;
}
$list_data['sex_disp'] = $sex_disp;
}

// 会員ランクの変換
if (count($list_data['customer_rank']) > 0) {
foreach($list_data['customer_rank'] as $key => $val){
$list_data['customer_rank'][$key] = $this->arrCustomer_rank[$val];
$customer_rank_disp .= $list_data['customer_rank'][$key] . ” “;
}
$list_data['customer_rank_disp'] = $customer_rank_disp;
}

// 職業の変換
if (count($list_data['job']) > 0) {
foreach($list_data['job'] as $key => $val){
$list_data['job'][$key] = $this->arrJob[$val];
$job_disp .= $list_data['job'][$key] . ” “;
}
$list_data['job_disp'] = $job_disp;
}

}

【EC-CUBE】会員ランクを設定し、ランクごとの割引率で販売する その1

年末は、再び年明けのEC-CUBEの案件に備えて、色々いじくりテスト。

大きなところで、3つのカスタムテストをしてみました。

1個目は、EC-CUBEの管理画面で、お問い合わせの履歴管理をし、そこからお問い合わせへの返信を行う、というもの。2個目は、商品一覧のテンプレートをカテゴリーごとに別のデザインでもてるようにカスタム。(そのうち詳細ページでも同様のことをやって見ようと思う。)もうひとつは、表題の通り。会員ランクを作って、会員のランクごとに、割引率を定め、特別価格で販売するというもの。

3つ目、結構面倒だった。なにって、、、仕組みとプログラムルートをたどっていくのが!!!オイッ!(何への怒り!?)

(--;)

何とかできたので、久しぶりすぎるブログのネタとして、とりあえず、晒します。
どっか、間違ってたら、指摘して(ついでに直して;)ください。。。

とりあえず、ぐだっとサンプルの仕様を書きます。

主な仕様ですが、会員ランクをまずは、5段階(ランク1~ランク5)とし、それぞれ、通常販売価格(会員以外の一般の人の価格)の10%割引から50%割引まで、割り引くことにします。
会員ランクの数と割引率は、管理画面のマスタデータ管理から追加や変更ができることにして、ランクごとの割引率は一律、とします。(ということで、別にランクは最初1つでもいいんだけど、サンプルなので、とりあえず5つ作る)

割引率が関係するので、お客さんが勝手にランクを登録したらマズい。
ので、お客さんが会員登録したときは、デフォルトで、会員ランクを1とします。つまり、非会員、ランク1~ランク5までの実質6段階の割引率設定があるわけです。
そして、管理画面で、顧客データを検索して、個別編集で、顧客情報の会員ランクを変更して、ランクを変えます。(例えば、優良顧客のみ、年会費をもらって高割引率で販売するようにしたり、高額購入者のみ顧客管理で検索してランクを変えて高割引率で販売したり、そういうことを想定しています。お金が絡むので、自動でランクを変えるようにはしません。もし、そういうことしたい人は、がんばってください。そして、ソースを晒してください。お願いします;)
あとは、メルマガ送信の顧客検索でも、会員ランクごとにメルマガを送りたいときもあるので、ここにもランクでの顧客情報検索を追加しておくことにします。そして、顧客情報CSVにも出力項目として追加しますね。
と、まあ、表面での仕様はこんな感じです。

さて、ここで、システム的な仕様ですが、ランクの追加・削除や割引率は、当然管理者が時々変えたくなるかも知れない項目なので、マスターデータで管理したいんですが、”mtb_”のテーブルはmtb_constants以外カラムが全部3つなんですね。で、会員ランクでは、id、名前,rank,それから割引率の4つ使いたいんですけど、それを作って、マスターデータ管理で編集しようとすると、さらに色々基幹の部分を触らないと行けなさそうで、システムのアップデートのときに、とっても、とっても、大変そう・・・
だから、ちょっと、気持ちわるいっていうか、マスターデータの編集のときに面倒さが残るけど、今回は、会員ランク用のmtb_customer_rankテーブルと割引率用のmtb_customer_discountテーブルの2つを作りました。でも、別にやり方次第で、1つのテーブル追加だけでも全然対応できると思います。
例えば、ランクは、mtb_のrankを共用利用して、使えばいいわけです。ソノへんは、適宜都合のいいようにしてチョウダイ。

まあ、ちょっとまだ表面的なこと(例えば、カートの中で割引率○○%です、みたいな表記出すとか)が、まだですが、そういうのは、テンプレの修正ですぐできるので、後でやります。

これで、下記のような最終動作となります。
まず、管理画面のマスターデータ管理から、mtb_customer_rankの編集で、会員のランクを必要な数だけ追加・削除します。そして、同じくマスターデータのmtb_customer_discountで、そのランクに応じた割引率を設定します。ランクの数は2つのテーブルであわして置いてくださいね。
ここまでが、管理者側の前準備です。
そして、実際にユーザーが、会員登録をしてくれた後、管理者は、適宜その会員に適用したいランクを管理画面の顧客管理から変更して登録します。
すると、その後、会員の買い物時には、ショッピングカートで、購入した商品に、その割引が適用されます。また、注文の追加や変更で、管理画面の受注管理から、顧客の購入情報を修正したときも、変更した割引率が適用されます。
注意する点は、顧客情報を編集した時点およびユーザーがログインした時点の会員ランクが適用されるということです。ですので、以前の購入情報を修正する場合、その間に会員ランクが変更されていれば、更新は新しいランクで行われますし、会員ランクの変更後は、再ログインしてもらうことで新しいランクでの買い物ができる、ということです。

って、長くなりだしましたので、早速本題の作業を開始します。
一応、ですが、そこそこ複雑な作業も含みます。また、備忘録として、EC-CUBEの基本の動作とか触り方をわかっている方向きに書いてますので、本当に初心者なんです~、という方には向きません。
(私のスキルもそこまで達者ではないので、)エラーなどのサポートも基本的にできません。
それでも良い方のみ覚悟して実装してくださいね。

この作業、結構長いので、途中でエントリー分けます。

【DBに追加するテーブル】
・mtb_customer_rank(3カラム)
・mtb_customer_discount(3カラム)

【触るファイル】
今回は管理機能メインになるので、テストだし、面倒だから、class_exは使いませんでした。
気になる方は、使ってください。
・/data/class/SC_CustomerList.php
・/data/class/helper/SC_Helper_DB.php
・/data/class/helper/SC_Helper_CSV.php
・/data/class/page/admin/customer/SC_Page_Admin_Customer.php
・/data/class/page/admin/customer/SC_Page_Admin_Customer_Edit.php
・/data/Smarty/templates/default/admin/customer/index.tpl
・/data/Smarty/templates/default/admin/customer/edit.tpl
・/data/Smarty/templates/default/admin/customer/edit_confirm.tpl
・/data/Smarty/templates/default/admin/mail/index.tpl
・/data/Smarty/templates/default/admin/mail/query.tpl

【ステップ1】
データベースにテーブルを2つ追加します。

・mtb_customer_rank (※全てnotnull=空白非許可)

id 1 ※smallint(6)/ユニークキーで作成
name ランク1 ※textで作成
rank 1 ※smallint(6)で作成

作成後、セルを追加で4つ作り、ランク1~ランク5までの値を登録する。

・mtb_customer_disucount (※全てnotnull=空白非許可)

id 1 ※smallint(6)/ユニークキーで作成
name 0.9 ※textで作成
rank 1 ※smallint(6)で作成

nameの数字は、1を100%価格として、割引後の掛け率。(0.9=10%offということ)

作成後、セルを追加で4つ作り、0.9/0.8/0.7/0.6/0.5の値を登録する。(それぞれランク1~5の割引掛け率に相当する)

さらに、もともとある、dtb_customerテーブルに、customer_rankというカラムをsmallint(6)で追加します。
ここへ、顧客ごとのランクを書き込んでいく仕様にします。
最後に、CSVの出力用に、dtb_csvテーブルの最後に、customer_rankの行を追加し、ID=85の更新日を参考に、rankがその次の値になるように入力します。

できました?

続きのエントリーはこちらです。↓

http://bton.papalabs.com/?p=1301

http://bton.papalabs.com/?p=1312

マストハブな、WORDPRESSプラグイン300選

http://mashable.com/2007/08/16/wordpress-god300-tools-for-running-your-wordpress-blog/

WORDPRESS GOD_ 300+ Tools for Running Your WordPress Blog

2007年のアーカイブなんで、ちょっと古いけどね;

なんせ人気プラグイン300選ですから。

バージョンアップしてるものもあるし、参考にはなるかも。

スクラッチで、wordpressのプラグインを開発するチュートリアル

http://net.tutsplus.com/tutorials/wordpress/creating-a-custom-wordpress-plugin-from-scratch/

Create a Custom WordPress Plugin From Scratch - Nettuts+

wordpressは今年に入って、国内でもかなり注目度が高い。

テーマやプラグインを色々探すことも多くなってきているが、自分でプラグインを開発するようなこともあるかもしれない。

そこで、スクラッチでWPプラグインを開発するチュートリアルの登場。

問題は、、、英語なんだよね;

でも、わかりやすく書かれているので、がんばって挑戦してみるのもアリ。

WORDPRESSで制作したサイトを多言語対応にする-その1-

マルチリンガルのやり方は、大きく分けて2通り。

日本語で書いたエントリーを自動翻訳させるパターンが、その1つ。

でも、これだと、変な翻訳になってもノーサポート。なので、コーポレートサイトなどには適さない。

もうひとつが、エントリー、それぞれが、多言語で記述できるというもの。

この場合は、翻訳自体は、自分でやらないといけないけど、エントリーごとに、対応言語の有無を選べたり、まとめられる。こっちのほうが、使い勝手があるかな?

とりあえず、実験。

今回は、「qTranslate」というプラグインを使用して、管理画面のエントリーフォームをタブで切り替えて、それぞれの言語のエントリーを記述し、フロントページからは、言語切り替えリンクボタンで、表示を切り替えられるようにしようと思う。

まずは、WORDPRESSのプラグインディレクトリから、qTranslateをダウンロードして(http://wordpress.org/extend/plugins/qtranslate/)FTPでアップロードするか、WPの管理画面のプラグインメニューから検索して、ブログに取り入れる。

qTranslateプラグインを有効にしたら、プラグインの管理メニューから設定を行う。
設定→言語設定が、qTranslateの設定項目になる。先にプラグインを有効化した時点で、WPの管理画面は、一旦英語表記になると思うので、Setting→Language、ですね。

Language Code: ja
Flag: jp.png
Name: Japanese
Locale: ja_JP
Date Format: ※特にフォーマットを指定する場合はここも入力
Time Format:※特にフォーマットを指定する場合はここも入力
Not Available Message: Sorry, this entry is only available in %LANG:, : and %.

Default LanguageをJapaneseにする。
その他利用する言語を「enable」、使用しない言語は、「disable」に。

qTranslateは、そのままだと、日本語のエンコードをeuc-jpに解釈してしまい、設定によっては文字化けなどが起こる可能性があるため、言語ファイルを用意する。

/wp-content/languagesの中の、「ja.mo」ファイルをコピーして、「ja_JP.mo」という名称で保存。(「ja.mo」は、そのまま残す。)

これで、だいたいOK。

今度は、フロントページで、ユーザーが閲覧する表示言語を選択できるようにする。

ヘッダーやindex.phpテンプレートの、言語選択リンクボタンを表示させる適当な場所に下記のコードを埋め込む。ヘッダーのglobal_navi取得コードの前に入れるとよい。

<?php echo qtrans_generateLanguageSelectCode(‘both’); ?>

国旗のマークアイコンを表示させる場合は(‘image’)、テキストで「日本語」「ENGLISH」などと表示させる場合は(‘text’)、両方表示は(‘both’)を使用する。

以上。

もし、文字化けなどのエラーが出たり、詳しい設定で躓いた場合は、下記サイトが参考になりマスヨ。

http://formula1.gimlet301515.com/WordPress/?p=407

http://saqoosha.net/2009/01/06/1672/

そのほか、自動翻訳などを使いたい場合は、こういうプラグインもあり。

http://wordpress.org/extend/plugins/wp-multilingual/

【EC-CUBE】PAYPAL支払いがちゃんとできるかテストする

とりあえず、このエントリーは、↓の続き。

http://bton.papalabs.com/?p=1135

PAYPAL決済を導入するに当たって、EC-CUBEからPAYPALのテストサイトへつないで決済テストを行うやり方。

テストなんだよね。テストなんだけど、いっぱい設定とか準備があって、面倒なんだよね。。。
ここからは、英語ばんばんの海外サイトなので、本当のところ気が狂いそう・・・

とか言ってられないので、がんばりましょう!

1)PAYPALの「Developer Central」内の下記URLへアクセスし、

https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_testing_sandbox

Sign Upメニューから、テスト用の新規アカウントを作成しましょう。

画面は英語だけど、基本的には通常のアカウント登録と同じなので、わからなくなったら、日本語の通常PAYPALサイトを参考にするとイイデスヨ。

アカウントを作ったらサンドボックスにログイン。別に本番アカウントのコピーでもOK。

左メニューで、「Sandbox」-「Home」

ページの真ん中の、Test Accounts 「Create a preconfigured buyer or seller account.」リンクから「Create a Sandbox Test Account」ページへ進む。

  • country:United States
  • Account Type:BuyerとSellerを1つずつ(かそれ以上)作る
  • Login Email:サンドボックスでのテスト用にセラーとバイヤーそれぞれ1つずつ用意する。
  • Password:決める

バイヤーとセラー両方のテストアカウントが必要なので、それぞれを1つずつ、2回登録する。

作成後、左メニューで「Sandbox」-「Test Accounts」をクリックすると、テストアカウントの確認ができるはず。「View Details」でテスト作成されたアカウントの詳細が確認できる。
クレジットカードや銀行の情報も作成されている。

表の中の、「Payment Review」と「Test Mode」をいずれも「Enabled」に変更しておきましょう。

ここまでできたら、いよいよテスト。

ページ右下の「Enter Sandbox Test Site」ボタンをクリックする。

すると、通常のPAYPALのページみたいなテストサイトがあら現れる。この画面に、先ほど作成した、バイヤーアカウントでログインすれば、購入者の動作確認ができるし、セラーアカウントでログインすれば、販売者の動作確認ができる。それぞれ、買い物をしたあと、画面に代金がどのように計上されるのか(できるのかできないのか、)確認すればいい。

さて、ここで、1つ問題が(ということでもないけど;)

前のエントリーでEC-CUBEに設定したのは、本番の設定。

つまり、テストをするためには、一時的に、

/data/class/pages/shopping/LC_Page_Shopping_Confirm.php

で接続するサイトをPAYPALの本番サイトからテストサイトのURLへ変更して、テストアカウントで接続させないといけない。

なので、先に編集した、L148~L155、テスト用には下記のようになります。

// 決済方法により画面切替
if($payment_type != “”) {
$_SESSION["payment_id"] = $arrData['payment_id'];
header(“Location: ” . URL_SHOP_MODULE);
}else{
if($arrData['payment_id'] == ※payment_id) {
// 設定変更行して下さい ↑ if($arrData['payment_id'] == payment_id) {
$paypalURL = “https://www.sandbox.paypal.com/j1/cgi-bin/webscr?cmd=_xclick&” ;
$paypalURL .= “business=” . “テストアカウントに登録したメールアドレス” . “&” ;
// 設定変更行して下さい ↑$paypalURL .= “business=” . “paypalアカウントのメールアドレス” . “&” ;
$paypalURL .= “lc=JP&item_name=” . “商品名” . “&” ;
// 設定変更行して下さい ↑ $paypalURL .= “lc=JP&item_name=” . “商品名” . “&” ;
$paypalURL .= “invoice=” . $order_id . “&” ;
$paypalURL .= “currency_code=JPY&no_shipping=1&no_note=1&” ;
$paypalURL .= “shipping=” . $arrData['deliv_fee'] . “&” ;
$paypalURL .= “amount=” . ($arrData['payment_total']-$arrData['deliv_fee']) . “&” ;
$paypalURL .= “email=” . $arrData["order_email"] . “&” ;
$paypalURL .= “first_name=” . urlencode(mb_convert_encoding($arrData["deliv_name02"], “UTF-8″,CHAR_CODE)) . “&” ;
$paypalURL .= “last_name=” . urlencode(mb_convert_encoding($arrData["deliv_name01"], “UTF-8″, CHAR_CODE)) . “&” ;

// 郵便番号から市町村を得る

$city = $objQuery->get(‘mtb_zip’, ‘city’, ‘zipcode = ?’, $arrData['deliv_zip01'] . $arrData['deliv_zip02']);

$paypalURL .= “address1=” . urlencode(mb_convert_encoding(str_replace($city, “”, $arrData["deliv_addr01"]), “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “address2=” . urlencode(mb_convert_encoding($arrData["deliv_addr02"], “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “city=” . urlencode(mb_convert_encoding($city, “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “zip=” . $arrData["deliv_zip01"] . “-” . $arrData["deliv_zip02"] . “&” ;
$paypalURL .= “night_phone_b=(” . $arrData["order_tel01"] . “)” . $arrData["order_tel02"] . “-” . $arrData["order_tel03"] ;

header(“Location: ” . $paypalURL);
} else {
header(“Location: ” . URL_SHOP_COMPLETE);
}
}

PAYPALのURLをPAYPALのサンドボックスのURLに、PAYPALのアカウントをPAYPALのサンドボックスのアカウントに、それぞれ、一時的に変更しましょう~。

これで、LC_Page_Shopping_Confirm.phpをアップロードしたら、EC-CUBEで、決済方法にPAYPALを選んで、テスト決済してみる。
PAYPAL(サンドボックス)サイトで決済して、その後、自サイトへリダイレクトされて戻ってくる、という一連の動作ができれば、OK。何度か動作確認して問題なければ、本番に切り替える。
以上どす。

【EC-CUBE】PAYPAL支払いAPIを利用する

EC-CUBEにPAYPAL支払いを導入する。

まずは、PAYPALのWEBサイトで、ビジネスアカウント(代金の受取ができるアカウント)を取得する。ビジネスとプレミアアカウントの違いは、機能的にはあまりないが、ビジネスアカウントの場合、クレジットカードなどの決済名に社名(または店舗、団体名など)が使用できるので、ビジネスで決済したいのであれば、ビジネスアカウントを利用するほうが便利。

上級なテクだが、PAYPAL決済では、定期購読やギフト券の発行などにも対応することもできる。とりあえず、まずは、ベーシックにいくけども。。。

アカウントを作成&メール認証したら、「マイアカウント」→「個人設定」→「ウェブ ペイメントの設定」を表示し、

  1. ウェブサイト決済の自動復帰
    自動復帰:オン
    ウェブサイト決済の自動復帰
    復帰URL:

    http://ショップURL/html/shopping/complete.php

  2. 支払いデータ転送:オン
  3. 暗号化ウェブサイト決済
    暗号化されていないウェブサイト決済の受領拒否:オフ
  4. PayPalアカウントオプションサービス:オフ
  5. 連絡先電話番号:オフ
  6. 高速チェックアウトの設定
    giropayおよび銀行振替による支払いのサポート:オフ

と設定する。
次に、
「マイアカウント」→「個人設定」→「言語のエンコード」で、

  1. 「ウェブサイトの言語」   →「日本語」を選択して、下の「詳細オプション」ボタンもクリック。エンコード方式を「UTF-8」にする。
  2. その下の「PayPalから送信されたデータと同じエンコード方式を使用しますか(IPN、ダウンロード可能なログ、メールなど)?」は、「はい」でOK

最後に「マイアカウント」→「個人設定」→「支払い受領設定」でクレジットカード利用名最上の名前をショップまたは会社の名前に設定する。

PAYPAL側での設定は一旦以上。

PAYPALでは、そのほかに、個別にPAYPALで決済したいお客様向けの決済案内メールを、請求書として送付したり(テンプレート設定ができる)PAYPALの決済画面をショップオリジナルの体裁に変更したり、色々と便利な機能が使える。

必須ではないが、あったほうがお客様にとって便利なオプションもあるので、研究してみるのもいいと思う。

さて、肝心のEC-CUBEでの設定を追加していく。

/data/class/pages/shopping/LC_Page_Shopping_Confirm.php

L148~L155(VER.2.4の場合)

// 決済方法により画面切替
if($payment_type != “”) {
$_SESSION["payment_id"] = $arrData['payment_id'];
header(“Location: ” . URL_SHOP_MODULE);
}else{
if($arrData['payment_id'] == ※payment_id) {
// 設定変更行して下さい ↑ if($arrData['payment_id'] == payment_id) {
$paypalURL = “https://www.paypal.com/j1/cgi-bin/webscr?cmd=_xclick&” ;
$paypalURL .= “business=” . “アカウントに登録したメールアドレス” . “&” ;
// 設定変更行して下さい ↑$paypalURL .= “business=” . “paypalアカウントのメールアドレス” . “&” ;
$paypalURL .= “lc=JP&item_name=” . “商品名” . “&” ;
// 設定変更行して下さい ↑ $paypalURL .= “lc=JP&item_name=” . “商品名” . “&” ;
$paypalURL .= “invoice=” . $order_id . “&” ;
$paypalURL .= “currency_code=JPY&no_shipping=1&no_note=1&” ;
$paypalURL .= “shipping=” . $arrData['deliv_fee'] . “&” ;
$paypalURL .= “amount=” . ($arrData['payment_total']-$arrData['deliv_fee']) . “&” ;
$paypalURL .= “email=” . $arrData["order_email"] . “&” ;
$paypalURL .= “first_name=” . urlencode(mb_convert_encoding($arrData["deliv_name02"], “UTF-8″,CHAR_CODE)) . “&” ;
$paypalURL .= “last_name=” . urlencode(mb_convert_encoding($arrData["deliv_name01"], “UTF-8″, CHAR_CODE)) . “&” ;

// 郵便番号から市町村を得る

$city = $objQuery->get(‘mtb_zip’, ‘city’, ‘zipcode = ?’, $arrData['deliv_zip01'] . $arrData['deliv_zip02']);

$paypalURL .= “address1=” . urlencode(mb_convert_encoding(str_replace($city, “”, $arrData["deliv_addr01"]), “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “address2=” . urlencode(mb_convert_encoding($arrData["deliv_addr02"], “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “city=” . urlencode(mb_convert_encoding($city, “UTF-8″, CHAR_CODE)) . “&” ;
$paypalURL .= “zip=” . $arrData["deliv_zip01"] . “-” . $arrData["deliv_zip02"] . “&” ;
$paypalURL .= “night_phone_b=(” . $arrData["order_tel01"] . “)” . $arrData["order_tel02"] . “-” . $arrData["order_tel03"] ;

header(“Location: ” . $paypalURL);
} else {
header(“Location: ” . URL_SHOP_COMPLETE);
}
}

こんな感じで!とりあえず、アップロードして、PAYPALの決済サイトへつながればOK。

さて、PAYPALのサイトでユーザーが決済完了すると、数秒でこちらのサイトへリダイレクトされて画面が戻ってくるようになっている。ここで注意しないといけないことは、リダイレクトされてくるタイミングで、こちらのDBでは、買い物完了という情報がPAYPALから送られてくる、ということだ。もし、短気なユーザーが「お買い物できたわ~。」と思って、ウインドウを閉じてしまったら、こちらには、決済情報はフィードバックされない;

これを解決する方法もあるのだが、ちょっと更にややこしいので、とりあえずは、ウインドウは閉じないでね、お願いね、とでも書いて、ユーザーに注意を促そう。。。

それでは、最後の仕上げ。

ソースができたら、テストを行う。ただし、PAYPALのサイトで実際に決済してしまうと、請求が来てしまう(!あたりまえ;)ので、先にテストをしておきたい。。。

PAYPALには、サンドボックスという便利なテスト機能があるので、それを利用してテストすることにする。

ここからが、英語ベースで結構面倒なんである・・・が、やっぱりお客様のお金を扱うので、ここは慎重に;

でも、長くなるので、エントリーを分けることにしまっす!→ここを見るべし

参考サイト:

http://eccube.seesaa.net/article/87548448.html
http://www.wiz.gr.jp/wordpress/82

http://blog.katsuma.tv/develop/paypal/

https://www.paypalobjects.com/WEBSCR-580-20090611-1/ja_JP/JP/pdf/PP_WebsitePaymentsStandard_Datasheet.pdf

https://cms.paypal.com/us/cgi-bin/?cmd=_render-content&content_ID=developer/howto_testing_sandbox

保護中: 【EC-CUBE】商品詳細ページフォーム項目にカスタム入力欄を追加する

この投稿はパスワードで保護されています。表示するにはパスワードを入力してください:


【EC-CUBE】商品詳細ページにカスタム入力欄を追加する(プレ)

表題の件。要するにぼやきのためのエントリー;

長らく悩まされていた詳細ページのフォームへカスタム入力欄(オーダーサイズを入力させたい!)追加ができるようになる。

もう、何が大変って、ちょいちょいっとで起きると思って始めたら、全然;
セッションの引き回しやら管理画面やら、メールやら、ややこしいったらありゃしない。。。

結局、とにかく自力で!PHPの入門マニュアルやら引き出してきて、変数と処理を追っかけまくる羽目になった。

いじるファイルも多いし、作業も面倒。

忘れないうちに、メモっておこうと思うけど、すでにこの時点で忘れかけ・・・(だって、かなりのトライアル&エラーだったんだもぉ~ん。)

マジでハゲるかと思いましたよ。(^^;

とりあえずあとで書くことにして、触ったファイルだけでもメモしておきたい。(メモなので間違ってるかも。まあ、いいや後で修正すれば。)

  • detail.tpl
  • cart/index.tpl
  • LC_Page_Products_Detail.php
  • SC_CartSession.php
  • SC_Helper_DB.php
  • LC_Page_Shopping_Complete.php
  • LC_Page_Mypage_History.php
  • LC_Page_Admin_Order_Edit.php
  • mypage/history.tpl
  • shopping/confirm.tpl
  • mail_teplate/order_mail.tpl
  • admin/order/edit.tpl
  • admin/order/disp.tpl
  • ctb_order_detail(データベースにカラム追加)

大体これくらい?携帯サイトのほうはまだできていませ~ん。

追記。で、情報も書いてみた。

そして、一般公開にしようかどうかを悩む。。。
ややこしい内容なので、クレーム来てもヤだし。。。

てことで、当面は、個別に知りたい人にだけこっそり教えることにする・・・

使えるWORDPRESSのテーマ&プラグイン

wordpress-designwalker

DESIGN WORKERさんで、よさげな記事を発見したので、あげあげ♪

【EC-CUBE】初回の買い物は、ポイント●倍にする

EC-CUBEを再びカスタマイズ。
初回の買い物は、ポイント●倍にして、その倍率は、管理画面のパラメータ設定で変えられるようにする。

その1)初回の買い物かどうか、判定してポイントを●倍にするロジックを追加。

/data/class/SC_CartSession.phpの function getAllProductsPoint() に下記コードを追加。
L206あたり。

$id = $_SESSION[$this->key][$i]['id'][0];
$point = SC_Utils_Ex::sfPrePoint($price, $point_rate, POINT_RULE, $id);
$total+= ($point * $quantity);
}
$objQuery = new SC_Query();
$objCustomer = new SC_Customer();
//customer_idを検証
$customer_id = $objCustomer->getValue(“customer_id”);
$order_count = $objQuery->count(“dtb_order”, “customer_id= ? and del_flg = 0″, array($customer_id));
if ($order_count == 0) {
$total = $total*FIRST_POINT;
}
return $total;
}

// カートへの商品追加

その2)管理画面のパラメータ設定にポイント倍率設定用の項目を増やす。

DBの、mtb_constantsを開いて、カラムを1行追加。

id FIRST_POINT
name 1
rank 523※一番最後に追加
remarks 初回購入ポイント倍率

nameの値が倍率になる。デフォルトは”1″(倍)。

倍率を変更するときは、管理画面のパラメータ設定で値を変えればOK。

その他の注意点としては、キャンセルがあったときなどにポイントの手動付け替えなど、色々懸念することが出てきてしまうので、

  • ポイント付与のタイミングを発送済みか支払い確認済みなどのステータスになったとき、などに変更しておいたほうがいい
  • 注文のキャンセルがあったときは、自動でポイントが付け替えられるほうがいい

こういうことも一緒にカスタマイズしておいたほうがいい。この辺は、次のバージョンあたりで解消されそうな気もするけども。

WORDPRESSへフォームをつけた。そして携帯対応にした。

WORDPRESSには、色んなプラグインがある。

その中に、お問い合わせフォームを簡単に作ろう♪というプラグインがあるのであるが、

この2つで迷い、悩みぬいた挙句(というか、やりたいことを実現するために朝方までソースをいじいじテストした挙句)今回は、contact form 7を利用することにした。

というのも、問題は、KTAI STYLEとの相性というか、、、携帯での文字化け?

フォームのメール入力欄に携帯電話のメールアドレスを使用すると、送られてくる内容確認メールが文字化けするのだ。色んなハックを調べてやってみたんだけど、PCサイトでは、文字化けなく携帯にメールが送られるようになったものの、どうしても、KTAI STYLEの携帯サイトからは、文字化けが直らない・・・

エンコードの問題があるので対応を迫られるのはしょうがない;
とはいえ、これはキビシイ。

cformでは、全体の文字化けは、回避できたけど、formの値の部分のみ文字化けする。(後ちょっとな気がするんだけど;)

てことで、なんとかうまくいったcontact form 7のハック。

wp-contact-form-7.phpのL991あたり。function validateにktai style用のコードを追加。

function validate($contact_form) {
$fes = $this->form_elements($contact_form['form'], false);
$valid = true;
$reason = array();

foreach ($fes as $fe) {
$type = $fe['type'];
$name = $fe['name'];
$values = $fe['values'];
$raw_values = $fe['raw_values'];

// Ktai ONLY
if (preg_match(‘/^(?:text|textarea)[*]?$/’, $type) && function_exists(‘is_ktai’) && is_ktai())
$_POST[$name] = mb_convert_encoding($_POST[$name], get_bloginfo(‘charset’) ,”SJIS”);

// Before validation corrections
if (preg_match(‘/^(?:text|email|captchar|textarea)[*]?$/’, $type))
$_POST[$name] = (string) $_POST[$name];

よし!

これで、簡単にフォームが追加できる!試しに、確認メールをお問い合わせユーザーに返信する設定で、メアドをdocomoにしてみたけど、OKだった。

は~。理屈は分かってんだけど、情報少ないし、大変だった。

参考サイト:http://d.hatena.ne.jp/v-m-s_memo/20081101/1225548282

この中で、ktai styleの作者のゆりこさんのコメントがあって、

「で、修正コードですが、SJIS 決め打ちはいろいろ問題が出そうです。現在は SJIS ないし SJIS-win しかないですが、将来的には is_ktai() が true でも UTF-8 になる可能性があるため、global $Ktai_Style; してから、$Ktai_Style->get(‘charset’) した値を使ってください。これならば、互換性が保てます。」

ということなので、

// Ktai ONLY
global $Ktai_Style;
$ktai_char = $Ktai_Style->get(‘charset’);
if (preg_match(‘/^(?:text|textarea)[*]?$/’, $type) && function_exists(‘is_ktai’) && is_ktai())
$_POST[$name] = mb_convert_encoding($_POST[$name], get_bloginfo(‘charset’) ,$ktai_char);

とかしたら、いいってことなのかな???

また、明日にでもテストしてみよう。。。 →これで、いけましたね。

追記:(09/08/17)

contact form 7のバージョンが新しくなったので、こちらに記載していたコードとコードの位置がどちらも変更になってしまった。(ketai styleもバージョンアップされている)

いい感じになったけど、ハックには不都合;

てことで、検索していたら、こちらで、モジュールを公開されているのを発見!
http://www.icoro.com/200908093906.html

WORDPRESSで登録メール等が届かない・・・対応

WORDPRESSでは、新しいユーザーが登録された場合やお問い合わせフォームプラグインなどの設置で、自動的にメールが届く仕組みがある。

・・・はずなのだが、このメールが一向に届かない。

原因は、inetd。

およそのサーバにですね、inetd(※inetd は、FTP、POP3、telnet といったインターネットサービスが使うポート番号を(指定されて)監視する。監視対象のポートにTCPパケットあるいはUDPパケットが届くと、inetd は対応するサーバプログラムを起動し、コネクションを制御させる。by wikipedia)というのが、走っているわけなんですが、このinetdが、メール送信の時に、from情報もしているようで、WORDPRESSのデフォルトのまま設定ではこの監視に引っかかってしまうので、メールを受け取れない。

どういうことかというと。

WORDPRESSは、通知メールの送信に、wordpress@あなたのサイト名のアドレスでメールを送信します。このメールアドレスが、サーバ内に実在していれば、問題がないのだが、実在していないメールアドレスからの送信は、inetdの監視に引っかかってしまう。

て、おいおい。。。

最初からwordpress@domainなんてメアド誰がつくっとるねん;
とかツッコんでしまう。

よって、主な対応方法は、2つかと。。。

  1. 上記、wordpress@domainというメアドを実際に作ってWPの管理アドレスに設定する。
  2. または、このメアドをサーバに実在している実際の運用アドレスに変更する。

ま、たいてい、2ですな。

やり方。

/wp-includes/pluggable.php を開いて、L354あたりの、

$from_email = ‘wordpress@’ . $sitename;

を、(1)

$from_email = ‘あなたのめあど@domain‘;

か(2)

$from_email = ‘あなたのめあど@‘. $sitename;

に変更。

ただし、(2)の方法で変更する場合、wordpressで送信されるメールアドレスは、wwwのサブドメインは削除されることに留意すること。(→つまり、ドメインが、www.domain.comでも@から後ろは、domain.comにしかなりませんよ、でも、sub.domain.comだったら、そのままですよ、ということです。まあ、これは普通メアド作るときにも同じようなルールになるので、問題ないかと思うのですが・・・)

こういうところって結構悩みますね。

ちなみに、メアドチェックは、サーバー内で掛かりますよ。他のサービスで持ってるメアドで運用しようとしている場合は、要注意です。

WORDPRESSで”とか’の記号が全角になってしまう;

wp-includes/formatting.php L60あたり、

$curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl);

をコメントアウト。

//$curl = preg_replace($dynamic_characters, $dynamic_replacements, $curl);

これだけです。

【EC-CUBE】詳細ページに商品への問い合わせボタンを追加する

  1. 商品の詳細ページに、商品についての問い合わせボタンを追加し、問い合わせフォームへ遷移させる。
  2. 問い合わせフォームには、商品詳細ページから飛んできた問い合わせについては、フォームに商品名や品番などを自動入力されるように変更する。

フォーラムを見て、こんなことをやってみました。(ryoさん、ありがとうございます)

まず、/data/Smarty/templates/defaults/detail.tpl 内の、問い合わせボタンを追加したい位置に、問い合わせボタン用のフォームを追加する。(そのとき、注文用のフォームとかぶったり、入れ子にならないように注意!)

<form method=”post” action=”<!–{$smarty.const.SITE_URL}–>contact/”>
<input type=”hidden” name=”products_name” value=”<!–{$arrProduct.name|escape}–>” />
<input type=”submit” name=”" value=”この商品について問い合わせる” />
</form>

※ SSLに飛ばすなら赤字を「$smarty.const.SSL_URL」に変更。

つぎに、/data/Smarty/templates/contact/index.tpl のL67あたり、お問い合わせ内容を記入してもらうtextareaに下記コードを追加。

<tr>
<th>お問い合わせ内容<span class=”attention”>※</span><br />
<span class=”mini”>(全角<!–{$smarty.const.MLTEXT_LEN}–>字以下)</span></th>
<td><span class=”attention”><!–{$arrErr.contents}–></span>
<textarea name=”contents” class=”area380″ cols=”60″ rows=”20″ style=”<!–{$arrErr.contents|sfGetErrorColor}–>”><!–{if $smarty.post.products_name != ” }–><!–{$smarty.post.products_name|escape}–>に関するお問い合わせ

<!–{/if}–>
<!–{$contents|escape}–></textarea></td>
</tr>

<!–{if $smarty.post.products_name != ” }–><!–{/if}–>
を記載することによって、「(商品名)に関するお問い合わせ」という部分が、商品ページからの遷移の場合のみ追加されることになる。(=通常のお問い合わせの場合入らない)

【EC-CUBE】最近チェックした商品の履歴を○○件表示させる

商品の詳細ページと一覧ページで最近チェックした商品の履歴を表示させる。

  1. 履歴はクッキーで(1ヶ月)保持する
  2. 最新の閲覧商品を(4件)表示させ、重複する閲覧履歴は表示しない
  3. 表示テンプレートはブロックで生成し、一覧ページにも詳細ページにも共通して使えるようにする

その1)表示用ブロックを作成する。

管理画面から新規ブロックを作成し、下記コードを保存。
(下記はオススメ商品ブロックに倣った2列表示のテンプレートコード。商品名、価格、説明適宜修正する。)

<!–▼閲覧履歴ここから–>
<!–{if $arrItemHistory}–>
<div id=”whoboughtarea” class=”clearFix”>
<h2><img src=”<!–{$TPL_DIR}–>img/products/title_history.jpg” width=”580″ height=”30″ alt=”閲覧履歴” /></h2>
<div class=”whoboughtblock”>
<!–{section name=cnt loop=$arrItemHistory}–>
<!–{if ($smarty.section.cnt.index % 2) == 0}–>
<!–{if $arrItemHistory[cnt].product_id}–>
<!– 左列 –>
<div class=”whoboughtleft”>
<!–{if $arrItemHistory[cnt].main_list_image != “”}–>
<!–{assign var=image_path value=”`$arrItemHistory[cnt].main_list_image`”}–>
<!–{else}–>
<!–{assign var=image_path value=”`$smarty.const.NO_IMAGE_DIR`”}–>
<!–{/if}–>
<a href=”<!–{$smarty.const.DETAIL_P_HTML}–><!–{$arrItemHistory[cnt].product_id}–>”>
<img src=”<!–{$smarty.const.SITE_URL}–>resize_image.php?image=<!–{$image_path|sfRmDupSlash}–>&width=65&height=65″ alt=”<!–{$arrItemHistory[cnt].name|escape}–>” />
</a>

<!–{assign var=price02_min value=`$arrItemHistory[cnt].price02_min`}–>
<!–{assign var=price02_max value=`$arrItemHistory[cnt].price02_max`}–>
<h3><a href=”<!–{$smarty.const.DETAIL_P_HTML}–><!–{$arrItemHistory[cnt].product_id}–>”><!–{$arrItemHistory[cnt].name|escape}–></a></h3>

<p>価格<span class=”mini”>(税込)</span>:<span class=”price”>
<!–{if $price02_min == $price02_max}–>
<!–{$price02_min|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>
<!–{else}–>
<!–{$price02_min|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>~<!–{$price02_max|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>
<!–{/if}–>円</span></p>
<p class=”mini”><!–{$arrItemHistory[cnt].main_list_comment|escape|nl2br}–></p>
</div>
<!– /左列 –>
<!–{/if}–>
<!–{/if}–>

<!–{if ($smarty.section.cnt.index % 2) != 0}–>
<!–{* assign var=nextCnt value=$smarty.section.cnt.index+1 *}–>
<!–{if $arrItemHistory[cnt].product_id}–>
<!– 右列 –>
<div class=”whoboughtright”>
<a href=”<!–{$smarty.const.DETAIL_P_HTML}–><!–{$arrItemHistory[cnt].product_id}–>”>
<!–{if $arrItemHistory[cnt].main_list_image != “”}–>
<!–{assign var=image_path value=”`$arrItemHistory[cnt].main_list_image`”}–>
<!–{else}–>
<!–{assign var=image_path value=”`$smarty.const.NO_IMAGE_DIR`”}–>
<!–{/if}–>
<img src=”<!–{$smarty.const.SITE_URL}–>resize_image.php?image=<!–{$image_path|sfRmDupSlash}–>&width=65&height=65″ alt=”<!–{$arrItemHistory[cnt].name|escape}–>” />
</a>
<!–{assign var=price02_min value=`$arrItemHistory[cnt].price02_min`}–>
<!–{assign var=price02_max value=`$arrItemHistory[cnt].price02_max`}–>
<h3><a href=”<!–{$smarty.const.DETAIL_P_HTML}–><!–{$arrItemHistory[cnt].product_id}–>”><!–{$arrItemHistory[cnt].name|escape}–></a></h3>

<p>価格<span class=”mini”>(税込)</span>:<span class=”price”>

<!–{if $price02_min == $price02_max}–>
<!–{$price02_min|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>
<!–{else}–>
<!–{$price02_min|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>~<!–{$price02_max|sfPreTax:$arrSiteInfo.tax:$arrSiteInfo.tax_rule|number_format}–>
<!–{/if}–>円</span></p>
<p class=”mini”><!–{$arrItemHistory[cnt].main_list_comment|escape|nl2br}–></p>
</div>
<!– /右列 –>
<!–{/if}–>
<!–{/if}–>
<!–{/section}–>
</div>
</div>
<!–{/if}–>

その2)詳細ページ用のphpに、コードを2箇所追加する。

/data/class/paes/products/LC_Page_Products_Detail.php

L100あたり、

// レイアウトデザインを取得
$helper = new SC_Helper_PageLayout_Ex();
$helper->sfGetPageLayout($this, false, “products/detail.php”);

// パラメータ管理クラス
$this->objFormParam = new SC_FormParam();
// パラメータ情報の初期化
$this->lfInitParam();
// POST値の取得
$this->objFormParam->setParam($_POST);

// ファイル管理クラス
$this->objUpFile = new SC_UploadFile(IMAGE_TEMP_DIR, IMAGE_SAVE_DIR);
// ファイル情報の初期化
$this->lfInitFile();

// 商品閲覧履歴取得
$this->Get_ItemHistory();

// 管理ページからの確認の場合は、非公開の商品も表示する。
if(isset($_GET['admin']) && $_GET['admin'] == ‘on’) {
SC_Utils_Ex::sfIsSuccess(new SC_Session());
$status = true;
$where = “del_flg = 0″;
} else {
$status = false;
$where = “del_flg = 0 AND status = 1″;
}

そして、コードの一番最後のほう、 function lfConvertParam()の後ろにも追加。

function lfConvertParam() {
if (!isset($this->arrForm['quantity']['value'])) $this->arrForm['quantity']['value'] = “”;
$value = $this->arrForm['quantity']['value'];
$this->arrForm['quantity']['value'] = htmlspecialchars($value, ENT_QUOTES, CHAR_CODE);
}
//商品詳細閲覧履歴取得、表示データ取得処理
function Get_ItemHistory() {
$cnt = 0;
// ページを再読み込み後に表示
if (isset($_COOKIE['product'])) {
foreach ($_COOKIE['product'] as $name => $value) {
$objQuery = new SC_Query();
// DBから一覧表示用商品情報取得
$arrRet = $objQuery->select(“*”, “vw_products_allclass AS alldtl”, “product_id =”.$value);
$this->arrItemHistory[$cnt] = $arrRet[0];
$cnt = $cnt+1;
}
}

//クッキーに重複項目がないか判定処理
$duplicateFlg = true;
if (isset($_COOKIE['product'])) {
foreach ($_COOKIE['product'] as $name => $value) {
if($value == $_GET['product_id']){
$duplicateFlg = false;
}
}
}

//重複がない場合クッキーに設定
if($duplicateFlg){
if($cnt < 4){
$cnt = $cnt + 1;
setcookie(“product[".$cnt."]“, $_GET['product_id'],time()+60*60*24*30 );
}else{
$reNum = 1;
foreach ($_COOKIE['product'] as $name => $value) {
if($reNum > 1){
$setNum = $reNum -1;
setcookie(“product[".$setNum."]“, $value, time()+60*60*24*30 );
}
$reNum = $reNum + 1;
}
setcookie(“product[4]“, $_GET['product_id'], time()+60*60*24*30 );
}
}
}
}
?>

その3)一覧ページ用phpにも同様にコードを追加する。

/data/class/paes/products/LC_Page_Products_list.php

L82あたり、

// レイアウトデザインを取得
$helper = new SC_Helper_PageLayout_Ex();
$helper->sfGetPageLayout($this, false, DEF_LAYOUT);

//2008.04.11 商品閲覧履歴取得
$this->Get_ItemHistory();

// 管理ページからの確認の場合は、非公開の商品も表示する。
if(isset($_GET['admin']) && $_GET['admin'] == ‘on’) {
SC_Utils_Ex::sfIsSuccess(new SC_Session());
$status = true;
$where = “del_flg = 0″;
} else {
$status = false;
$where = “del_flg = 0 AND status = 1″;
}

//表示件数の選択
if(isset($_POST['disp_number'])
&& SC_Utils_Ex::sfIsInt($_POST['disp_number'])) {
$this->disp_number = $_POST['disp_number'];
} else {

コードの最後のほう、

function lfconvertParam () {
foreach ($this->arrForm as $key => $value) {
if (preg_match(‘/^quantity[0-9]+/’, $key)) {
$this->arrForm[$key]
= htmlspecialchars($this->arrForm[$key], ENT_QUOTES, CHAR_CODE);
}
}
}
//2008.04.11 商品詳細閲覧履歴取得、表示データ取得処理
function Get_ItemHistory() {
$cnt = 0;
// ページを再読み込み後に表示
if (isset($_COOKIE['product'])) {
foreach ($_COOKIE['product'] as $name => $value) {
$objQuery = new SC_Query();
// DBから一覧表示用商品情報取得
$arrRet = $objQuery->select(“*”, “vw_products_allclass AS alldtl”, “product_id =”.$value);
$this->arrItemHistory[$cnt] = $arrRet[0];
$cnt = $cnt+1;
}
}

//クッキーに重複項目がないか判定処理
$duplicateFlg = true;
foreach ($_COOKIE['product'] as $name => $value) {
if($value == $_GET['product_id']){
$duplicateFlg = false;
}
}

//重複がない場合クッキーに設定
if($duplicateFlg){
if($cnt < 4){
$cnt = $cnt + 1;
setcookie(“product[".$cnt."]“, $_GET['product_id'],time()+60*60*24*30 );
}else{
$reNum = 1;
foreach ($_COOKIE['product'] as $name => $value) {
if($reNum > 1){
$setNum = $reNum -1;
setcookie(“product[".$setNum."]“, $value, time()+60*60*24*30 );
}
$reNum = $reNum + 1;
}
setcookie(“product[4]“, $_GET['product_id'], time()+60*60*24*30 );
}
}
}
}
?>

を追加。

その4)最後に、管理画面から、先に作っていた表示用ブロックを詳細ページまたは一覧ページのレイアウトに追加。

自サイトでアフィリエイトを行うプログラム

アフィリエイトといえば、A8やもしもが有名だけど、少しの商品・低予算でアフィリエイトを行いたい、アフィリエイトの形態を独自に決めたい、直接リンク元情報を得たいといった場合には、自サイトで独自にアフィリエイトを行いたい場合がある。

ASPは、統括管理ができたり、使い安い反面、費用や用途に制限があったりするが、自社でプログラムをインストールするなら、カスタマイズもできるし、管理情報も自社で持てる。また、長期利用してもコストの心配も要らない。

で、見つけたのがこれ。オンライン・デモもあるので先に試してみることができる。

Affiliate Pro。
※サイトを開くといきなり音が出て、ちょっとイラつくので注意(^^;

海外ソフトだが、管理画面も日本語翻訳されていて、機能も高価なASPに負けないくらい豊富。価格は、$49でお財布に優しいし、購入すれば、自分で運営している色々なサイトに使用できるので、お徳ではないでしょうか。色々見た中では、手頃でよさげ。

affiliatepro

こちらのサイトからなら更に10%OFF

その他のソフトを探すなら、こういうアフィリエイトやコマースソフトの一覧サイトもあります。http://www.topshareware.com/affiliate/downloads/1.htm

J. BTON ‘s Recent Posts mu-plugin for WordPress MU ver.2

[JAPANESE]

Download the code, and FTP-upload the file to /wp-ontent/mu-plugin/. It will work as soon as file uploaded.

**FEATURE**

Parameter explanations
$how_many: how many recent posts are being displayed
$how_long: time frame to choose recent posts from (in days)
$cate: category ID to be selected
$limit: how many posts should be displayed from each category
$titleOnly: true (only title of post is displayed) OR false (title of post and name of blog are displayed)
$begin_wrap: customise the start html code to adapt to different themes
$optmask: bitmask for various display options (default: 255)
 DISPLAY OPTIONS BITMASK
 1;  // gravatar
 2;  // date
 4;  // author name
 8;  // comment count
 16; // blog name
 32; // post name
 64; // post excerpt
 128; // excerpt capitalization
$exc_size: size of excerpt in words (default: 30)
$end_wrap: customise the end html code to adapt to different themes

Sample call:
1)You can edit the palameter in this plugin code L76,
   function ahp_recent_posts($how_many=9, $how_long=30, $cate=5, $limit=3, $titleOnly=false, $optmask=255, $exc_size=30, $begin_wrap=’<li class=”pageposts_list”>’, $end_wrap=’</li>’) {
and call the function in your template file like this…
   <ul><?php bton_recent_posts(); ?></ul>
2)If you want to call the parameter in your each code of the template,
change L75 –> delate ‘//’ from this code.
   function ahp_recent_posts($how_many, $how_long, $cate, $limit, $titleOnly, $optmask, $exc_size, $begin_wrap, $end_wrap) {
and coment out L76.
   //function ahp_recent_posts($how_many=9, $how_long=30, $cate=5, $limit=3, $titleOnly=false, $optmask=255, $exc_size=30, $begin_wrap=’<li class=”pageposts_list”>’, $end_wrap=’</li>’) {
So, you can set each parameter in your template
bton_recent_posts(9, 30, 5, 3, true, 255, 30, ‘<li class=”pageposts_list”>’, ‘</li>’); >> total 9 most recent entries over the past 30 days, from cateID 5, 3 entries from each blog, displaying titles only
 write code in template like this…
   <ul><?php bton_recent_posts(9, 30, 5, 3, true, 255, 30, ‘<li class=”pageposts_list”>’, ‘</li>’); ?></ul>
And you can also add style in your css files like this.
li.pageposts_list {list-mark-style:none;}
span.pageposts_cont{font-size:small; color:#333;}
span.pageposts_date {font-size:x-small; color:#ccc;}
span.pageposts_author {font-size:x-small; color:#ccc;}
span.pageposts_comment {font-size:x-small; color:#ccc;}
span.pageposts_blog {font-size:x-small; color:#ccc;}
span.pageposts_title {font-size:small; color:#333;}

->>[DOWNLOAD](bton_recent_posts_2.0.zip:4KB)

WORDPRESS MUで、各ブログの新着エントリーをカテゴリーごとに数件ずつ表示するMUプラグインver.2.0

[ENGLISH ]

速攻で失礼しますが、bton_recent_postsをバージョンアップします。

WORDPRESS MUで、マルチブログの各ブログについて(同じMU・DBで運用しているブログについて)、

  • 各サブブログから、
  • 指定したカテゴリーに属するエントリーで、
  • 公開されており、かつ、
  • エントリーの種類が「投稿=post」
  • エントリー後▲日以内の記事を
  • それぞれ○○件、最大●●件
  • アバター表示、コメント数と投稿者の表示対応(オプションマスクでそれぞれ表示・非表示を設定できる
  • XHTMLバリデート(※これについては特に書いていませんが、VER.1も同じです)

抽出して、表示させるMU-プラグイン。

こちらはver.2となっており、パラメータで色々設定できるのに対して、ver.1では、もう少しシンプルな設定です。完全にまとめてもいいのですが、カスタムフィールドなど他の要素を加えるときにマージできない場合があるかもしれないのと、そんなに複雑なものよりもう少しシンプルなほうがいい、という人もいると思いますので、両方のバージョン系列を分けました。

【概要】

サブブログ内のスパム・削除フラグなどが掛かっていない公開エントリーをメインブログのトップページなどに指定数だけ表示させる。

例えば、各サブブログにそれぞれNEWSカテゴリーがあり、NEWSカテゴリーの投稿を、サブブログごとに3件、3つのブログから合計9件、メインブログのトップページに表示させたい、といったときに使用する。

エントリーの抽出はカテゴリー単位で行うので、ブロック単位で、ニュースから2件ずつ、テーマから2件ずつ、という指定が可能。

bton_recent_posts()内のそれぞれの変数が表示の指定パラメータとなっている。(※ver.1より設定項目が増えていますのでご注意ください。)

bton_recent_posts($how_many, $how_long, $cate, $limit, $titleOnly, $optmask, $exc_size,$begin_wrap, $end_wrap)

  1. $how_many: 全体でいくつのエントリーを表示させるか
  2. $how_long: ▲日以内の投稿
  3. $cate: 抽出するカテゴリーのID
  4. $limit: 各ブログから抽出するそれぞれのエントリーの数
  5. $titleOnly: trueならタイトル、投稿日、出典ブログ名、内容の一部抜粋なども表示する /falseなら、タイトルとエントリーへのリンクのみ表示
  6. $optmask: 各項目の表示・非表示を設定する(デフォルト: 255)
     DISPLAY OPTIONS BITMASK
     1;  // gravatar(アバターアイコン)
     2;  // date(日付)
     4;  // author name(投稿者名)
     8;  // comment count(コメント数)
     16; // blog name (出典ブログ名)
     32; // post name (投稿のタイトル)
     64; // post excerpt(本文からの抽出文)
     128; // excerpt capitalization(英文で、抽出文の最初の数文字を大文字で表示する場合)
  7. $exc_size: size of excerpt in words (デフォルト: 30)
  8. $begin_wrap: リストを挟むHTMLタグ(開始タグ)
  9. $end_wrap: リストを挟むHTMLタグ(終了タグ)

表示の指定は、表示させたいテンプレート内(例えば、page.phpやindex.phpなど)で

<ul><?php bton_recent_posts(); ?></ul>

というように記述する。
それぞれの表示項目に対するオプションは、L76の対応する変数の値を編集する。

もし、このプラグインを使用して、条件の違うエントリー抽出を複数行いたい場合は、L75の「//」を削除してアクティブにし、L76行頭に「//」を追加して行をコメントアウトする。
そして、パラメータの指定は、<ul><?php bton_recent_posts(ここに順番に記述); ?></ul>内で指定すると良い。パターンを変えていくつも表示させられる。(例えば、トップページの左ナビでは、カテゴリーID5のニュースばかりを各ブログから3件ずつ表示させ、右のサイドバーには、カテゴリーID2のテーマのエントリーを1件ずつ表示させる、ということも可能。)共通のパラメータは、L75からL76にコピーして残せば、それについては、都度設定しなくとも良くなる。※パラメータ値の記述順番を間違わないように注意してください。

複数のカテゴリーを表示するときの参考コード例として、下記のようにカテゴリーIDを変えて、コードを呼び出せば、別のブロック位置であってもそれぞれエントリーが表示されるので、ポータル的な表示が可能。プラグインのカスタマイズで、色々とバリエーションが作れる。

プラグインのソース内では、
function bton_recent_posts($how_many, $how_long, $cate, $limit, $titleOnly=false, $optmask=255, $exc_size=30, $begin_wrap=’<li class=”pageposts_list”>’, $end_wrap=’</li>’) {

「タイトル以外の項目も表示、表示オプションの指定、抽出本文は30字、リストタグでまとめる」はプラグイン内で共通設定する。
<ul><?php bton_recent_posts(8, 30, 5, 2); ?></ul>//全部で8件、30日以内のエントリーをカテゴリー5から2件ずつ表示。
<ul><?php bton_recent_posts(4, 30, 1, 1); ?></ul>>//全部で4件、30日以内のエントリーをカテゴリー1から1件ずつ表示。
この2つを個別にテンプレートファイルに記述。

【使い方】
ソースをダウンロード・解凍し、FTPで、/wp_content/mu-plugin/ディレクトリにアップロード。(※mu-pluginディレクトリのプラグインは、管理画面のプラグインメニューで使用設定をしなくても、アップロードするだけで反映される。原則としてver.1と一緒には使えません。)

->>[ソースのダウンロード](bton_recent_posts_2.0.zip:4KB)

動作確認は一応していますが、ノーサポートです。もしものトラブル責任も負いません。ご自身のリスクの範囲内で自己責任で使用してください。

【EC-CUBE】MySQL使用の場合のページ表示スピードを改善する。

EC-CUBEのmySQL用のSQLクエリーは、どうも表示速度にとっても問題を及ぼすようだ。。。

基本、PSQLメインの仕様だから、とか言われるのだけど、実際には、DBはMSQLしかないサーバーも多いし、色々運用のことも考えると、やっぱりMSQLでもそれなりのパフォーマンスはして欲しい・・・と思っているのは私だけではないはず。(^^;
いいシステムなのに、ところどころオシイんですよね。でも、最近ちょっと活発になってきてよくなってくる予感。

先日来フォーラムで、MSQLのパフォーマンスについて色々見ていたところ、あるスレッドで、

/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php の商品データ呼び出しクエリーを変更すれば、パフォーマンスに劇的に変化がある、という話を目にし、早速やってみる。結果、PSQLのDBを使用した場合とほとんど遜色ないくらい速くなった!

要は簡単で、コミュニティ版で提供されているファイルに、SC_DB_DBFactory_MYSQL.phpを置き換えて、dtb_productsなどのDBテーブルをカスタマイズして携帯用のコメントなどを追加している場合は、そのカラムについてのSQLの値を追加すればいいだけ。(これは、カスタマイズしている場合だけね。)
ソース中のクエリーの中で、データベースにカスタマイズしてカラムを追加してある場合、dtb_productsに「comment7」を追加しているのであれば、comment6の行の下に同じ記述ルールでに、comment7を取得する記述を1行追加してあげるだけでいい。例えば、comment7の追加が必要な場所は、mein_comment(商品の詳細説明)が呼び出されている箇所(現在のソースなら下記2箇所)と同じところになるので、ソース内を検索してみるべし。

以下は、コミュニティ版で提供されているSC_DB_DBFactory_MYSQL.phpのソース(2/20現在)。多分、EC-CUBEのダウンロードサイトから最新の物を持ってきたほうがいいと思うし、そのうち正式版でも同じように改善されると思うけど、一応コピペしておく。

// {{{ requires
require_once(CLASS_PATH . “db/SC_DB_DBFactory.php”);

/**
* MySQL 固有の処理をするクラス.
*
* このクラスを直接インスタンス化しないこと.
* 必ず SC_DB_DBFactory クラスを経由してインスタンス化する.
* また, SC_DB_DBFactory クラスの関数を必ずオーバーライドしている必要がある.
*
* @package DB
* @author LOCKON CO.,LTD.
* @version $Id:SC_DB_DBFactory_MYSQL.php 15267 2007-08-09 12:31:52Z nanasess $
*/
class SC_DB_DBFactory_MYSQL extends SC_DB_DBFactory {

/**
* DBのバージョンを取得する.
*
* @param string $dsn データソース名
* @return string データベースのバージョン
*/
function sfGetDBVersion($dsn = “”) {
$objQuery = new SC_Query($this->getDSN($dsn), true, true);
list($db_type) = split(“:”, $dsn);
$val = $objQuery->getOne(“select version()”);
return “MySQL ” . $val;
}

/**
* MySQL 用の SQL 文に変更する.
*
* @access private
* @param string $sql SQL 文
* @return string MySQL 用に置換した SQL 文
*/
function sfChangeMySQL($sql){
// 改行、タブを1スペースに変換
$sql = preg_replace(“/[\r\n\t]/”,” “,$sql);
// view表をインラインビューに変換する
$sql = $this->sfChangeView($sql);
// ILIKE検索をLIKE検索に変換する
$sql = $this->sfChangeILIKE($sql);
// RANDOM()をRAND()に変換する
$sql = $this->sfChangeRANDOM($sql);
// TRUNCをTRUNCATEに変換する
$sql = $this->sfChangeTrunc($sql);
return $sql;
}

/**
* 文字コード情報を取得する
*
* @return array 文字コード情報
*/
function getCharSet() {
$objQuery = new SC_Query();
$arrRet = $objQuery->getAll(“SHOW VARIABLES LIKE ‘char%’”);
return $arrRet;
}

/**
* テーブルの存在チェックを行う SQL 文を返す.
*
* @return string テーブルの存在チェックを行う SQL 文
*/
function getTableExistsSql() {
return “SHOW TABLE STATUS LIKE ?”;
}

/**
* インデックスの検索結果を配列で返す.
*
* @param string $index_name インデックス名
* @param string $table_name テーブル名
* @return array インデックスの検索結果の配列
*/
function getTableIndex($index_name, $table_name = “”) {
$objQuery = new SC_Query(“”, true, true);
return $objQuery->getAll(“SHOW INDEX FROM ” . $table_name . ” WHERE Key_name = ?”,
array($index_name));
}

/**
* インデックスを作成する.
*
* @param string $index_name インデックス名
* @param string $table_name テーブル名
* @param string $col_name カラム名
* @param integer $length 作成するインデックスのバイト長
* @return void
*/
function createTableIndex($index_name, $table_name, $col_name, $length = 0) {
$objQuery = new SC_Query($dsn, true, true);
$objQuery->query(“CREATE INDEX ? ON ? (?(?))”, array($index_name, $table_name, $col_name, $length));
}

/**
* テーブルのカラム一覧を取得する.
*
* @param string $table_name テーブル名
* @return array テーブルのカラム一覧の配列
*/
function sfGetColumnList($table_name) {
$objQuery = new SC_Query();
$sql = “SHOW COLUMNS FROM ” . $table_name;
$arrColList = $objQuery->getAll($sql);
$arrColList = SC_Utils_Ex::sfswaparray($arrColList);
return $arrColList["Field"];
}

/**
* テーブルを検索する.
*
* 引数に部分一致するテーブル名を配列で返す.
*
* @param string $expression 検索文字列
* @return array テーブル名の配列
*/
function findTableNames($expression = “”) {
$objQuery = new SC_Query();
$sql = “SHOW TABLES LIKE ?”;
$arrColList = $objQuery->getAll($sql, array(“%” . $expression . “%”));
$arrColList = SC_Utils_Ex::sfswaparray($arrColList, false);
return $arrColList[0];
}

/**
* View の WHERE 句を置換する.
*
* @param string $target 置換対象の文字列
* @param string $where 置換する文字列
* @param array $arrval WHERE 句の要素の配列
* @param string $option SQL 文の追加文字列
* @return string 置換後の SQL 文
*/
function sfViewWhere($target, $where = “”, $arrval = array(), $option = “”){

$arrWhere = split(“[?]“, $where);
$where_tmp = ” WHERE ” . $arrWhere[0];
for($i = 1; $i < count($arrWhere); $i++){
$where_tmp .= SC_Utils_Ex::sfQuoteSmart($arrval[$i - 1]) . $arrWhere[$i];
}
$arrWhere = $this->getWhereConverter();
$arrWhere[$target] = $where_tmp . ” ” . $option;
return $arrWhere[$target];
}

/**
* View をインラインビューに変換する.
*
* @access private
* @param string $sql SQL 文
* @return string インラインビューに変換した SQL 文
*/
function sfChangeView($sql){

$arrViewTmp = $this->viewToSubQuery();

// viewのwhereを変換
foreach($arrViewTmp as $key => $val){
$arrViewTmp[$key] = strtr($arrViewTmp[$key], $this->getWhereConverter());
}

// viewを変換
$changesql = strtr($sql, $arrViewTmp);

return $changesql;
}

/**
* ILIKE句 を LIKE句へ変換する.
*
* @access private
* @param string $sql SQL文
* @return string 変換後の SQL 文
*/
function sfChangeILIKE($sql){
$changesql = eregi_replace(“(ILIKE )”, “LIKE “, $sql);
return $changesql;
}

/**
* RANDOM() を RAND() に変換する.
*
* @access private
* @param string $sql SQL文
* @return string 変換後の SQL 文
*/
function sfChangeRANDOM($sql){
$changesql = eregi_replace(“( RANDOM)”, ” RAND”, $sql);
return $changesql;
}

/**
* TRUNC() を TRUNCATE() に変換する.
*
* @access private
* @param string $sql SQL文
* @return string 変換後の SQL 文
*/
function sfChangeTrunc($sql){
$changesql = eregi_replace(“( TRUNC)”, ” TRUNCATE”, $sql);
return $changesql;
}

/**
* WHERE 句置換用の配列を返す.
*
* @access private
* @return array WHERE 句置換用の配列
*/
function getWhereConverter() {
return array(
“&&crscls_where&&” => “”,
“&&crsprdcls_where&&” =>”",
“&&noncls_where&&” => “”,
“&&allcls_where&&” => “”,
“&&allclsdtl_where&&” => “”,
“&&prdcls_where&&” => “”,
“&&catcnt_where&&” => “”
);
}

/**
* View をサブクエリに変換するための配列を返す.
*
* @access private
* @return array View をサブクエリに変換するための配列
*/
function viewToSubQuery() {
$sql['vw_products_allclass_detail'] =<<< __EOS__
(
SELECT
dtb_products.product_id,
dtb_products.name,
dtb_products.deliv_fee,
dtb_products.sale_limit,
dtb_products.sale_unlimited,
dtb_products.maker_id,
dtb_products.rank,
dtb_products.status,
dtb_products.product_flag,
dtb_products.point_rate,
dtb_products.comment1,
dtb_products.comment2,
dtb_products.comment3,
dtb_products.comment4,
dtb_products.comment5,
dtb_products.comment6, //例えば、携帯用コメントとして、dtb_productsに「comment7」を追加しているのであれば、この下の行に、「dtb_products.comment7,」と1行追加してあげる。
dtb_products.note,
dtb_products.file1,
dtb_products.file2,
dtb_products.file3,
dtb_products.file4,
dtb_products.file5,
dtb_products.file6,
dtb_products.main_list_comment,
dtb_products.main_list_image,
dtb_products.main_comment,
dtb_products.main_image,
dtb_products.main_large_image,
dtb_products.sub_title1,
dtb_products.sub_comment1,
dtb_products.sub_image1,
dtb_products.sub_large_image1,
dtb_products.sub_title2,
dtb_products.sub_comment2,
dtb_products.sub_image2,
dtb_products.sub_large_image2,
dtb_products.sub_title3,
dtb_products.sub_comment3,
dtb_products.sub_image3,
dtb_products.sub_large_image3,
dtb_products.sub_title4,
dtb_products.sub_comment4,
dtb_products.sub_image4,
dtb_products.sub_large_image4,
dtb_products.sub_title5,
dtb_products.sub_comment5,
dtb_products.sub_image5,
dtb_products.sub_large_image5,
dtb_products.sub_title6,
dtb_products.sub_comment6,
dtb_products.sub_image6,
dtb_products.sub_large_image6,
dtb_products.del_flg,
dtb_products.creator_id,
dtb_products.create_date,
dtb_products.update_date,
dtb_products.deliv_date_id,
T4.product_code_min,
T4.product_code_max,
T4.price01_min,
T4.price01_max,
T4.price02_min,
T4.price02_max,
T4.stock_min,
T4.stock_max,
T4.stock_unlimited_min,
T4.stock_unlimited_max,
T4.class_count
FROM
dtb_products
LEFT JOIN
(
SELECT
product_id,
MIN(product_code) AS product_code_min,
MAX(product_code) AS product_code_max,
MIN(price01) AS price01_min,
MAX(price01) AS price01_max,
MIN(price02) AS price02_min,
MAX(price02) AS price02_max,
MIN(stock) AS stock_min,
MAX(stock) AS stock_max,
MIN(stock_unlimited) AS stock_unlimited_min,
MAX(stock_unlimited) AS stock_unlimited_max,
COUNT(*) as class_count
FROM dtb_products_class
GROUP BY product_id
) AS T4
ON dtb_products.product_id = T4.product_id
)
__EOS__;

return array(
“vw_cross_class” => ‘
(SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2
FROM dtb_classcategory AS T1, dtb_classcategory AS T2 ) ‘,

“vw_cross_products_class” =>’
(SELECT T1.class_id1, T1.class_id2, T1.classcategory_id1, T1.classcategory_id2, T2.product_id,
T1.name1, T1.name2, T2.product_code, T2.stock, T2.price01, T2.price02, T1.rank1, T1.rank2
FROM (SELECT T1.class_id AS class_id1, T2.class_id AS class_id2, T1.classcategory_id AS classcategory_id1, T2.classcategory_id AS classcategory_id2, T1.name AS name1, T2.name AS name2, T1.rank AS rank1, T2.rank AS rank2
FROM dtb_classcategory AS T1, dtb_classcategory AS T2 ) AS T1 LEFT JOIN dtb_products_class AS T2
ON T1.classcategory_id1 = T2.classcategory_id1 AND T1.classcategory_id2 = T2.classcategory_id2) ‘,

“vw_products_nonclass” => ‘
(SELECT
T1.product_id,
T1.name,
T1.deliv_fee,
T1.sale_limit,
T1.sale_unlimited,
T1.category_id,
T1.rank,
T1.status,
T1.product_flag,
T1.point_rate,
T1.comment1,
T1.comment2,
T1.comment3,
T1.comment4,
T1.comment5,
T1.comment6, //例えば、携帯用コメントとして、dtb_productsに「comment7」を追加しているのであれば、この下の行に、「T1.comment7,」と1行追加してあげる。
T1.file1,
T1.file2,
T1.file3,
T1.file4,
T1.file5,
T1.file6,
T1.main_list_comment,
T1.main_list_image,
T1.main_comment,
T1.main_image,
T1.main_large_image,
T1.sub_title1,
T1.sub_comment1,
T1.sub_image1,
T1.sub_large_image1,
T1.sub_title2,
T1.sub_comment2,
T1.sub_image2,
T1.sub_large_image2,
T1.sub_title3,
T1.sub_comment3,
T1.sub_image3,
T1.sub_large_image3,
T1.sub_title4,
T1.sub_comment4,
T1.sub_image4,
T1.sub_large_image4,
T1.sub_title5,
T1.sub_comment5,
T1.sub_image5,
T1.sub_large_image5,
T1.sub_title6,
T1.sub_comment6,
T1.sub_image6,
T1.sub_large_image6,
T1.del_flg,
T1.creator_id,
T1.create_date,
T1.update_date,
T1.deliv_date_id,
T2.product_id_sub,
T2.product_code,
T2.price01,
T2.price02,
T2.stock,
T2.stock_unlimited,
T2.classcategory_id1,
T2.classcategory_id2
FROM (SELECT * FROM dtb_products &&noncls_where&&) AS T1 LEFT JOIN
(SELECT
product_id AS product_id_sub,
product_code,
price01,
price02,
stock,
stock_unlimited,
classcategory_id1,
classcategory_id2
FROM dtb_products_class WHERE classcategory_id1 = 0 AND classcategory_id2 = 0)
AS T2
ON T1.product_id = T2.product_id_sub) ‘,

“vw_products_allclass” => ”
(
SELECT
alldtl.*,
dtb_category.rank AS category_rank,
T2.category_id,
T2.rank AS product_rank
FROM
{$sql['vw_products_allclass_detail']} AS alldtl
LEFT JOIN
dtb_product_categories AS T2
ON alldtl.product_id = T2.product_id
LEFT JOIN
dtb_category
ON T2.category_id = dtb_category.category_id
) “,

“vw_products_allclass_detail” => $sql['vw_products_allclass_detail'],

“vw_product_class” => ‘
(SELECT * FROM
(SELECT T3.product_class_id, T3.product_id AS product_id_sub, classcategory_id1, classcategory_id2,
T3.rank AS rank1, T4.rank AS rank2, T3.class_id AS class_id1, T4.class_id AS class_id2,
stock, price01, price02, stock_unlimited, product_code
FROM ( SELECT
T1.product_class_id,
T1.product_id,
classcategory_id1,
classcategory_id2,
T2.rank,
T2.class_id,
stock,
price01,
price02,
stock_unlimited,
product_code
FROM (dtb_products_class AS T1 LEFT JOIN dtb_classcategory AS T2
ON T1.classcategory_id1 = T2.classcategory_id))
AS T3 LEFT JOIN dtb_classcategory AS T4
ON T3.classcategory_id2 = T4.classcategory_id) AS T5 LEFT JOIN dtb_products AS T6
ON product_id_sub = T6.product_id) ‘,

“vw_category_count” => ‘
(SELECT T1.category_id, T1.category_name, T1.parent_category_id, T1.level, T1.rank, T2.product_count
FROM dtb_category AS T1 LEFT JOIN dtb_category_total_count AS T2
ON T1.category_id = T2.category_id) ‘
);
}
}
?>

ポスグレへ移行テストもしているけど、正直これだけ改善されたら、まあ、いいかな、MSQLのままでも、と思い始めている。。。

J. BTON ‘s Recent Posts mu-plugin for WordPress MU

[JAPANESE]

Download the code , and FTP-upload the file to /wp-ontent/mu-plugin/. It will work as soon as file uploaded.

**FEATURE**

Parameter explanations
$how_many: how many recent posts are being displayed
$how_long: time frame to choose recent posts from (in days)
$cate: category ID to be selected
$limit: how many posts should be displayed from each category
$titleOnly: true (only title of post is displayed) OR false (title of post and name of blog are displayed)
$begin_wrap: customise the start html code to adapt to different themes
$end_wrap: customise the end html code to adapt to different themes

Sample call: bton_recent_posts(8, 30, 5, 2, true, ‘<li>’, ‘</li>’); >> total 8 most recent entries over the past 30 days, from cateID 5, 2 entries from each blog, displaying titles only
write code in template
ex. <ul><?php bton_recent_posts(8, 30, 5, 2, true, ‘<li class=”pageposts_list”>’, ‘</li>’); ?></ul>
And you can also add style in your css files like this.
li.pageposts_list {list-mark-style:none;}
span.pageposts_cont{font-size:small; color:#333;}
span.pageposts_date {font-size:x-small; color:#ccc;}
span.pageposts_blog {font-size:x-small; color:#ccc;}

->>[DOWNLOAD](bton_recent_posts_1.0.zip:2KB)

/*Now, Ver.2 available*/

WORDPRESS MUで、各ブログの新着エントリーをカテゴリーごとに数件ずつ表示するMUプラグイン

[ENGLISH ]

WORDPRESS MUで、マルチブログの各ブログについて(同じMU・DBで運用しているブログについて)、

  • 各サブブログから、
  • 指定したカテゴリーに属するエントリーで、
  • 公開されており、かつ、
  • エントリーの種類が「投稿=post」
  • エントリー後▲日以内の記事を
  • それぞれ○○件、最大●●件

抽出して、表示させるMU-プラグイン。

【概要】

サブブログ内のスパム・削除フラグなどが掛かっていない公開エントリーをメインブログのトップページなどに指定数だけ表示させる。

例えば、各サブブログにそれぞれNEWSカテゴリーがあり、NEWSカテゴリーの投稿を、サブブログごとに3件、3つのブログから合計9件、メインブログのトップページに表示させたい、といったときに使用する。

エントリーの抽出はカテゴリー単位で行うので、ブロック単位で、ニュースから2件ずつ、テーマから2件ずつ、という指定が可能。

bton_recent_posts()内のそれぞれの変数が表示の指定パラメータとなっている。

 bton_recent_posts($how_many, $how_long, $cate, $limit, $titleOnly, $begin_wrap, $end_wrap)

  1. $how_many: 全体でいくつのエントリーを表示させるか
  2. $how_long: ▲日以内の投稿
  3. $cate: 抽出するカテゴリーのID
  4. $limit: 各ブログから抽出するそれぞれのエントリーの数
  5. $titleOnly: trueならタイトル、投稿日、出典ブログ名、内容の一部抜粋なども表示する /falseなら、タイトルとエントリーへのリンクのみ表示
  6. $begin_wrap: リストを挟むHTMLタグ(開始タグ)
  7. $end_wrap: リストを挟むHTMLタグ(終了タグ)

表示の指定は、表示させたいテンプレート内(例えば、page.phpやindex.phpなど)で

<ul><?php bton_recent_posts(8, 30, 5, 2, true, ‘<li class=”pageposts_list”>’, ‘</li>’); ?></ul>

というように記述する。
この例では、全体で8つのエントリー、30日以内に投稿されたもので、かつ、カテゴリーIDが5のものを各2件、エントリーのタイトルだけではなく、出典ブログ名や投稿日時、投稿内容の一部も、<ul><li class=”pageposts_list”></li></ul>タグを使って表示させる、という指定になる。

複数のカテゴリーを表示するときは、下記のようにカテゴリーIDを変えて、コードを呼び出せば、別のブロック位置であってもそれぞれエントリーが表示されるので、ポータル的な表示が可能。プラグインのカスタマイズで、色々とバリエーションが作れる。

<ul><?php bton_recent_posts(8, 30, 5, 2, true, ‘<li class=”pageposts_list”>’, ‘</li>’); ?></ul>
<ul><?php bton_recent_posts(8, 30, 1, 2, true, ‘<li class=”pageposts_list”>’, ‘</li>’); ?></ul>

【使い方ソースをダウンロードし、FTPで、/wp_content/mu-plugin/ディレクトリにアップロード。(※mu-pluginディレクトリのプラグインは、管理画面のプラグインメニューで使用設定をしなくても、アップロードするだけで反映される。)

->>[ソースのダウンロード](bton_recent_posts_1.0.zip:2KB)

動作確認は一応していますが、ノーサポートです。もしものトラブル責任も負いません。ご自身のリスクの範囲内で自己責任で使用してください。

*コメント*0221/次のバージョンとの整合性を取るため、ちょっと変数名を変更しました。動作には変更ありません。 VER.2をリリースしました。

【EC-CUBE】mySQLからpostgreSQLへデータを移行する

パフォーマンス改善のため、MSQLからPSQLへのデータベース移行を行う。

移行前 mySQL5.2 → 移行後 postgreSQL8.3 (※VER末番省略)

PSQLの8.3系はパフォーマンスは高いが、SQLの互換性で色々と問題が出ることもあるようなので、モジュールなどを使用する際は、注意すること。

移行の場合は、一旦同サーバ内に、サブドメインなどで別環境を作っておき、そちらでインストールしてから本番環境からDBを切り替えるのが望ましい。

【主な手順】

  1. MYSQLのDBからphpMyAdminで、テーブルごとにCSVデータを書き出す。
  2. (一応同じサーバ内に別環境をつくり)EC-CUBEをポスグレ使用でインストール
  3. postgreSQL(以下PSQL)のDBのテーブル内のデータを全て空にする
  4. テーブルごとに、先にMSQLからダウンロードしていたCSVデータをインポート(※携帯用コメントとショップ用コメントをカスタマイズ追加しているから、この際にPSQLのdtb_productsにcomment7とshop_comment1カラムを追加しておく。)
  5. ビューを調整。
    ・vw_product_class
    ・vw_products_allclass
    ・vw_products_allclass_detail
    ・vw_products_nonclass
    の4つのビューに、カスタマイズで追加していたコメントカラム(comment7、shop_comment1 ※ショップカラムは、表示しないので、allクラスとnonclassだけでもいいと思う)をそれぞれ追加して生成しなおす

では詳しい手順。

その1)

phpMyAdminを開いて、左のサイドメニューからテーブルを1つずつ選択。エクスポートタブメニューをクリックし、テーブルのエクスポートメニューで、

エクスポート:「MS Excel用CSVデータ」を選択。
Excelオプション:NULL/最初の1行目にフィールド名を追加する(チェックあり)/Excelの種類(Windows)
ファイルで保存する(チェック)/圧縮(無し)/エンコード(non)

で実行。

supremecenter53com-_-papalabs_ageha-_-dtb_baseinfo-_-phpmyadmin-264-pl2

エンコードの変換有無は、移行する相互のDBの文字エンコードが違う場合、文字化けを防ぐために必要になるが、書き出してからテキストエディタなどで様子を見ながら変換したほうが安心な気がする。

結構な数のテーブルがあるので、PSQLにインポートの際間違えないようにファイル名に気をつけながら順番に繰り返す。

その2)

PSQLでEC-CUBEインストール用のDBを1つ新規作成し、そこへ、もとのMSQLのEC-CUBEと同じバージョンのEC-CUBEを新規インストールする。

以前のものと同じバージョンにあわせるのは、DBの安全移行のため。ただしテーブル構造などが変わっていないバージョンの変更であれば、新しいEC-CUBEでもかまわない。
別のEC-CUBEを使う場合は、DBだけでなくファイルの移行も色々気をつけないといけないから正直めんどい;問題も切り分けにくいのでまずは、普通に移行だけ先に行ったほうがいいように思う。

その3)

ここで一旦新しいEC-CUBEの基本動作確認がベター。サーバー側の別のエラーが出ている場合は修正しておくこと。問題なければ、PSQLの各テーブルのデータを一旦空にする。

phpPgAdminを開いて、左メニューから、スキーマ→public→テーブルをクリックして選択。テーブルの一覧がでるので、ページ下の方の「複数行の操作」メニューから、「すべて選択する」—>「空にする」を選んで実行ボタンをクリック。

phppgadminjpg

これで、テーブルの構造は残るが値は消えた。

その4)

dtb_baseinfoを選択して、上のタブメニューからインポートを選ぶ。

フォーマット(CSV)/NULL文字を許可する(\n、NULL、殻の文字列・項目いずれもチェック)

先に保存していたMSQLのdtb_baseinfoのテーブルデータを選択して、インポートボタンをクリック。

phppgadmin2

これを、最後のテーブルまで繰り返す。

途中、インポートエラーが出たらメッセージごとにもとのMSQLデータを調整するなどして対応。カスタマイズして増やしたカラムに相当するカラムがPSQLのテーブルにない場合、エラーが出るので、その際は、該当するカラムをテーブルに追加しておく。(例えば、dtb_productsにcomment7などを追加していた場合、PSQLのインポートでは、そのデータを入れるカラムがまだないので、作成しておかなくてはいけない)

その5)

PSQLでは、VIEWを使用してテーブルから値をあらかじめ集めておくことで表示のパフォーマンスをあげている。上記のようなカスタマイズでMSQLのテーブルにカラムを追加していた場合、そのデータをEC-CUBEで表示させるならVIEWにも修正が必要になる。(例えば、上記携帯用コメントcomment7は、携帯ページで表示させるので、それを読み込んでいるVIEWにもデータがなくては表示エラーになってしまう)

今回は、

  • comment7→携帯ページ用商品説明文を入力&表示させている。
  • shop_comment1→商品登録時に店舗のメモを格納しているが管理画面で確認するだけでフロント表示はしない。

となっているので、

  • vw_product_class
  • vw_products_allclass
  • vw_products_allclass_detail
  • vw_products_nonclass

の4つのビューに、それぞれ、値を足すことにする。

  1. vw_product_classは、マスター的な役割をするので、comment7もshop_comment1も追加する
  2. vw_products_allclassには、comment7のみ追加
  3. vw_products_allclass_detailには、comment7のみ追加
  4. vw_products_nonclassには、もshop_comment1も追加する

vw_product_class以外には、shop_comment1のほうが必要かどうかちょいとあいまい。なくてもいいかもしれない。(エラー出たときに足せば・・・)

やり方。まず、左メニューからビューのvw_product_classを選択。ページの右上のほうのタブメニューからエクスポートを選択。
まずは、ダウンロードを選んで、一旦ローカルにビューのデータをバックアップ。その後、表示でファイルを開く。L18あたりの、 t6.comment6,の後ろに、 t6.comment7, t6.shop_comment1,を追加。ソースをドラッグ&コピー。

phpPgAdminへ戻り、左メニューのビューをクリックして、表示されるビューの一覧から、vw_product_classのテーブル内の「破棄」ボタンをクリックして、vw_product_classビューを破棄する。

画面の上の方のデータベース名をクリック。
SQLタブをクリックして、フォームに修正後のソースを貼り付けて、実行。

phppgadmin4

これで、新しく修正されたビューが再生成される。「レコードが見つかりません」と表示されればok。残りのビューについても同様に繰り返す。

vw_products_allclassは、t5.comment3, の後ろにt5.comment7,を、t1.comment3, の後ろにt1.comment7,を追加。

vw_products_allclass_detailは、t3.comment3, の後ろにt3.comment7, を追加。

vw_products_nonclassは、 t1.comment6, の後ろに、t1.comment7, t1.shop_comment1, を追加。

これでOK。

最終テストを行うので、新EC-CUBEから、/data/install.php以外のデータを一旦削除し、本番のec-cubeのソースをこちらにコピーしてくる。これで、本番の環境と同じプログラムでDBのみPSQLの環境ができたことになるので、データが正しく移行されて、表示されているか確認。

動作に問題がなければ、本番のec-cubeの/data/install.phpの接続データベースをPSQLの情報に変更して、接続するDBを入れ替えて完了。テストの段階で、PHPソースなどを変更しなければならなかった場合は、本番にもそれらを反映する。

以上。書いてると長いけど、慎重にやれば、作業自体はそれほど難しくはない。

保護中: WORDPRESS MUで特定ブログのカテゴリーの新着記事●件を表示させるコード

この投稿はパスワードで保護されています。表示するにはパスワードを入力してください:


WORDPRESSのプラグイン:カスタムフィールドを使いやすくカスタマイズ!

カスタムフィールドのGUIを使いやすくして、CMSとしても利用しやすくするプラグイン2つ。

ベースのプラグインは同じものから、独自仕様を追加したりカスタマイズしたものなので、使いやすい♪

それぞれに特徴があって、1つは、共通フィールドと投稿ごとのフィールドをそれぞれ追加できる「Custom Field GUI Utility」(※2009/2/6時点の最新アップデート版はこちら。)

もうひとつは、ページテンプレートとして、いくつかのパターンを追加でき、また、プラグインの設定画面から一括設定が可能な「Custom Field Template」。こちらは、よりCMSっぽいことができる。

【WORDPRESS】MTのマルチブログっぽいことをする

WordPress MUは、マルチユーザーマルチブログなんだけども、1つMTと大きく違うのが、MTのMULTIBLOGでできる、子ブログの記事のインポートができないってこと。これができるのとできないのとでは、CMS化して使用するためには、大違い。

そこで、登場するのが、feedwordpress。このプラグインを使うと、自分のブログだけでなく、他のものでもRSSフィードからエントリーデータを取得して自分のブログ内に表示ができる。

って、これ。取り込んだデータは自分のグログで自分の記事として公開できてしまうのよ。。。
自分のブログじゃなくて人のブログから記事を取り込んで自分のブログの中に公開しちゃったら、コンテンツドロボーじゃんか。。。

まあ、とりあえず、ワタシの目的は、自分の子ブログのデータが読み込めればいいので、とりあえず、人様のことはよしとする。

  1. 上のサイトからZIPとかのデータをダウンロード。
  2. 解凍して、wp-contentsのpluginフォルダにアップロード。WPの左ナビゲーション内のプラグインメニューからfeedwordpressを「使用する」リンクをクリック。
  3. そうすると左ナビと(ついでに言うと設定メニューの中にも)ヘッダーの右上にSyndicationというメニューが出てくるので、そこの設定で読み込んだ記事のカテゴリーとか、読み込んだ記事をブログ内のコンテンツに取り込むのか元のサイトへのリンクで処理するのか、記事の投稿者は誰にするのかとか色々初期設定しておく。
  4. あとは、Syndicationのほうのメニューページで、取り込むサイトのURLを入力すればOKなんす。

これだけ。悪いことに使っちゃダメだよ~。自己責任だよ~。

今回やったこと。

  • WORPRESS MUをダウンロードしてきてサブドメインを使ってマルチユーザー・マルチブログのWPサイトを構築。
  • MUは英語ベースなので、こちらから日本語ソースをもらってきて、wp-contents-languageフォルダを作成して日本語ファイルをインストール。(アップロードしてからサイト管理-設定の言語設定をjapaneseに変更。wp-config.phpのWPLANGも変更してdefine (‘WPLANG’, ‘ja’);とする。詳しくは、上記日本語ソース配布サイトに書いてる。今は、ver.2.7作成中となっていたが、そのうちできるでしょ。2.6.2用でも一部英語が残るだけで別に問題なし。)
  • 2つ目のブログを作って、そのブログに、ktai_entryプラグインを入れて投稿設定。
  • その記事を、feedwordpressでメインのブログのニュースカテゴリに読み込む。(ニュースを子ブログで作る想定ね)
  • ついでなんで、携帯電話でも見られるように、ktai_styleも入れてみた。携帯でメール投稿した後、内容確認したくなるときもあるだろうしね。(作者のyurikoさんってすごいなぁ。。。なんでもできちゃうんだなぁ。。。)

これで、WEBサイトのニュース記事を携帯電話からメール更新で更新できて、しかも、その更新は、ニュース専用の投稿者にお願いする、ってことができちゃう。ヤッタ。

応用で、特定のカテゴリー記事だけ別部門で運用して、別々に運用しているカテゴリーのコンテンツをメインサイトにまとめるとか、そういうこともできるよねw(^^)w
別に同じブログ内で、カテゴリーだけ分けて、ニュース記事を抽出してもいいんだけど、そうすると、更新頻度の高いカテゴリーの記事に頻度の低いカテゴリーの記事が埋もれちゃったり、カテゴリーごとに編集権限が違うときとか、公開前に他の人には見せられないカテゴリーの記事があったりとか、そういうときに困ることもあるから、できると便利な一工夫ってことになりますネ。

WORDPRESS MUキター!

とか言ってみる。

実はもともとMT愛好者のワタシ。
昔は、マルチブログとカスタムフィールドを駆使して、CMSッぽいことしてたね。あの頃は、CMSといえば、エンタープライズかブログのそれっぽいのしかなかった。。。
もちろんエンタープライズなんて買えないさ~ってな低予算プロジェクトではMTでがんばってた。

ニュースは、ニュースブログで、商品は商品ブログで作って、メインブログにインクルードして、それぞれのブログで更新権限分けて、みたいなことをして何とかしのいでた。

最近、いろんなCMS、それもブログの何ちゃってCMSと呼んでみた~みたいなのではなくて、ちゃんと承認フローとかロールもついてるようなちゃんとしたやつがオープンソースで出てきたりして、使う機会は無くなってきたけど。。。

久しぶりに、グログツールで、ホラ、アレだ、ちょいと簡単にマルチブログ作ってインクルードしたい、なんてことを考えたら、やっぱWORDPRESS使いたいな~、PHPだしな~、OSCだしな~、MTは独自タグ多いしな~、とか心がぼやき始めたので、とりあえず検索。

MTOS(MTのオープンソース版)使うって手もあるけど、そうすると、商用でクライアントに提案したいときに、結局パッケージ必要になるから、どうせなら、WPで実験しとこうかと。)

WPはシングルブログだから、別のブログをインクルードしてきてもいいとしても、同じサイトに属する複数のブログを分けて管理するのは面倒・・・

WORDPRESS MUならできるかも。マルチブログだし。一部のプラグインとかは、動かないのもあるみたいだけど、B豚の使いたいのはいけそうな感じ。

さて、インストール。

ちょっとWPとちゃうけど、まあいいか。マルチブログをサブドメインで運用するかサブディレクトリで運用するか?サブドメがええわ。どっちでもいいけど、とりあえずテストやし。

んで、あれこれやって、2つ目のブログ作ろうと思って、挫折・・・あれ?これってどこのディレクトリ参照してんの?
てか、表示されんし。

どうも、WPMUをサブドメインで運用するには、ホストのDNSでAレコードにワイルドカード(*.domain.comみたいのん)が指定できないとだめらしい。しかも、うちのサーバーは、コンパネでサブドメインとかDNS設定するやつやし、ROOT権限はないし。

WPの内部で、WPのメインディレクトリへのアクセスをサブドメイン(=複数ブログ)ごとに振り分けている模様。

どうすっぺ~。どうすっぺ~。

う~ん。う~ん。

だめもとで、とりあえず、ホストのコンパネでサブドメインつくる。→サブドメの参照ディレクトリは、メインドメインと同じディレクトリにする。

お?なに?いけたわ。悩みに悩んだワタシの3時間をカエセ。

てことで、あえなく解決。

備忘録やけど、とりあえず、この悶々たる想いをだらだら書きたかったので、普通にブログになってもた。
たまにはいいよね、こういうのも?

あとは、プラグインのテストと、ブログのインクルードテンプレ作ることだね。。。
やれやれ、いつになったらできるやら。。。

【EC-CUBE】注文確認メールで支払い先口座情報を追加する

受注確認メールの支払い先をメール中に挿入する。その時に支払方法ごとに挿入内容を変える。

/data/Smarty/templates/default/mail_templates/order_mail.tplに、支払方法ごとに支払方法を追加する。

<!–{if $arrOrder.payment_method == “銀行振込” }–>
銀行振込み先:○○銀行 ○○支店
       口座番号 普通 ○○○○○
       口座名義 ○○○○

<!–{elseif $arrOrder.payment_method == “郵便振替” }–>
郵便振替え先:記号○○ 番号○○
       口座名義 ○○○○

<!–{else$arrOrder.payment_method == “○○ }–>
支払い先:○○
    
<!–{else}–>
代金引換えにて配送いたします。
商品お受取りの際、配達員に代金をお支払いください。

<!–{/if}–>

【EC-CUBE】PCサイトで追加した新着商品ブロックを携帯サイトでも追加する

以前に、追加した大変便利なブロック機能。「新着商品をブロックで表示する」(http://www.bton.net46.net/?p=493

 これは実装時には基本PCサイトでのみ動作していたのだけど、携帯でも同じように使用したい。

ということで、ちょこっと改変して、携帯でも使うことにする。

そこで、私は、http://www.bton.net46.net/?p=735で商品登録に携帯用のコメントを追加したので、モバイルサイトでは、PC用の普通の説明文ではなく、携帯用の説明文を表示させることにする。(そうすると絵文字も自由に使えるからね!)

さて、新着商品の表示だけど、トップページで、左に小さな写真、右に商品名、携帯用説明文(最初の60字)を表示させて、写真と商品名には詳細ページへのリンクをつける、ということにしたい。

その1)ブロックのPHPを作成する。

以前に作成した、/html/frontparts/bloc/new.phpをコピーして、/html/mobile/frontparts/bloc/new.phpとして保存。

コピーしたファイルを開き、最後から2行目、3行目の、

$objPage->init();
$objPage->process();

$objPage->mobileInit();
$objPage->mobileProcess();

に変更して保存。

その2)ブロック作成。

/data/Smarty/templates/default/mobile/frontparts/bloc/にnew.tplを作成し、下記ソースを参考に表示用のテンプレートブロックを作成する。

<!–{if count($arrFlagProducts) > 0}–>
<div style=”background-color:#3cf; color:#fff; font-size:small; padding:1px; text-align:center;”>新着商品</div>
<div style=”font-size:x-small; background-color:#cff;”>
<!–{section name=cnt loop=$arrFlagProducts step=1 max=6}–>
<!–{if $arrFlagProducts[cnt].main_list_image != “”}–>
<!–{assign var=image_path value=”`$arrFlagProducts[cnt].main_list_image`”}–>
<!–{else}–>
<!–{assign var=image_path value=”`$smarty.const.NO_IMAGE_DIR`”}–>
<!–{/if}–>
<div style=”clear:both;”><a href=”<!–{$smarty.const.MOBILE_DETAIL_P_HTML}–><!–{$arrFlagProducts[cnt].product_id}–>”><img src=”<!–{$smarty.const.SITE_URL}–>resize_image.php?image=<!–{$image_path|sfRmDupSlash}–>&amp;width=60&amp;height=60″ alt=”<!–{$arrFlagProducts[cnt].name|escape}–>” style=”float:left;margin-top:3px; margin-right:3px; margin-bottom:8px; margin-left:3px;” align=”left” border=”0″ /></a>
<span style=”<!–color:#f36;–>”>[emoji:148]&nbsp;<a href=”<!–{$smarty.const.MOBILE_DETAIL_P_HTML}–><!–{$arrFlagProducts[cnt].product_id}–>”><strong><!–{$arrFlagProducts[cnt].name|escape}–></strong></a></span><br /><br />
[emoji:76]<span style=”color:#666;”><!–{if !$arrProduct.comment7}–><!–{$arrFlagProducts[cnt].main_list_comment|mb_strimwidth:0:60:”…”|escape|nl2br}–><!–{else}–><!–{$arrFlagProducts[cnt].comment7|mb_strimwidth:0:60:”…”|escape|nl2br}–><!–{/if}–></span><br clear=”all” /></div>
<!–{/section}–>
</div>

ポイント。

リサイズイメージで、商品画像を60×60pxに変換している。
SECTIONのループで、max=6と指定しているので、新着商品は6個表示される。
imgタグのSTYLE属性で画像を左にfloatさせている。ドコモXHTMLでは、floatの解除は、brタグではできないので、divタグのスタイル属性でstyle=”clear:both;”とするんであるが、古い携帯の場合、これでクリアされないかもしれないので、念のため、保険代わりに<br clear=”all” />も追加しておく。
最後のほうで、携帯用のコメント(comment7)があれば、それを表示し、携帯コメントが登録されていなければ、PC用のコメントを表示する、としている。また、コメントはいずれも全角30字とし、それ以上長いものは、省略させている。
こんなとこ。
変数名が前回保存したPC用のソースで指定したものと一致しているか確認すること。(変数名が違うと表示されない)

その3)データベースから抽出されるデータにcommnet7を追加しておく。

/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php

のL368あたりから(ver.2.3.3の場合)vw_products_allclassというのがあるので、この中の           comment3,の下あたりにcomment7,を1行追加。

ついでなので、その20行ほど下の、

 T0.comment3,の下にも、
 T0.comment7,を1行追加しておいた。

【EC-CUBE】携帯サイトのニュース表示を調整する

モバイルサイトでは、ニュースは、最新1つだけ、しかもタイトルのみしか表示されない。

これだと更新履歴や商品入荷情報などを配信したい場合、ちょいと不都合。

ということで、モバイルサイトのニュースでも、

日付: 「2009.02.01」 というように。
タイトル:「○○が入荷しました!」というように。
本文:「オススメの人気ブランド○○のTシャツ緊急入荷!急げ!」というように。(また、本文は、文字数を頭から20字のみ表示、というように丸めたい場合もあると思うので、それも踏まえて改修。)

こういう表記になるように変更する。

これも基本、PCサイトのソースを持ってきて変更するだけ。

NEWSはPCと同じCLASSのロジックを使用しているので、基本テンプレのファイルを修正するだけでOK。
PCサイトのほうからソースをコピーしてきて、モバイル用に表示のHTMLを変更していく。

ニュースブロックの中身を変更する。

/data/Smarty/templates/default/mobaile/frontparts/bloc/news.tpl

を開く。

ソースを下記を参考に変更する。(※XHTMLで記述している)

<div style=”color:#666; font-size:small;”><strong>NEWS!!</strong></div>
<!–{section name=data loop=$arrNews}–>
<!–{assign var=”date_array” value=”-”|explode:$arrNews[data].news_date_disp}–>
<div style=”color:#666; font-size:x-small;”>[emoji:e54]<!–{$date_array[0]}–>.<!–{$date_array[1]}–>.<!–{$date_array[2]}–></div>
<div style=”color:#666; font-size:x-small;”>
<!–{if $arrNews[data].news_url}–><a href=”<!–{$arrNews[data].news_url}–>”>
<!–{/if}–>
<!–{$arrNews[data].news_title|escape|nl2br}–>
<!–{if $arrNews[data].news_url}–></a></span>
<!–{/if}–><br />
<!–{$arrNews[data].news_comment|mb_strimwidth:0:40:”…”|escape|nl2br}–>
</div>
<!–{/section}–>

小さくポイントになるところを解説。

  1. SECTIONでloopさせている$arrNewsは、ニュースの数だけ繰り返し、という意味なので、例えば最新の3つのニュースを表示するのであれば、$arrNewsではなく、「3」といれる。
  2. <!–{$date_array[0]}–>.<!–{$date_array[1]}–>.<!–{$date_array[2]}–>は、2009.02.01というように日付の区切りを[.]にしているので、/にしたければ、[/]に変更すればよいし、[]、[]、[]としたければ、そのように記述。
  3. mb_strimwidth:0:40:”…”| この部分で、ニュース本文の最初(0文字目)から40字目(半角なので、全角文字の場合は、これで20字ということ)までを表示し、最後に[...]を追加する、ということを言っている。[...]を[続く]としたり、他の記号にすることもできるし、40字ではなく60字などにすることもできる。

 こんなもんかな?

【EC-CUBE】携帯サイトの検索でもカテゴリ一覧検索を使用したい

EC-CUBEでは携帯サイトの商品検索は、PCよりしょぼい・・・(失礼!)

というか、こういう仕様になったのにはそれなりの訳もあるのかもしれない(表示のパフォーマンスや色々あるのかもしれないし、単にこっちはとりあえず実装だったのかもしれない)が、PCサイトでは、商品検索でカテゴリ検索ができる。検索窓でカテゴリの一覧から検索対象のカテゴリを選択することができるのだ。

これが、モバイルのほうでは、いきなり検索したい商品名を入力してちょ、とくる。そして別画面で検索のみ行う仕様である。
初めてのユーザーや特定の商品名、キーワードのイメージがないユーザーには、ちょいと使いにくい仕様である。なので、これをカスタマイズして、PCと同じくカテゴリ検索ができるようにする。

searchimage

こういう感じ。この機能をブロックにして、トップページなどで利用できるようにする。
モバイルサイトでは、ブロックは管理画面から配置するのではなく、該当するテンプレート中に、直接インクルードするので、今回はデータベースと管理画面は触らない。

基本的には、PCサイトのsearchのロジックをMOBILEに移植するだけでOK。

【携帯サイトへカテゴリ検索ブロックの追加】

その1)ブロック用PHP作成。

/html/frontparts/bloc/search_products.php をコピーして、
/html/mobile/frontparts/bloc/search_products.php として保存。

コピーしたファイルを開き、最後から2行目、3行目に、

$objPage->init();
$objPage->process();

というそーすがあるのを、

$objPage->mobileInit();
$objPage->mobileProcess();

と変更する。

その2)ブロック作成。

/data/Smarty/templates/default/mobile/frontparts/bloc/に、SearchProducts.tplという名称でテンプレファイルを作成し、PC用のSearchProducts.tplを参考にしながら、コーディング。

参考までに、上記のようなデザインにするためのコードは下記。(※XHTMLにてコーディングした場合)

<div style=”background-color:#96c; color:#fff; font-size:small; padding:1px; text-align:center;”>[emoji:119]&nbsp;商品検索&nbsp;[emoji:119]</div>
<div style=”font-size:x-small; padding:1px; background-color:#EEE6F7;”>&nbsp;お探しの商品名・型番を入力してください。</div>
<div style=”text-align:center; font-size:x-small;”><br /><form name=”search_form” id=”search_form” method=”get” action=”<!–{$smarty.const.URL_DIR}–>products/list.php”>
カテゴリから選ぶ<br />
<input type=”hidden” name=”mode” value=”search” />
<select name=”category_id”>
<option label=”全ての商品” value=”">全ての商品</option>
<!–{html_options options=$arrCatList selected=$category_id}–>
</select><br />
商品名を入力する<br />
<input type=”text” name=”name2″ maxlength=”50″ value=”<!–{$smarty.get.name|escape}–>” />
<br />
<input type=”submit” name=”search” value=”&nbsp;&nbsp;&nbsp;検索&nbsp;&nbsp;&nbsp;”>
</form>

これで、検索ブロックの基本は完成。

その3)最後に、トップページへ検索ブロックを埋め込む。

/data/Smarty/templates/default/mobile/top.tpl の、検索窓を表示したい箇所に、

<!–{include_php file=`$smarty.const.MOBILE_HTML_PATH`frontparts/bloc/search_products.php}–>

と記述。もちろん他のページでもかまわない。現状のEC-CUBEの構造で、検索ページの中身をカテゴリ検索の形に変更したいのであれば、

/html/mobile/products/search.php と

/data/Smarty/templates/default/mobile/products/search.tpl のソースを上記で出来上がるソースに置き換えればいい。(または、別に上記ソースを作成しておいて、商品検索のリンクのみ、/html/mobile/frontparts/bloc/search_products.phpへのリンクパスに変更すればいい。

他にも色々やった(オススメや新着のランダム表示ブロックに携帯機能を追加したりとかトップエページにカテゴリリストをボーダーデザインで出すようにしたりとか)けど、以外にスムーズに行き過ぎ、小さく色々さわりすぎたもんで、手順を記録できず、整理するのが大変・・・(^^;

次のときに必要だから、思い出して必ず記録する!乙!

【EC-CUBE】携帯サイトをXHTML仕様にする

今はモバイルサイトの仕様過渡期なので、ちょいと注意が必要なんだけども。

というのも、少し前に、モバイルXHTMLの標準化について、なんとなく関係各処でオーソライズされたらしいので。けれど、しばらくは、色々な事情からこのネタも生きることであろう。

モバイルサイトをXHTMLにすると何がいいかというと、ドコモでインラインCSSが使えるようになる。
ドコモなどで、文字に背景をつけたいとかインラインスタイルを書いて色々ちょいと調整したいとか、ただでさえ制限の多い携帯のコーディングで、少しでも自由な表現をするには、やっぱりスタイルシートが使えないと不便。

画像の多様で容量上げて凝ったデザインにするのはECではつらいので、モバゲーみたいに色々デザインされたページを無理なくコードで実現しようとすると、やっぱりCSSが必要なんである。

細かいところは、携帯サイトのコーディングについて詳しいサイトがいくつも公開されているので、そちらにお願いすることにして、とりあえず抑えておくポイントは、EC-CUBEのようなシステムベースだから3キャリア共通でHTMLソースを使用したいという場合には、XHTMLで、ドコモ向けにコーディングし、小さなところで、auやソフトバンク向けに調整する、ということが必要なんである。

ドコモでは、XHTMLは、docタイプが適切に出力されて、MIMEタイプがapplication/xhtml+xmlとして認識されて、などいくつかの制限がクリアされないとXHTMLと認識されず、HTMLと認識されてしまう。

EC-CUBEはSMARTYのテンプレートを使用しているので、ページがdisplayされる前に、mimetypeにxhtml+xmlをセットする。

【EC-CUBEの携帯サイトを3キャリア対応のXHTMLにするための手順】

1)/data/Smarty/templates/default/mobile/site_frame.tplのヘッダを、

<?xml version=”1.0″ encoding=”Shift_JIS”?> ※この行はなくても可。
<!DOCTYPE html PUBLIC “-//i-mode group (ja)//DTD XHTML i-XHTML(Locale/Ver.=ja/1.1)1.0//EN” “i-xhtml_4ja_10.dtd”>
<html xml:lang=”ja”> 

または、

<?xml version=”1.0″ encoding=”Shift_JIS”?> ※この行はなくても可。
<!DOCTYPE html PUBLIC “-//W3C//DTD XHTML 1.0 Transitional//EN”
“http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd”>
<html xmlns=”http://www.w3.org/1999/xhtml” lang=”ja” xml:lang=”ja”>
<head>
<meta http-equiv=”Content-Type” content=”application/xhtml+xml; charset=Shift_JIS” />

とする。

2)/data/class/helper/SC_Helper_Mobile.phpのL253あたりに、

 function sfMobileInit() {
ini_set(“default_mimetype”, “application/xhtml+xml”);  //1行追加
$this->lfMobileInitInput();

これで、OK。

【EC-CUBE】携帯サイトで、画像リサイズの問題を解決する

その1)

デザイン画像について。

EC-CUBEでは、携帯サイトに使用している画像は、容量圧縮のため、自動的に低解像度のJPGに変換され、アクセスごとにアクセスしてきた携帯端末の画面サイズに合わせてリサイズされ、/upoad/mobile_image/にたまっていく。

けれど、これをされると、最初から携帯サイト向けに最適化したデザイン画像まで全てJPGで圧縮されるため、画質がエラきたない;しかも、小さなサイズの画像も横幅が一旦画面いっぱいになるようにサイズ変更される。(なんで、GIFで容量も最適化してアップロードした携帯用画像までJPG変換するのか・・・)

これでは、どの端末で見ても携帯画面の横幅いっぱいに画像が表示されますよ、奥さん。以上の弊害が大きすぎるので、もう少しグレードアップして、本当にキレイに最適化されるまで、暫定的にこの自動リサイズ機能は使わないことにする。

auやドコモでは、横幅いっぱいにしたい画像は、横幅が大きければ端末のほうで自動的にリサイズして表示してくれるので、240px位で作っておけばいいのだ。

/data/require_base.php

のL72あたり(EC-CUBE Ver.2.3.3の場合)、

require_once(CLASS_PATH . “SC_MobileImage.php”);

をコメントアウト。

これで勝手にリサイズ&変換されなくなる。

ただし、これで、横幅自動変換機能はあくまで携帯端末の機能に頼ることになるので、ソフトバンクの高解像度携帯など、一部の携帯では、横幅が広いのに小さくしか画像が表示されず、レイアウトがちょいと見にくいなど、弊害もなくはないということは認識しておく必要アリ。

その2)

つぎに、商品画像について。

商品画像は、管理画面の商品登録で、大・中・小の3種類の大きさで保存される。(必須登録は中サイズで、中または大画像をアップロードすると、それより小さいサイズは登録時に自動的にリサイズされた画像が作成される)

これは、どのサイズもPCサイトではそれなりの大きさ及び画質で表示させたいので、携帯用に小さい画像にしてしまうのは、ちぃとな~。

ところが、携帯では、なぜかresize_imageが使用できない。。。

このままでは、携帯ページのコーディングで画像サイズを指定して小さく見せることはできるが、商品リストに画像も表示したいときなんかは、画像自体は元の容量だから、容量制限のキビシイ携帯サイトでは、やっぱりつらいのである。

ということで、require.phpを少し修正して、携帯サイトでも、resize_imageが使用できるようにする。これで容量エコになる♪

携帯サイトでresize_imageがうまく動作しないのは、リダイレクトが影響しているらしい。

/html/require.php のコード、一番下のほうに、

header(“Location: “. SC_Utils_Ex::sfRmDupSlash($url . $path));
exit;

というソースがあるので、これを、

/* resize_image.phpのときだけ、リダイレクト解除 */
if(!preg_match(“/resize_image.php/i”, $path)) {
header(“Location: “. SC_Utils_Ex::sfRmDupSlash($url . $path));
exit;
}

と変更。

表示させるほうのHTMLは、

<img src=”<!–{$smarty.const.SITE_URL}–>resize_image.php?image=<!–{$image_path|sfRmDupSlash}–>&amp;width=60&amp;height=60″>

などとすればOK。

参考サイト:http://xoops.ec-cube.net/modules/newbb/viewtopic.php?viewmode=flat&topic_id=1838&forum=11

【EC-CUBE】メール送信者を社名から店舗名に変更する

EC-CUBEでは、なぜか、お問い合わせの確認メールなどを配信するときに送信元が、基本情報の店名ではなく、社名になっている。

ので、これを店名に変更。

LC_Page_Admin_Mail_Sendmail.phpのL135あたり、

,$objSite->data["company_name"]             // 送信元名

,$objSite->data["shop_name"]             // 送信元名

と変更。これで、ショップ名でメールが配信される。

【EC-CUBE】トラブル回避のためのインストールTIPS

2月20日一部追記・編集しました。——————–

EC-CUBEをインストールすると、結構なトラブルに見舞われる(^^;
ざっと思いついただけでも、

  • DBの文字化け
  • 携帯サイトで購入フローエラー
  • 郵便番号住所データ登録でエラー
  • DBのタイムゾーン問題(海外サーバなどでシステム時計のタイムゾーンが日本の標準とあってない場合など)
  • HTACCESSとPHP.INIの設定

すでに対応策をメモったものがほとんどだけど、サーバーによって対応策は違うし、順不同に個別のものをメモっただけなので、一度整理して、クリーンインストールを前提にインストール方法としてまとめようと思う。

DBがpostgreSQLの場合は、EC-CUBEは比較的トラブルも少ないようなので&今のところB豚はポスグレでインストールすることがほぼ無いので、DBは取り合えずmySQL想定で。

【EC-CUBEのインストール】

1)まずは事前確認。インストールするサーバーの環境を確認しておく。

  1. PHPとmySQLのバージョンは5以上がベター。EC-CUBEの公式対応バージョンは、
    分類 ソフトウェア 動作確認済み
    OS Windows Windows 2000 ProfessionalWindows 2000 ServerWindows 2003 ServerWindowsXP ProfessionalWindowsNT Workstation 4.0WindowsNT Server 4.0
    UNIX Linux glibc 2.1/2.2/2.3
    FreeBSD 5.4以降
    言語 PHP PHP4.1.x以降
    PHP5.0.x以降
    ライブラリ 画像生成 freetype2 2.1.x以降
    gd 2.0.x以降
    データベース Postgres PostgreSQL 7.4.x以降
    MySQL MySQL4.1以上
    (MySQL5.x系を含む)

    となっているが、1系の開発&サポートが打ち切られることもあって、今後の運用を考えるとPHP、mySQLは、どちらもver.5以上にしておいたほうが無難。

  2. サーバーのPHPがapacheのモジュール版であるかCGI版であるかを確認しておく。また、HTACCESSやPHP.INIでのサーバー設定のオーバーライドができるかどうかも確認。注意点は、(特にHTACCESSで)php_valueとphp_flagの上書き設定ができるかどうかが重要な確認事項。
    EC-CUBEの各種設定を行う際に、サーバーのデフォルト設定を個別に上書きして使用しないといけないことが多い。特に携帯サイトも一緒に使用したい場合は、これが正しく設定できないと動作がおかしくなる原因になりやすい。
    EC-CUBEでは、サーバーのphp初期設定を、HTACCESSまたはカスタムのphp.iniファイルで上書き変更している。まずPCサイト用に設定変更を行って、さらに携帯サイトのみ、さらに設定を携帯用に上書きしている。(PCの文字エンコードがUTF-8で携帯がSHIFT_JISであるため。)
    その際、PHPがCGI版で動作しているのであれば、HTACCESSファイルでは、PHPの設定の上書きはできないため、ユーザーが自分のカスタムPHP.INIファイルでそれぞれ設定を行うことになり、PHPがAPACHEモジュールで動作している場合は、HTACCESSファイルでPHP設定を上書きすることになる。
    ここでさらに1つ留意点は、PHPがapache版でHTACCESSでphp初期設定の上書きを行う場合は、ユーザーはルートのディレクトリとmobileのメインディレクトリにそれぞれ設定事項を書いたHTACCESSファイルを1つずつ配置すればいいが、PHPがCGI版でphp.iniで設定を行う場合は、EC-CUBEの/html/ディレクトリ以下の、phpファイルがあるすべてのディレクトリにそれぞれ、php.iniファイルを置いていいかなければならない。これは結構面倒。もう1つ、さらにphp.iniがユーザーごとにメインディレクトリに1つしか設定できないサーバーがある。これは、つまり=EC-CUBEでは、携帯サイトのディレクトリで別のphp.ini設定が利用できないということなので、携帯サイトも運用したいのであれば、そういうサーバーは利用しないほうがいいと思う。
    扱いやすいのは、apache版PHPのサーバーでHTACCESSファイルでの設定。ただし、PHP自体の動作はCGI版のほうが速いとか・・・海外では、CGI版がほとんどですね。。。
    また、URLをSEO対策して静的HTML化するカスタマイズを行いたいのであれば、HTACCESSでMOD_REWRITEが使用できることも合わせて確認しておくと良い。
  3. 独自SSLの使用可否と固定IPアドレスを使用する際の追加料金、制限などについても確認。
    EC-CUBEは現バージョン(2009/01/17 ver.2.3.3)では、まだ共有SSLはほんの一部の特殊条件に当てはまる場合を除き使用できない。ショップとしてきちんとセキュリティ対策を行いながら運用したいのであれば、基本独自SSLを使用することになるだろうと思う。
    独自SSLを使用するために必要なのが、固定IPアドレスだ。ホスティングサービスによっては、1契約につき固定IPは1つしか使えない、ということがあり、または共有ホスティングサービスの場合は固定IPも独自SSLもそもそも全く使えない、ということが多い。複数のショップを同じサーバーのアカウントで運用したい場合もあると思う。そういった場合は複数の固定IPアドレスでそれぞれ独自SSLが使用できなければならないことになるので、この辺も確認しておきたい。(SSLでサブドメも含めたワイルドカードSSLを使用したい場合なら、ワイルドカードSSLが使用できるか確認しておいたほうが良いと思う。ワイルドカードSSLは高価だし、使用できるサーバーサービスも意外と少ない。専用サーバーを丸々1台借りて自由に設定できるSEがいれば別だろうけど、そうでなければ留意したほうがいいと思う。)
  4. まあ、特に後から引っかかりそうなところは↑この辺。あとは、SSHで接続できないサーバーの場合は、phpMyAdminなどDBの値を後から編集できるツールが使用できるか、など自分のスキルに合わせて細かく聞いておくと良いっすな。結構あとからDB触ったりカスタマイズしたりする必要性に見舞われることが多いので。。。

2)EC-CUBEパッケージのダウンロード

  1. EC-CUBEのホームページから、EC-CUBE2系→正式版をダウンロード、解凍しておく。ダウンロードするファイルをZIPにするかTAR.GZにするかは、自分が解凍しやすいほうでOK。普通WINDOWSユーザーはZIP、LINUXユーザーはTAR.GZをダウンロードする。
    ナイトリービルド版は、有志の開発者が日々新しい機能を組み込んだりバグを修正したりしている開発版なので、いち早く新しい機能を試したい、正式版でどうやっても解消できないバグが開発版で対策されている、といった場合には使用すると良い。ただし、あくまで開発中のベータ版であるのでテストなどが不十分なこともあるから、そのあたりは自己判断で。(ここでは正式版をDLしたものとして話を進める)
  2. パッケージの中身に抜けがないかチェックするため、念のためシステム要件や仕様、構成等をホームページを見ながら軽く確認。

3)PHPの設定。

PHPがapacheモジュール版の場合は、HTACCESSファイルで、CGI版の場合は、PHP.INIで、サーバーのPHP設定をEC-CUBE用に変更する。

  1. apache版の場合
    下記はいずれも、EC-CUBEのパッケージに入っているので、そのまま使用してかまわない。また、設定する値は自分の使用しているサーバーのデフォルトの値と矛盾するものだけセットすればいい。
    /html/のなかに、「.htaccess」ファイルを作成して、下記内容で保存。

    #基本はphp_ini.incで設定するが、ini_setで反映されないものはここで設定する
    php_value mbstring.language Japanese
    php_value output_handler mb_output_handler
    php_flag mbstring.encoding_translation 1
    php_flag magic_quotes_gpc 0
    #php_flag session.use_cookies 0
    #php_flag session.use_trans_sid 1
    # INI_ALL なのにもかかわらず, ini_set で指定しても反映されない環境がある…
    php_value mbstring.internal_encoding UTF-8
    # デフォルトテンプレートの状態で 2M近くになるため
    php_value upload_max_filesize 5M
    php_value date.timezone Asia/Tokyo

    /html/mobile/にも同様に、「.htaccess」ファイルを作成して、下記内容で保存。

    php_flag mbstring.encoding_translation 0
    php_value output_handler null
    php_value variables_order EGPS
    php_flag session.auto_start 0
    php_flag session.use_trans_sid 1
    php_value date.timezone Asia/Tokyo

  2. CGI版の場合
    設定する内容は「.HTACCESS」ファイルの場合と同じ。CGI版ではHTACCESSでのPHP設定の上書きができないため、php.iniで設定する。また、同様に、設定する値は自分の使用しているサーバーのデフォルトの値と矛盾するものだけセットすればいい。
    /html/の、phpスクリプトファイルが存在する全てのディレクトリに、「php.ini」ファイルを作成して、下記内容で保存。(※ルートのphp.iniだけ設定すれば良いサーバもあるが、mobileのほうではどのみち個別に設定しなければいけない)

    #基本はphp_ini.incで設定するが、ini_setで反映されないものはここで設定する
    mbstring.language= Japanese
    output_handler= mb_output_handler
    mbstring.encoding_translation= 1
    magic_quotes_gpc= 0
    #session.use_cookies= 0
    #session.use_trans_sid= 1
    mbstring.internal_encoding= UTF-8
    upload_max_filesize= 5
    date.timezone= Asia/Tokyo

    /html/mobile/にも同様に、「php.ini」ファイルを作成して、下記内容で保存。

    mbstring.encoding_translation= on
    output_handler= null
    variables_order= EGPS
    session.auto_start= off
    session.use_trans_sid= on
    date.timezone= Asia/Tokyo

4)サーバーのWEB公開領域にダウンロードしたEC-CUBEのパッケージをアップロードする。

  1. さて、ここでちょっと考えておくのがEC-CUBEのファイルディレクトリ構成。デフォルトでは、/html/と/data/の2つのディレクトリがあり、そのままアップロードして、/html/をwebサイトのデフォルトアクセスディレクトリに設定するんであるが、その構成に当てはまるサーバ(=つまりWEBの公開ルートディレクトリより上の階層にファイルを格納できるサーバ)は意外と少ない。
    ので、ここの構成を変えることにする。必要がない場合は、このステップはスキップね。
    今回は、/html/の中身をWEBのルートディレクトリ(メインのURL http://wwwdomain.com/などとして、アクセスできるWEB用の領域。通常は、/public_html/とか/web/とか/~user名/html/になっていると思う。)にアップロードし、/data/の中身は、その中に一階層下げてアップロードすることにする。
    /html/の中に、「define.php」というphpファイルがあるので、それを秀丸などのテキストエディタで開き、
    ——
    /** HTMLディレクトリからのDATAディレクトリの相対パス */
    define(“HTML2DATA_DIR”, “/data/“);
    /** DATA ディレクトリから HTML ディレクトリの相対パス */
    define(“DATA_DIR2HTML”, “../“);
    ——
    と変更。
  2. 「data」フォルダは、「html」フォルダの中に入れ、「html」フォルダを開いて、その中身のファイルを全てサーバーにアップロード。
  3. この時点でアップロードファイルの構成パターンは大体下記の3つ。
    • dataフォルダをhtmlフォルダの中に入れ、htmlはサーバのWEBルートディレクトリになっているパターン。
      (root)|—|about|  (htmlフォルダの中身)
      —|admin| (htmlフォルダの中身)
      —|data|
      —|その他のファイル| (htmlフォルダの中身)
    • /html/をWEBの公開ディレクトリに設定し、htmlフォルダとdataフォルダが平行してアップロードされているパターン。
      |html|—|about|
      —|admin|
      —|その他のファイル|
      |data|  (※htmlと同じ階層)
    • /html/の中身をWEBの公開ディレクトリに設定し、dataフォルダは、それと同階層になるように、WEBの公開ディレクトリより1段上の階層にアップロードされているパターン。
      (root)|—|about| (htmlフォルダの中身)
      —|admin| (htmlフォルダの中身)
      —|その他のファイル| (htmlフォルダの中身)
      |data|  (※htmlの中身=rootより1段上の階層)

5)データベースの作成と事前設定。

  1. まずは、EC-CUBE用のデータベースを作成する。
  2. 作成できたら、データベース内の文字化けを防ぐため、DB内のデフォルトの文字コード設定を確認、修正しておく。
    まずは、現状のデフォルト文字コードを確認。
    phpMyAdminで下記のSQLコードを実行し、現在サーバーで使用されている文字コードを確認する。

    show variables like “char%”;

    serverphp

    システムの文字コード以外は全てutf-8になっているか確認。(システム文字コードもUTF-8であればそれはそれでかまわない) 

  3. DBの文字コードがUTF-8になっていない場合は、再びSQLで、

    alter database 〜DB名 character set utf8;

    と打ち込んで文字コードを変更。変更後、先のshowコマンドで再びチェックしておく。
    上記のように正しく変更されていればOK。

  4. このままでは、スクリプトを起動したタイミングで文字コードはサーバーのデフォルトに戻ってしまうので、スクリプトにもコードを追加する。
    /data/class/SC_DbConn.phpの65行目あたりに下記コードを追加しておく。(多分、新しいバージョンのEC-CUBEであれば、ここはパッケージソース自体が修正されていると思う。一応確認。)

    if(defined(‘DEFAULT_DSN’)) {
    $objDbConn = DB::connect(DEFAULT_DSN, $options);
    $this->dsn = DEFAULT_DSN;
    } else {
    return;
    }
    }
    }
    if (DB_TYPE == ‘mysql’) {
    $objDbConn->query(‘SET NAMES utf8′);
    }

    $this->conn = $objDbConn;

これで、いよいよインストール。

6)ブラウザから、EC-CUBEをインストールするURLを開く。インストーラの手順に沿ってインストール。

  1. インストールが正常に完了したら、再び/data/class/SC_DbConn.phpを開き、
    $this->conn = $objDbConn;の下(先のコードのL69辺り)に
    $this->conn->query(“SET time_zone = ‘Asia/Tokyo’”);
    と追記して、保存。上書きアップロード。
    ※国内サーバの場合は、タイムゾーンはすでにアジアになっているだろうから、その場合はこの設定は不要。

7)管理画面からショップの設定を行う。

先に、基本情報と特定商取引法に関する表記を入力。その後、「郵便番号DB登録」をクリック。郵便番号辞書はすごいデータ量なので、途中で何とかサーバーエラーが表示されたり画面が真っ白になることがある。
そういう時は、phpMyAdminで、mtb_zipテーブルを確認してみて、その中のデータが増えていれば、問題なく登録されていっていると考えていいので、最終的に、ブラウザで完了画面が出るまで休み休みしながら何度か繰り返しページをリロードし続ける。

完了したら、再びphpMyAdminからmtb_zipテーブルの中身を確認して、データ登録が沖縄県まで全て完了しているか確認しておこう。

最後にメールの送信テスト。
ECサイトのお問い合わせから別のメールアドレスで問合せメールを送ってみて、正常に送信(管理者とお客様双方に確認メールが届く)されればメールはOK。
もし、送信されない場合は、ブラウザからEC-CUBEの管理画面にアクセスして、システム管理画面のパラメータ設定で、「MAIL_BACKEND」の値を”smtp”から”mail”または”sendmail”に変更してみる。たいていは、「mail」で送信できるようになると思う。

大体ここまでで、クリーンインストールでトラブルになる点を解消したインストールができていると思う。カスタマイズを行う前に、フロント画面でログインや注文動作などチェックしておく。

WORDPRESS2.7にもOKなブログテーマ10

http://mashable.com/2009/01/07/wordpress-2-7-themes/

10-of-the-best-wordpress-27-compatible-themes

なかなか使いやすいテーマが揃っている。

ブログというよりもコーポレートサイトやポータルに使えそう。

【EC-CUBE】海外サーバーの時差をなんとかする(表現、ビミミョ~;)

海外サーバを使ってEC-CUBEを運営しているので、ここで時差になやまされる。

ワードプレスとかみたいなワールドワイドに結構作りこまれているソフトだとタイムゾーンを管理画面から調整できるのだけど、EC-CUBEは純国産だからか、そういう機能は残念ながら無い;

時差を吸収するためには、2つの対策が必要。

1つめ)PHPの扱う時間。これは受注メールを送ったりといったときに出てくることになる。
2つめ)DBが扱う時間。こっちは、受注した時間や管理画面を操作した時間なんかが登録される。

1つ目の対策→php.iniに、タイムゾーンを書く。

2つ目の対策→/data/class/SC_DbConn.phpの
「$this->conn = $objDbConn;」の1行後ろに、
「$this->conn->query(“SET time_zone = ‘Asia/Tokyo’”);」を追加。

これで、DBに格納される受注日などは日本のタイムゾーンで登録される。

先に既に登録されているものは変更されないので、手動で変更。

WORDPRESSのビデオテュートリアル30選

http://sixrevisions.com/wordpress/30-excellent-wordpress-video-tutorials/

テーマの作成やカスタマイズ法などがビデオテュートリアルで公開されている。

但し、英語なので、全然分かってないところから、、、というのは、ちと厳しいかも。
大体概要は分かっていて、もう少しスキルブラッシュアップしたい、というときには、とてもいい勉強になりそう。

【EC-CUBE】SMARTYでマルチバイト文字を丸める(字数制限を利用する)

SMARTYのテンプレートで商品説明などを表示するときに、レイアウト上、前から10文字だけを表示してあとは、「…」という感じで表示する文字数を合わせたいときに利用する。

前から何文字目から何文字、といったように文字を丸めるわけだが、日本語の場合マルチバイトなので、PHPで本来の丸めにつかうtrancate()が利用できないので、mb_strimwidth()を使う。

それをSMARTY上で、利用することになる。

例:

{$hoge|mb_strimwidth:0:40:”…”|escape}

『$hogeの文字列の最初から(=0)、40字(=40)を表示し、一番最後は「…」と表示する。』という意味。
注意しておくのは、どうやら、この40字、マルチバイトは半角の2文字なので、つまりは、これで20文字ということになる模様。なるほど。

これ、結構使えるなぁ。

参考:
http://www.php-seed.net/blog/archives/118
http://www.phppro.jp/phpmanual/php/function.mb-strimwidth.html

【EC-CUBE】テンプレートの中に別のテンプレート(ブロック)を呼び込む記述

1)管理画面からブロック(tempA)を作る。 (※既存のテンプレブロックの場合は、これは不要)

2)読み込む側のテンプレのソースにインクルード用のコードを記述する。

<!–{assign var=tempA value=$smarty.const.USER_TEMPLATE_PATH|cat:”default/bloc/tempA.tpl“}–>
<!–{include file=$tempA}–>

重要!)先に変数にアサインしてから、インクルードすること。上記ソース参照。
下記でも可能。

<!–{include file=`$smarty.const.USER_TEMPLATE_PATH`default/bloc/tempA.tpl}–>

【EC-CUBE】テンプレを変更してもブロックレイアウト情報を設定したとおりに再現する

EC-CUBEでは、ブロックのデフォルトレイアウトが、update_block.sqlのSQL文によって設定されている。

管理画面でレイアウトを決めても、テンプレートを変更したり、キャッシュをクリアした場合、ブロックレイアウトの情報をこのupdate_block.sqlから新規に読み込んできてしまうため、その都度デフォルトのブロックレイアウトに変わってしまう。

これじゃあ、イタチのおっかけっこってやつじゃあないですかい?
ってことで、一旦リリースしたWEBサイトでは、次にテンプレ更新したときも、やっぱり同じブロックレイアウトで表示されたいですな、ってことで、どん。

update_block.sqlは、
/data/smarty/templates/(テンプレ名)/_packages/sql/
/user_data/packages/(テンプレ名)/sql/
/user_data/packages/default/sql/
にそれぞれあるので、ここの値を変更。

テンプレの更新時に読み込んでもらいたいなら(Aのテンプレでは、Aのブロックレイアウトセットを使うけど、違うテンプレのときには違うブロックレイアウトセットを使うときは)/data/smarty/templates/(テンプレ名)/_packages/sql/のなかのupdate_block.sqlのみ編集。

下記に編集ルールをば。

INSERT INTO dtb_blocposition (page_id,target_id,bloc_id,bloc_row,filename)values(1,5,1,0,’category’);

これは、前から、

  • page_id→
  • target_id→5
  • bloc_id→1
  • bloc_row→0
  • filename→category

と設定されているということで、

page_id トップページ=1、一覧ページ=2、詳細ページ=3、マイページ=4、その他カスタムで作成したページへID付与。(dtb_pagelayout参照)
target_id 左カラム=1、中央上カラム=2、右カラム=3、中央下カラム=4、未使用ブロック=5.mtb_target参照)
bloc_id カテゴリー=1、利用ガイド=2、かごの中=3等。(dtb_bloc参照)
bloc_row カラム内でのブロックの表示優先順位。0は非表示で、target_idに5(未使用ブロック)が選択されている場合に設定可能。
filename カテゴリー=1、利用ガイド=2、かごの中=3等。(dtb_bloc参照)bloc_idと対応している。

つまり、上記の文では、トップページでは、カテゴリーブロックが未使用、ということ。

自分で、決めたレイアウトどおりにブロックの配列を記載しておくとよい。

新規ページを作成した場合、そのブロックの設定は、データベースのdtb_blocpositionに保存されるので、テンプレが更新されてもリセットはされない。デフォルトの各ページのみこのSQLの影響を受ける。もちろん新規ページについても同SQL内で設定しておくことも可能。

【EC-CUBE】入力欄の許可タグ

入力欄の許可タグ・・・

許可されてる種類が異様に少ない・・・

<li>は許可されて、<ol>とか<ul>入ってないって、どういうこと!?
<span>ないってどういうこと!?
<th>はあかんのか!?

・・・・・追加。

DBのmtb_allowed_tagに、追加したいタグのそれぞれ開始タグと終了タグを登録する。
PhpMyAdminでDBにアクセスして、mtb_allowed_tagを探してデータ編集。
IDとRANKは、データの一番後ろから連番で追加していくこと。

インストールのときから、増やしときたい場合は、インストールのところのプログラムをイジイジ。(とりあえず、今は、先にインストールされたEC-CUBEのカスタマイズのハナシなんで、こっちのハナシは一旦無視。)

登録できたら、/data/cache/の中の「mtb_allowed_tag.php」削除して、一応管理画面もログアウトしてから再ログイン。

これで、タグ許可の入力エリアに入力できるタグの種類が増えた♪

【EC-CUBE】ヘッダーにトップページだけメインビジュアルをででんと表示する

トップページに大きくメインビジュアルを表示させる場合(ホラ、あれよ、アレ。メインビジュアルどど~ん、ってやつよ。フラッシュとか。)site_main.tplやtop.tplにいれるとカラムの影響を受けてしまうので、header.tplへトップページの場合のみエリアを表示させる変更を入れることにする。

該当出力ページが、サイトのトップページ(/index.php)だったら、<div id=”mainvisual”></div>を表示。
それ以外だったら、この部分には何も表示しない。

<!–{if $smarty.server.PHP_SELF == “/index.php”}–>
<div id=”mainvisual”>(この中にフラッシュのソース他コンテンツを入れる)</div>
<!–{else}–><!–[if}–>

以上だす。

【EC-CUBE】携帯用詳細コメントを追加する

データベースに携帯用コメントカラムを追加し、商品登録時に、携帯用には別の詳細説明を登録し、PCサイトの説明と別にする。

  • データベースにカラム(フィールド)追加
  • 商品登録のPHPスクリプト追加
  • 管理画面の商品登録・確認テンプレートを修正
  • モバイル用詳細テンプレートを修正

その1)データベースへのカラム追加

phpMyAdminでDBへアクセスし、dtb_productsの最後へ1カラム追加。

カラム名「comment7」
データ型「text」

※残りのフィールドは先のデータを参照。

その2)商品登録PHPの修正。

/data/class_extends/page_extends/admin/products/LC_Page_Admin_Products_Product_Ex.php

/data/class/pages/admin/products/LC_Page_Admin_Products_Product.phpからlfRegistProduct関数 (=商品登録関数)をコピー(L387~L493:ver.2.3.2の場合)し、LC_Page_Admin_Products_Product_Ex.phpの「デストラクタ」の下(L68:ver.2.3.2の場合※最後の「}」の手前へ。)へ貼り付け。
ソースを一部編集する。

貼り付けたソースのL78あたりにcomment7(=携帯用コメント)を追加。

 ”comment4″, “comment5″, “comment6″, “comment7″, “main_list_comment”,

L97あたりにも1行追加。

$sqlval['comment7'] = $arrList['comment7'];

LC_Page_Admin_Products_Product.phpからLC_Page_Admin_Products_Product_Ex.phpへ、lfErrorCheck関数もコピー。(L546~L609:ver.2.3.2の場合)
lfRegistProduct関数の下に貼り付け。

貼り付けたソースのL183あたり
$objErr->doFunc(array(“詳細-メインコメント”, “main_comment”, $this->arrAllowedTag), array(“HTML_TAG_CHECK”));
の下に2行追加。

$objErr->doFunc(array(“携帯用詳細コメント”, “comment7″, LLTEXT_LEN), array(“SPTAB_CHECK”, “MAX_LENGTH_CHECK”));
$objErr->doFunc(array(“携帯用詳細コメント”, “comment7″, $this->arrAllowedTag), array(“HTML_TAG_CHECK”));

その3)MySql用にデータの読み込みコードを追加

これをやらないと、再編集するときに、登録画面に以前に登録したデータが読み込まれない;

/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.php (L304あたり:ver.2.3.3の場合)

「T1.comment6,」の下に1行追加し、「T1.comment7,」。

その4)データ登録用ADMINテンプレートの編集。

商品登録画面のテンプレートへ携帯用情報登録フォームのコード追加。

/data/Smarty/templates/default/admin/products/product.tpl (L243あたり、詳細-メインコメントのTD中へ。)

 <br><br>
 <div class=”center”>
  <input type=”button” name=”btn” onclick=”selectAll(‘category_id’); lfDispSwitch(‘mobile_detail’);” value=”モバイル専用詳細コメント表示/非表示”>
 </div>
 <div id=”mobile_detail” style=”<!–{if !$arrForm.comment7}–>display:none<!–{/if}–>”>
  <p>
  PCと携帯で異なる詳細コメントを表示する際には以下のフォームに携帯サイト用のコメントを入力して下さい。<br />
  入力されなかった場合は、PCサイトと同じ詳細コメント↑を表示します。<br />
  </p>
  <textarea name=”comment7″ id=”comment7″ value=”<!–{$arrForm.comment7|escape}–>” maxlength=”<!–{$smarty.const.LLTEXT_LEN}–>” style=”<!–{if $arrErr.comment7 != “”}–>background-color: <!–{$smarty.const.ERR_COLOR}–><!–{/if}–>”  cols=”60″ rows=”8″ class=”area60″><!–{$arrForm.comment7|escape}–></textarea><br /><span class=”red”> (上限<!–{$smarty.const.LLTEXT_LEN}–>文字)</span>

確認画面は、携帯用コメントを入力した場合のみ表示されるようにコードを追加。

/data/Smarty/templates/default/admin/products/confirm.tpl (L183あたり、詳細-メインコメントの/TRの後ろへ。)

<!–{if $arrForm.comment7}–>
<tr>
 <td bgcolor=”#f2f1ec” width=”160″ class=”fs12n”>モバイル詳細コメント</td>
 <td bgcolor=”#ffffff” width=”557″ class=”fs12n”>
 <!–{$arrForm.comment7|nl2br}–>
 </td>
</tr>
<!–{/if}–>

その5)モバイルサイトの表示テンプレートを編集。

/data/Smarty/templates/default/mobile/products/detail.tpl (L39あたり。詳細メインコメントの表示を変更。)

<!–{$arrProduct.main_comment|nl2br}–>

↓下記に変更。

<!–{if !$arrProduct.comment7}–><!–{$arrProduct.main_comment|nl2br}–><!–{else}–><!–{$arrProduct.comment7|nl2br}–><!–{/if}–>

携帯専用のコメントがある場合は、それを表示し、ない場合は、PC用のコメントを共用で表示する。

参考:http://www.eccube-school.jp/products/detail40.html
※DBがポスグレの場合は、上記手順と少し違うため、こちらのサイトを参照のこと。

【EC-CUBE】お問い合わせの項目を追加する(お問い合わせタイトルの選択追加)

EC-CUBEのお問い合わせでお問い合わせ内容の区分によってタイトルを選択する仕様を追加。

同様の応用で項目の追加もできる。(多分タイトル追加よりは少し簡単)

  • お問い合わせフォームでタイトル(お問い合わせカテゴリー)を選択してもらい、
  • 受付確認メールのタイトルにそのお問い合わせタイトルを表示し、
  • メールの中にもタイトルを表記する
  • タイトルは必須チェックはかけない。(かけてもいいけどとりあえず要らない;)

という処理でやってみる。

その1)お問い合わせフォームのテンプレートに選択フィールドを追加。

/data/Smarty/templates/default/contact/index.tpl (L37あたり:ver.2.3.2)

<tr>
<th>タイトル</th>
<td><select name=”contacttitle” value=”<!–{$contacttitle|default:$arrData.contacttitle|escape}–>” style=”<!–{$arrErr.contacttitle|sfGetErrorColor}–>”>
<option value=”">タイトルを選択</option>
<option label=”●●に関するお問い合わせ” value=”●●に関するお問い合わせ”>●●に関するお問い合わせ</option>
<option label=”▲▲に関するお問い合わせ” value=”▲▲に関するお問い合わせ”>▲▲に関するお問い合わせ</option>
<option label=”その他のお問い合わせ” value=”その他のお問い合わせ”>その他のお問い合わせ</option>
</select></td>
</tr>

/data/Smarty/templates/default/contact/confirm.tpl (L38あたり)

<tr>
<th>タイトル</th>
<td><!–{$arrForm.contacttitle|escape}–></td>
</tr>

その2)メールのテンプレートの本文中にも項目を追加。(※本文中には不要な場合は省略)

/data/Smarty/templates/default/mail_templates/contact_mail.tpl (L41あたり)

■タイトル:<!–{$arrForm.contacttitle}–>

その3)LC_Page_Contact.phpのコードの修正・追加

/data/class/pages/contact/LC_Page_Contact.php

(L79あたり)コード追加。

array( “column” => “contacttitle”, “convert” => “aKV” ),

(L258あたり)コード追加。(お客様送信メール用のタイトルをセット)

$fromMail_title = $objPage->arrForm['contacttitle'];

(L261あたり)同じコード追加。(自分送信メール用のタイトルをセット)

$fromMail_title = $objPage->arrForm['contacttitle'];

(L263あたり)コード変更。

$subject = $helperMail->sfMakeSubject($objQuery, $objMailText, $this, “お問い合わせがありました。”);

これを↓

$subject = $helperMail->sfMakeSubject($objQuery, $objMailText, $this, $fromMail_title);

(L276あたり)コード変更。

$subject = $helperMail->sfMakeSubject($objQuery, $objMailText, $this, “お問い合わせを受け付けました。”);

これを↓

$subject = $helperMail->sfMakeSubject($objQuery, $objMailText, $this, $fromMail_title);

その他)

/data/Smarty/templates/default/contact/mail_title.tpl

L24あたり。
→【 】内へショップネームが入るようになっている。その後上記のタイトルが入ります。変更が必要であればここも変える。但し、これはサイト全体の設定になるため、注文メールなども同様の設定になるので注意。

【EC-CUBE】受注管理でデータの更新ができない場合にエラーメッセージを出す

受注データの更新ができていなくてもアラートがでなかったのを、ちゃんとエラーメッセージが出るようにする。(エラーなく更新できるようにバグ修正するわけではないので誤解なきよう注意。)

/data/class/pages/admin/order/LC_Page_Admin_Order_Edit.php

L151あたりの

   if(count($this->arrErr) == 0) {
       $this->lfRegistData($_POST['order_id']);
       // DBから受注情報を再読込
       $this->lfGetOrderData($order_id);
       $this->tpl_onload = “window.alert(‘受注履歴を編集しました。’);”;
     }

これを↓下記に。

   if(count($this->arrErr) == 0) {
      $this->lfRegistData($_POST['order_id']);
      // DBから受注情報を再読込
      $this->lfGetOrderData($order_id);
      $this->tpl_onload = “window.alert(‘受注履歴を編集しました。’);”;
    } else {
       $this->tpl_onload = “window.alert(‘受注履歴が編集できませんでした。”.array_shift($this->arrErr).”‘);”;
    }

【EC-CUBE】売り上げ集計をバッチモードにして動作を軽減(再びCRON)

EC-CUBEの売り上げ集計は2つのモードが選択でき、デフォルトは、リアルタイム集計。処理が長くなると、タイムアウトしてしまったり、ダウンしてしまう。

  1. リアルタイム・・・「月度で集計する」や「期間で集計する」ボタンが押されたときにその場で集計→集計データ格納→集計データ取得→表示、と行う方法。
  2. バッチモード・・・あらかじめ売上データを集計しておき、「月度で集計する」や「期間で集計する」ボタンが押されたときには、すでに集計して格納済みのデータを取得→表示、と行う方法。

その1)管理モードの変更

管理画面→システム管理→パラメータ管理で、
DAILY_BATCH_MODEを[false]から[true]に変更。

その2)/data/script/execute_batch_daily.phpを作成。

/**
* デイリーバッチ起動スクリプト
*/

require_once( dirname(__FILE__) . “/../install.php” );
define( “CLASS_PATH”, DATA_PATH . ‘class/’ );
define( “CLASS_EX_PATH”, DATA_PATH . ‘class_extends/’ );
define( “CACHE_PATH”, DATA_PATH . ‘cache/’ );

require_once(CLASS_EX_PATH . “util_extends/GC_Utils_Ex.php”);
require_once(CLASS_EX_PATH . “util_extends/SC_Utils_Ex.php”);
require_once(CLASS_EX_PATH . “db_extends/SC_DB_MasterData_Ex.php”);
require_once(CLASS_EX_PATH . “db_extends/SC_DB_DBFactory_Ex.php”);
require_once(CLASS_PATH . “SC_DbConn.php”);
require_once(CLASS_PATH . “SC_Query.php”);
require_once(CLASS_PATH . “SC_SelectSql.php”);

require_once(CLASS_EX_PATH . ‘batch_extends/SC_Batch_Daily_Ex.php’);
require_once(CLASS_EX_PATH . “SC_Initial_Ex.php”);
// アプリケーション初期化処理
$objInit = new SC_Initial_Ex();
$objInit->init();

$usage = <<

php -f execute_batch_daily.php start term
集計期間を指定して売上集計をします。

 start 集計開始日。何日前の売上から集計するか。1 から 365以内で指定。
 term 集計対象期間。何日分の売上を集計するか。1 から 365以内で指定。

例:昨日の売上を集計します。
php -f execute_batch_daily.php 1 1

USAGE;

if ( $argc != 3 ) {
echo ( $usage );
exit(1);
}

$start = $argv[1];
$term = $argv[2];
if ( !is_numeric( $start ) || !is_numeric( $term ) ) {
echo ( $usage );
exit(1);
}

$start = intval( $start );
$term = intval( $term );

if ( $start < 1 || $start > 365 || $term < 1 || $term > 365 ) {
echo ( $usage );
exit(1);
}

if ( $term > $start ) {
echo ( $usage );
exit(1);
}

$objBatch = new SC_Batch_Daily_EX();
$objBatch->lfStartDailyTotal( $term, $start, true );
?>

その3)/data/class/batch/SC_Batch_Daily.phpを修正。

L92,93(ver.2.3.2の場合)

// 削除された受注データの受注詳細情報の削除
$objQuery = new SC_Query();
//$where = “order_id IN (SELECT order_id FROM dtb_order WHERE del_flg = 1)”; ←コメントアウト
//$objQuery->delete(“dtb_order_detail”, $where); ←コメントアウト

// 最後に更新された日付を取得

// 最後に更新された日付を取得

L102(ver.2.3.2の場合)

// 最後のバッチ実行からLOAD_BATCH_PASS秒経過していないと実行しない。
if($pass < LOAD_BATCH_PASS) {
//GC_Utils_Ex::gfPrintLog(“LAST BATCH ” . $arrRet[0]['create_date'] . ” > ” . $batch_pass . ” -> EXIT BATCH $batch_date”); ←コメントアウト
$batch_next = date( “Y-m-d H:i:s”, strtotime($batch_last) + LOAD_BATCH_PASS ); ←追加
GC_Utils_Ex::gfPrintLog(“LAST BATCH ” . $batch_last . ” NEXT BATCH AFTER $batch_next -> EXIT BATCH”); ←追加

return;
}

L107(ver.2.3.2の場合)

// 集計
//for ($i = $start; $i < $term; $i++) { ←コメントアウト
for ($i = $start, $k = 0; $k < $term; $i–, $k++ ) { ←追加
// 基本時間から$i日分さかのぼる
$tmp_time = $now_time – ($i * 24 * 3600);

L154(ver.2.3.2の場合)

GC_Utils_Ex::gfPrintLog(“LOADING BATCH $batch_date”);
$this->lfBatOrderDaily($tmp_time);
$this->lfBatOrderDailyHour($tmp_time);
$this->lfBatOrderAge($tmp_time);
// タイムアウトを防ぐ ←追加
SC_Utils_Ex::sfFlush(); ←追加

}
}

※そもそも集計時にSQLエラーになるところがあるので、先に
http://www.bton.net46.net/?p=724
の修正を行っておくこと。

その4)CRONの設定

0 2 * * * /usr/local/bin/php -f /path/to/eccube/data/script/execute_batch_daily.php 1 1 2>&1 > /dev/null

参考サイト:http://d.hatena.ne.jp/yuhei_kagaya/20081019

ホーム > CMS・ブログツール

Search
Feeds
Meta

Return to page top