/data/class/helper/SC_Helper_DB.phpにはやたら沢山メソッドがあるのですが、その中にカテゴリ関連のものも存在します。
カテゴリを取得できるっぽいメソッドとしてSC_Helper_DB::sfGetCatTree()があります。
1
2
3
4
5
6
7
8
|
/**
* カテゴリツリーの取得を行う.
*
* @param integer $parent_category_id 親カテゴリID
* @param bool $count_check 登録商品数のチェックを行う場合 true
* @return array カテゴリツリーの配列
*/
function sfGetCatTree($parent_category_id, $count_check = false)
|
ちょっと試してみます。
1
|
$ret=$SC_Helper_DB->sfGetCatTree('1',false);
|
親カテゴリIDが1のリストを取得してくるかと思えば、何故か商品が一件でも登録されているカテゴリが全て返ってきました。
なんだこれ。
試しに発行されたSQLを覗いてみると、
1
2
3
4
5
6
7
|
SELECT
T1.category_id, category_name, level
FROM dtb_category AS T1
LEFT JOIN dtb_category_total_count AS T2
ON T1.category_id = T2.category_id
WHERE
del_flg = 0 AND product_count > 0ORDER BY rank DESC
|
……何処にもparent_category_idの文字がない……
実際メソッドを見てみると、上記SQLで全てのカテゴリを取得後、親カテゴリIDを取得してその中に突っ込むという何をやっているのかさっぱりわからないことをやっています。
これは一体何のためのメソッドなんだ?
もうひとつカテゴリを取得できそうなメソッドを見つけました。
1
2
3
4
5
6
7
8
9
10
11
12
|
/**
* カテゴリツリーの取得を行う.
*
* $products_check:true商品登録済みのものだけ取得する
*
* @param string $addwhere 追加する WHERE 句
* @param bool $products_check 商品の存在するカテゴリのみ取得する場合 true
* @param string $head カテゴリ名のプレフィックス文字列
* @return array カテゴリツリーの配列
*/
function sfGetCategoryList($addwhere = "",
$products_check = false, $head = CATEGORY_HEAD)
|
試してみます。
1
|
$ret=$SC_Helper_DB->sfGetCategoryList('parent_category_id=1',false);
|
無事に想定どおり、親カテゴリIDが1であるカテゴリの配列が返ってきました。
めでたしめでたし。
が、調子に乗って
1
2
|
$ret=$SC_Helper_DB->sfGetCategoryList(
'parent_category_id='.$_REQUEST['category_id'],false);
|
とすると死にます。
引数として'1 OR 1=1'を与えると見事に全カテゴリが返ってきてしまいました。
普通こういうメソッドを作る場合は$addwhereを連想配列なりプリペアドクエリなりにし、メソッド側でエスケープ処理を行います。
SC_Helper_DB::sfGetCategoryList()は
1
|
$where.= " AND $addwhere";
|
という信じがたいことをやっているので、外部引数を使用するときにはこのメソッドを使うことができません。
全てのメソッドがこのような作りであれば(よくはありませんが)まだましなのですが、
例えばSC_Helper_DB::sfDataExists($table_name, $where, $arrval)は引数$whereにプリペアドクエリを用意し$arrvalにその値を入れるという作りになっています。
1
2
|
$ret=$SC_Helper_DB->sfDataExists('dtb_category'
, 'parent_category_id=?', array($_REQUEST['category_id']))
|
という形で安全に引数を渡すことができるようになっているのです。
いやはやなんでこんな酷いことになってるんですかね。
簡単に子カテゴリリストを取得できるメソッドを追加しましょう。
/data/class_extends/helper_extends::SC_Helper_DB_Ex.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
/*
子カテゴリリストを取得
*/
public function getChildCategory($parent_category_id=0){
//SQL
$objQuery = new SC_Query();
$col = " * ";
$where = "del_flg = 0 AND parent_category_id = ?";
$objQuery->setOption("ORDER BY rank DESC");
//実行
$arrRet = $objQuery->select($col, "dtb_category",
$where, array($parent_category_id));
//返却
return $arrRet;
}
|
何故この程度のメソッドが最初から用意されていないのかは謎。
SC_Helper_DBそのものについても、SC_Queryを毎回newせずにコンストラクタで用意しておいてSC_Queryにreset()、resetOrder()を用意してくれとかSC_Queryを渡したりするのをやめてくれとかいろいろ言いたいことはあるのですがあまりに酷すぎるのでもういいや。
EC-CUBEの記事
ところが転送先URLに
hoge.php?id=100
とか書いても、転送先では$_REQUEST['id']を取得できなかったりします(取得できる場合もある)。
転送先URLの作成などはPear::Net_URLを使用しています。
URLにセッションID等を付加する処理は以下のようになっています。
1
2
3
4
5
6
7
8
9
|
$netURL = new Net_URL($url);
if (!empty($_SERVER['QUERY_STRING'])) {
$netURL->addRawQueryString($_SERVER['QUERY_STRING']);
}
$session = SC_SessionFactory::getInstance();
if ($isMobile || $session->useCookie() == false) {
$netURL->addQueryString(session_name(), session_id());
}
$netURL->addQueryString(TRANSACTION_ID_NAME, $this->getToken());
|
どこが問題なのかというと、ここです。
1
2
3
|
if (!empty($_SERVER['QUERY_STRING'])) {
$netURL->addRawQueryString($_SERVER['QUERY_STRING']);
}
|
単にURLにリクエストパラメータを追加しているようにしか見えませんが、実はNet_URL::addRawQueryString()は「追加」ではなく「上書き」です。
ちなみに同じような名前のNet_URL::addQueryString()は追加です。
なにこの罠。
従って、何かひとつでもリクエストパラメータがあった場合にLC_Page::sendRedirect($url)を使用すると、$urlに引き渡したGETパラメータは全て消え失せてしまいます。
これはNet_URLのバグだと思うのですが中の人はバグじゃないとか言っています。
だったら名前どうにかしろよと。
仕方ないのでこちらでどうにかしましょう。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
function sendRedirect($url, $isMobile = false ) {
$netURL = new Net_URL($url);
//GETパラメータを保存しておく
$queryStringArray=$netURL->querystring;
//今までの処理
if (!empty($_SERVER['QUERY_STRING'])) {
$netURL->addRawQueryString($_SERVER['QUERY_STRING']);
}
$session = SC_SessionFactory::getInstance();
if ($isMobile || $session->useCookie() == false) {
$netURL->addQueryString(session_name(), session_id());
}
$netURL->addQueryString(TRANSACTION_ID_NAME, $this->getToken());
//GETパラメータを追加
if(is_array($queryStringArray)){
foreach($queryStringArray as $key=>$val){
$netURL->addQueryString($key, $val);
}
}
//リダイレクト
header("Location: " . $netURL->getURL());
exit();
}
|
できました。
EC-CUBEの記事
http://blog.cnobi.jp/v1/blog/user/8f14c19eb01af9c2e80c7f2ad07dc8ca/1271426019
EC-CUBE2.4.3用です。
基本的にはSC_CartSession.phpを差し替えるのですが、一部問題点があるので修正策も提示しておきます。
主な変更点
・$_SESSION['cart'][0]、$_SESSION['cart'][1]…となっていた商品リストを$_SESSION['cart']['products']配下に入れた
・商品の配列キーを連番ではなく商品IDにした
・cart_noも面倒なのでIDにした
・SC_CartSession::getNextCartID()、SC_CartSession::getMax()は不要なので削除
・ereg()を排除
注意事項
・あんまりデバッグしてない
・売り切れとかポイント関連は何やってるのかよくわからなかったので概ね適当
・$_SESSION['cart']を直接どうこうしていた場合動かなくなるかもしれない
・MySQLで作ったのでPostgreSQLだと動かなくなるかもしれない
・マジックメソッドとかrunkitとかの強力な機能でカートを上書きしていた場合動かなくなるかもしれない
・SC_CartSession::getNextCartID()、SC_CartSession::getMax()を使用していた場合動かなくなるかもしれない
・商品配列のキーが数値連番である前提の実装だった場合動かなくなるかもしれない
・よくわからないけどどこかで動かなくなるかもしれない
さて、差し替えただけでは一部動かない場所があります。
まあ注意事項の下から2番目と3番目に引っかかってるんですが。
まずSC_Helper_DB::sfTotalCart()、LC_Page_Cart::process()、LC_Page_Shopping_Complete::lfRegistOrderDetail()。
何れも商品リストに対し、
for ($i = 0; $i < $max; $i++) {
とか書いてあります。
それぞれ順番に、
foreach( $arrCart as $i => $val){
foreach( $arrRet as $i => $val){
foreach( $arrCart as $i => $val){
に書き換えるとそのまま動きます。
なんでそんなにforが好きなの?
次にLC_Page_Shopping_Payment::lfGetDelivDate()
max = $objCartSess->getMax();
for($i = 1; $i <= $max; $i++) {
とか書いてあります。
ていうか、$_SESSION[$objCartSess->key]とか書いてあります。
これはひどい。
勝手拡張でこんなのを追加した、とかなら仕方ないかもしれないが正式版でやることではなかろう。
何故SC_CartSession::getAllProductID()を使わないのかと。
以下の部分を書き換えます。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
|
// 商品IDの取得
$max = $objCartSess->getMax();
for($i = 1; $i <= $max; $i++) {
if($_SESSION[$objCartSess->key][$i]['id'][0] != "") {
$arrID['product_id'][$i]
= $_SESSION[$objCartSess->key][$i]['id'][0];
}
}
↓
// 商品IDの取得
$arrID['product_id']=array();
$tmp=$objCartSess->getAllProductID();
foreach($tmp as $key=>$val){
$arrID['product_id'][]=$val[0];
}
|
この$arrID、別に他に使われているわけでもないし二次元配列にする意味が全く無いんだが何故こんなことに。
以上でSC_CartSessionが見た目すっきりになりました。
実はなにか重大な理由があってあのような作りになっていたとかいう可能性もないでもないですが気付かなかったことにします。
まあ、修正したはいいけどパフォーマンスチェックとかやってないから早くなったという保証はないんですがね。
というか、毎回尋常じゃない結合をやっているSQLのほうが明らかにボトルネックなので正直自己満足レベル。
あと、カートなんてどう考えても投入より参照回数の方が多いんだから、税金の計算とかも投入時にやるべきなんですが、そこらへんもやってません。
めんどうだったので。
EC-CUBEの記事
見れば見るほど誰がこんな正気の沙汰ではない実装を行ったのか、というかどうしてこのような実装を行おうという発想に至ったのかが不思議でしょうがない。
例えばカートの中身を全部拾うメソッドを実装するとして、100人中99人が
1
2
3
|
function getCartList(){
return $_SESSION['cart']['products'];
}
|
とか書く思うのですが、EC-CUBEの場合は何故か2回ループが走ります。
具体的にはこんな。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
function getCartList() {
$max = $this->getMax();
$arrRet = array();
for($i = 0; $i <= $max; $i++) {
if(isset($_SESSION['cart'][$i]['cart_no'])
&& $_SESSION['cart'][$i]['cart_no'] != "") {
$arrRet[] = $_SESSION['cart'][$i];
}
}
return $arrRet;
}
function getMax() {
$cnt = 0;
$pos = 0;
$max = 0;
if (count($_SESSION['cart']) > 0){
foreach($_SESSION['cart'] as $key => $val) {
if (is_numeric($key)) {
if($max < $key) {
$max = $key;
}
}
}
}
return ($max);
}
|
これに限らず、カートに対して何か操作を行おうとするたびに
・毎回カートセッションの全要素に対してforeachでループを行い配列のキーの最大値を求める
・求めた値に対しforループを行い何かを行う
という流れになっています。
なんでこんなことになっているかというと、これは、カートセッションの作りが、
1
2
3
4
5
6
7
|
$_SESSION['cart']=array(
'prev_url'=>戻り先URL
,'cancel_purchase'=>購入キャンセル
,[0]=>array(カート内の商品1)
,[1]=>array(カート内の商品2)
,…
);
|
と、カート内商品と他の要素が並列になっているからです。
なので商品に対し何かを行いたい場合に直接扱えない状態になっています。
1
2
3
4
5
6
7
8
9
|
$_SESSION['cart']=array(
'prev_url'=>戻り先URL
,'cancel_purchase'=>購入キャンセル
,'products'=>array(
[0]=>array(カート内の商品1)
,[1]=>array(カート内の商品2)
,…
));
|
ってするだけで平穏無事に終わったはずなのに。
最初の設計が悪かったせいで後々まで苦労するといういい例ですね。いやよくないけど。
ところでこのSC_CartSession、メソッド中の'cart'の部分が全て$this->keyとなっており、引数を変えることで同時に複数のカートセッションを扱えるような作りになっています。
この部分だけは面白いのだが使い道がわからない。
EC-CUBEの記事
/data/Smarty/templates/default/header.tpl
/data/Smarty/templates/default/footer.tpl
が使用されます。
また、ユーザで作成したテンプレがあれば、
/html/user_data/packages/default/header.tpl
/html/user_data/packages/default/footer.tpl
が優先して使用されます。
これでは、たとえばログイン画面などの一部のページだけ全然別のヘッダにしたいんだよ、といった場合に対応できません。
一番手っ取り早いのはExクラスで適当にフラグを突っ込んで、header.tplで場合分けでしょう。
/data/class_extends/page_extends/mypage/LC_Page_Mypage_Login_Ex.php
1
2
3
4
|
function process() {
$this->use_tpl_hoge=1;
parent::process();
}
|
1
2
3
4
5
|
<!--{$use_tpl_hoge}-->
違うヘッダ
<!--{else}-->
いつものヘッダ
<!--{/if}-->
|
ですがまあ正直どうなのという作り方ですね。
どうにかしてみましょう。
テンプレートの割り当ては
/data/class/SC_View.phpのSC_View::SC_View()、コンストラクタで行っています。
で、困ったことにLC_Page_Mypage_Login等のクラスはLC_Page_Mypage_Login::process()内でSC_Viewをインスタンス化して表示まで一気に行ってしまっています。
Exクラスから介入する余地がないんですよね。
毎度言ってますがなんでこんな適当な作りなんですかね。
具体的なロジックはここら辺になります。
1
2
3
4
5
6
7
8
9
10
11
12
|
// ヘッダとフッタを割り当て
$header_tpl = USER_PATH . USER_PACKAGE_DIR
. TEMPLATE_NAME . "/" . "header.tpl";
$footer_tpl = USER_PATH . USER_PACKAGE_DIR
. TEMPLATE_NAME . "/" . "footer.tpl";
// ユーザー作成のテンプレートが無ければ, 指定テンプレートを割り当て
if (!$this->_smarty->template_exists($header_tpl)) {
$header_tpl = TEMPLATE_DIR . "header.tpl";
}
if (!$this->_smarty->template_exists($footer_tpl)) {
$footer_tpl = TEMPLATE_DIR . "footer.tpl";
}
|
ユーザディレクトリ内にヘッダフッタがあればそれを割り当て、それが無ければデフォルトのテンプレートを割り当てています。
外部から値を渡すことができないので操作もできません。
結局該当のクラスを直接変更するしかありません。
LC_Page_Mypage_Login::process()の、SC_SiteViewをインスタンス化した直後あたりに以下を埋め込みましょう。
1
2
3
|
//ヘッダフッタのテンプレートを変更する
$objView->assign("header_tpl", TEMPLATE_DIR . "header_hoge.tpl");
$objView->assign("footer_tpl", TEMPLATE_DIR . "footer_hoge.tpl");
|
全然どうでもいいんですがデフォルトのテンプレートに
<div id="fotter">
とか書いてあります。これはひどい。
EC-CUBEの記事
1
2
3
4
|
$this->arrPRODUCTLISTMAX =
$masterData->getMasterData("mtb_product_list_max");
$this->disp_number =
current(array_keys($this->arrPRODUCTLISTMAX));
|
という流れで取得されています。
mtb_product_list_maxには予め15、30、50の値が登録されており、なんとなくそこから選択することができそうな雰囲気に見えますが、それ以前の何処にもポインタを移動するような処理が無いので、このcurrent()は常時配列の一番上を返します。
つまり、常時15件のページャーとなります。
なにこの意味のわからない作り。
従って、表示件数を変更したい場合はシステム設定→マスタデータ管理からmtb_product_list_maxの一番上の15件を変更することになります。
下の30とか50とかは無意味な上にわかりにくくなって邪魔なので消してもかまいません。
EC-CUBEの記事
カテゴリID,カテゴリ名,親カテゴリID
1,親カテゴリ,
2,子カテゴリ1,1
3,子カテゴリ2,1
というCSVをアップすると、これまでの順序関係は壊れてしまうのですがとりあえずアップはできます。
一方、現在までのカテゴリを壊したくないので新しく追加しようと、
カテゴリID,カテゴリ名,親カテゴリID
1,親カテゴリ,
21,子カテゴリ1,1
22,子カテゴリ2,1
というCSVをアップしても何故か登録できません。
ログをよく見るとUPDATEとか書いてあります。
カテゴリはdtb_categoryに保存されますが、そこにcategory_id=21とかのものが存在しなくてもUPDATEになってしまいます。
中を見てみると、カテゴリIDのカラムに何か書いてあればUPDATE、何もなければINSERTになっていました。
/data/class/pages/admin/products/LC_Page_Admin_Products_UploadCSVCategory.phpの
LC_Page_Admin_Products_UploadCSVCategory::lfRegistProduct()で定義されています。
1
2
3
4
5
6
7
8
|
if ($arrRet['category_id'] == 0) {
$category_id = $objQuery->max("dtb_category", "category_id") + 1;
$sqlval['category_id'] = $category_id;
$update = false;
} else {
$sqlval['category_id'] = $arrRet['category_id'];
$update = true;
}
|
元々ここらへんはカテゴリ管理から手動登録→CSVをダウンロード→そのCSVを少々変更してアップロード、という流れを意図しているらしく、最初からカテゴリの一覧をCSVで作成してアップといった用途には向いていません。
どうしてもそこらへんを全部手動で管理したいんじゃ、任意のカテゴリIDを使用したいんじゃ、という場合はこのようにします。
1
2
3
4
5
6
7
8
9
10
11
12
13
|
if($arrRet['category_id']){
$sqlval['category_id'] = $arrRet['category_id'];
//使用済だったらUPDATE、無ければINSERT
if( $objQuery->count("dtb_category", "category_id = ?",
array($sqlval['category_id'])) > 0){
$update = true;
}else{
$update = false;
}
}else{
$sqlval['category_id'] = $objQuery->max("dtb_category", "category_id") + 1;
$update = false;
}
|
そのカテゴリIDが既に存在すればUPDATE、無ければINSERTとなります。
でも削除したくてCSVから消したしたはずのカテゴリがあったとしてもDBにはそのまま残り続けたりするので、最初にdtb_categoryをTRUNCATEしてから全部INSERTしたほうが手っ取り早いかもしれません。
まあ、dtb_category_countとかdtb_productsとかの関連を何も考えてないのでどこで不具合が出るかわかったものではありませんが。
ていうか、この、
$update = true;
とか作り的にもう少しどうにかならなかったのだろうか。
EC-CUBEの記事
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
|
<!-- ▼おすすめ情報 ここから-->
<!--{if count($arrBestProducts) > 0}-->
<div id="recomendarea">
<div class="title">おすすめ情報</div>
<!--{foreach from=$arrBestProducts key=cnt item=BestProducts name=loop}-->
<!--{if $smarty.foreach.loop.index is even }-->
<!--{* 2件毎に段落開始 *}-->
<div class="recomendblock">
<div class="recomendleft">
<!--{else}-->
<div class="recomendright">
<!--{/if}-->
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$BestProducts.product_id|escape}-->">
<img src="<!--{$smarty.const.SITE_URL}-->resize_image.php
?image=<!--{$BestProducts.main_list_image|sfRmDupSlash}-->
&width=48&height=48"
alt="<!--{$BestProducts.name|escape}-->" />
</a>
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$BestProducts.product_id|escape}-->">
<!--{$BestProducts.name|escape}-->
</a>
<p><!--{$BestProducts.comment|escape}--></p>
<!--{if ( ($smarty.foreach.loop.index is odd)
|| ($smarty.foreach.loop.last) ) }-->
<!--{* 2件毎、もしくは最後であれば段落終了 *}-->
</div>
</div>
<!--{else}-->
</div>
<!--{/if}-->
<!--{/foreach}-->
</div>
<!--{/if}-->
<!-- ▲おすすめ情報 ここまで-->
|
価格とか画像のあたりは端折ってる処理もありますが、たったこれだけでほぼ同等の機能を実現できます。
なんで倍以上の長さを使ってあんなわかりにくい作りにしてるんだろう。
なんかEC-CUBEのテンプレ作った人がやたらsection好きみたいで困る。
ロジックもやたらforが好きだし。foreach使えと。
↓ちなみに元のソース
cnt2の求め方のあたりが非常にださい。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
|
<!--▼おすすめ情報ここから-->
<!--{if count($arrBestProducts) > 0}-->
<div id="recomendarea">
<h2>
<img src="img/top/osusume.jpg" width="400" height="29" alt="おすすめ情報" />
</h2>
<!--{section name=cnt loop=$arrBestProducts step=2}-->
<div class="recomendblock">
<div class="recomendleft">
<!--{if $arrBestProducts[cnt].main_list_image != ""}-->
<!--{assign var=image_path
value="`$arrBestProducts[cnt].main_list_image`"}-->
<!--{else}-->
<!--{assign var=image_path value="`$smarty.const.NO_IMAGE_DIR`"}-->
<!--{/if}-->
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$arrBestProducts[cnt].product_id}-->">
<img src="<!--{$smarty.const.SITE_URL}-->resize_image.php
?image=<!--{$image_path|sfRmDupSlash}-->&width=48&height=48"
alt="<!--{$arrBestProducts[cnt].name|escape}-->" /></a>
<h3>
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$arrBestProducts[cnt].product_id}-->">
<!--{$arrBestProducts[cnt].name|escape}--></a>
</h3>
<!--{assign var=price01 value=`$arrBestProducts[cnt].price01_min`}-->
<!--{assign var=price02 value=`$arrBestProducts[cnt].price02_min`}-->
<p>価格<span class="mini">(税込)</span>:<span class="price">
<!--{if $price02 == ""}-->
<!--{$price01|sfPreTax:$arrInfo.tax:$arrInfo.tax_rule|number_format}-->
<!--{else}-->
<!--{$price02|sfPreTax:$arrInfo.tax:$arrInfo.tax_rule|number_format}-->
<!--{/if}-->円
</span>
</p>
<p class="mini"><!--{$arrBestProducts[cnt].comment|escape|nl2br}--></p>
</div>
<div class="recomendright">
<!--{assign var=cnt2
value=`$smarty.section.cnt.iteration*$smarty.section.cnt.step-1` }-->
<!--{if $arrBestProducts[$cnt2]|count > 0}-->
<!--{if $arrBestProducts[$cnt2].main_list_image != ""}-->
<!--{assign var=image_path
value="`$arrBestProducts[$cnt2].main_list_image`"}-->
<!--{else}-->
<!--{assign var=image_path value="`$smarty.const.NO_IMAGE_DIR`"}-->
<!--{/if}-->
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$arrBestProducts[$cnt2].product_id}-->">
<img src="<!--{$smarty.const.SITE_URL}-->resize_image.php
?image=<!--{$image_path|sfRmDupSlash}-->&width=48&height=48"
alt="<!--{$arrBestProducts[$cnt2].name|escape}-->" /></a>
<h3>
<a href="<!--{$smarty.const.URL_DIR}-->products/detail.php
?product_id=<!--{$arrBestProducts[$cnt2].product_id}-->">
<!--{$arrBestProducts[$cnt2].name|escape}--></a>
</h3>
<!--{assign var=price01 value=`$arrBestProducts[$cnt2].price01_min`}-->
<!--{assign var=price02 value=`$arrBestProducts[$cnt2].price02_min`}-->
<p>価格<span class="mini">(税込)</span>:<span class="price">
<!--{if $price02 == ""}-->
<!--{$price01|sfPreTax:$arrInfo.tax:$arrInfo.tax_rule|number_format}-->
<!--{else}-->
<!--{$price02|sfPreTax:$arrInfo.tax:$arrInfo.tax_rule|number_format}-->
<!--{/if}-->円</span>
</p>
<p class="mini"><!--{$arrBestProducts[$cnt2].comment|escape|nl2br}--></p>
<!--{/if}-->
</div>
</div>
<!--{/section}-->
</div>
<!--{/if}-->
<!--▲おすすめ情報ここまで-->
|
EC-CUBEの記事
EC-CUBEはSSLに対応しており、/install.phpのSSL_URLを書き換えるだけで、お問い合わせフォームなどをさっくりとSSL対応にすることができます。
デフォルトで用意されている利用ガイドブロックの、お問い合わせへのリンクも自動的にSSLサイト宛になります。
ではこれでお問い合わせフォームがSSL対応になってよかったよかった、かと思えばそんなことはありません。
公式の事例から適当に引っ張ってきたサイトですが、たとえばここ。
http://www.shimachunet.com/
右上の「お問い合わせ」をクリックするとSSLを使用した問い合わせフォームを利用することができます。
https://www.shimachunet.com/contact/index.php
で、なんとなくhttpsからsを外してみると、見事に問い合わせフォームに行けてしまいました。
http://www.shimachunet.com/contact/index.php
実際に送信までは行っていませんが、確認画面までは行けたのでおそらくそのまま送信できてしまうと思います。
問い合わせフォームを扱うファイルは/data/class/pages/contact/LC_Page_Contact.phpです。
LC_Page_Contact::init()あたりに
1
2
3
4
5
6
|
//SSLでなければSSLページに移動
if(strpos(SITE_URL,$_SERVER['SERVER_NAME'])!==false){
$this->sendRedirect($this->getLocation(
"./index.php", array(), true));
exit;
}
|
みたいなのを追加することでこの不具合を解消することができます。
まあ、最初から全部SSLオンリーにしてしまうのが一番手っ取り早い気もしますが。
EC-CUBEの記事
商品情報テーブルはdtb_productsですが、ここに適当に商品情報のカラムを追加したら商品リストですぐに表示できるかというとできません。
検索ブロックなどからの検索は/data/class/pages/products/LC_Page_Products_List.phpのLC_Page_Products_List::lfDispProductsList()で実行されています。
450行目あたり、▼商品詳細取得の部分で、検索対象となるカラムを羅列しています。
ここに追加したカラムを記入すると、表示できるようになるかというとシステムエラーになりました。
そこらへんの処理をよく見てみると、実はvw_products_allclassという得体の知れないテーブルから検索を行っています。
実際にデータベースを覗いてみてもvw_products_allclassは存在しません。
名前の通りvw_products_allclassはビューなのですが、MySQLの場合は何故か実際にビューを作成せずに、ビューに相当するSQL文を毎回作成して実行しているみたいです。
どうしてこんな作りなのかは謎。
実際にそのビュー的なSQLを作成しているところは
/data/class/db/dbfactory/SC_DB_DBFactory_MYSQL.phpのSC_DB_DBFactory_MYSQL::viewToSubQuery()です。
最初に$sql['vw_products_allclass_detail']を作成するところでdtb_products.***なんかがいっぱい並んでいますが、そこにカラムを追加することでようやくテンプレートから参照できるようになります。
このビューですが、なにやら尋常ではないJOINを行っていてとんでもなく訳がわからないことになっています。
どうしてこんな作りなのかは謎。