ecmall 學習記錄
1.
/* 載入配置項 */
$setting =& af(MODULE);
Conf::load($setting->getAll());
af方法定義如下:
/** * 獲取陣列檔案物件 * * @author Garbin * @param string $type * @param array $params * @return void */ function &af($type, $params = array()) { static $types = array(); if (!isset($types[$type])) { /* 載入資料檔案基礎類 */ include_once(ROOT_PATH . '/includes/arrayfile.base.php'); include(ROOT_PATH . '/includes/arrayfiles/' . $type . '.arrayfile.php'); $class_name = ucfirst($type) . 'Arrayfile'; $types[$type] = new $class_name($params); } return $types[$type]; }
其實就是載入了兩個檔案,然後返回了一個例項化的物件,上面載入配置項 af 傳參的MODULE是指當前模組的名字,
關於af方法 註釋說是沒有返回值,但是下面return的是一個物件,af裡引入了兩個類檔案,其實,例項化的就是basearrayfile這個物件,因為引入的類檔案裡繼承的這個basearrayfile物件,然後呼叫裡面的方法獲取配置資訊,至於什麼時候要獲取配置資訊,就要看專案需求了,比如,會員年費有可能是100,也有可能是200,這個時候不能在程式裡寫死,所以要在配置檔案裡配置,這樣要改的話就改配置檔案,就不用改程式程式碼了,通過查詢配置檔案,就可以得到修改後的價格。配置檔案在data目錄下名為XXX..inc.php.
m 例項化模型物件,這個是最常用的 也就相當於TP框架裡的直接例項化一張表,可以對錶的內容進行增刪查改。
bm 例項化的是業務物件,也就是繼承自模型物件(m方法例項化的),不過邏輯相對複雜,就抽象出來行成業務物件,進行業務邏輯處理,也會有增刪改查,業務多的時候需要邏輯分層,這個時候用bm,(可以參考線上商城的goods.model.php)我還是不太懂,大腿畢竟是大腿,等過幾年接觸的東西多了,業務實現的多了,說不定我就懂了......此處應該有表情,可是這個編輯器沒有,我能怎麼辦呢,我也很無奈。
2017.6.9
關於ecmall的模組開發
什麼時候用到模組開發? 一個新的專案需求,需要分析,經常用的是直接寫控制器 也就是在專案資料夾下的app裡寫前臺控制器,在admin/app裡寫後臺控制器。
開發過程中,常用的就是直接在app目錄下寫控制器,適用於簡單的需求,可快速開發,擴充套件性較差,相應的功能在後臺需要新增相應的選單。
開發模組適用於較大,較為複雜的專案需求,模組的擴充套件性較好,模組開發也要寫前後臺模組,後臺擴充套件裡可以進行模組的管理。
關於模組開發和直接寫控制器,在邏輯上,業務上沒有區別,只是不同的做法而已,module比較容易擴充套件,app比較容易開發。
模組訪問就是 index.php?module=XX&act=XXX
直接寫控制器的訪問就是 index.php?app=XX&act=XXX
關於ecmall的模版
前臺模版是在專案目錄下的themes 裡面分為mall 和store 。mall 是商城模版,store是店鋪模版。至於控制器引入上傳模版還是店鋪模版就看繼承的父類了,繼承mallbase的就引入mall,繼承storebase就引入store。
2017.6.12
1.ecmall 自帶的寫入日誌方法:do_log4php("函式名","類名",$param); $param是引數
在類裡呼叫寫入之日的方法 需要先載入函式工具庫 import('functions.lib');
生成的日誌存在於 temp/logs。
配置路徑就在 log4php.properties檔案中,這個檔案就在專案根目錄下,找不到的話可以用everything找一下。
2.ecmall 引入微信jsssdk類庫 import('檔名'); ecmall 引入微信類庫;ecmall生成微信簽名
判斷是否為微信端:
function isWeixin()
{
if ( strpos($_SERVER['HTTP_USER_AGENT'], 'MicroMessenger') !== false ) {
return true;
}
return false;
}
獲取微信簽名:
/*start@author:hans@date:20160718*/
//引入微信授權
if( isWeixin() ){
import('weixinsdk');
import('functions.lib');
$weixin_config = require_once('data/weixin_config.php');
$jssdk = new JSSDK($weixin_config['appId'], $weixin_config['appSecret']);
$signPackage = $jssdk->GetSignPackage();
//do_log4php("display","FrontendApp",$signPackage);
$this->assign('wxsignPackage',$signPackage);
}
/*end@author:hans@date:20160718*/
3.後臺一級選單設定有個開啟偽靜態,開了和不開的區別很大,測試系統上沒有開,線上開了,所以店鋪分享可以正常用。
4.關於JS-SSDK中獲得微信簽名方法的修改
//地址沒有入口檔案 2017615 xiaolu
if (empty($request_uri)){ //沒有入口檔案的時候request_uri是為空的 列印一下$_SERVER 就知道該用什麼啦
$request_uri=$_SERVER['REQUEST_URI'];
}
if (strpos($_SERVER['REQUEST_URI'],"from=")){ //如果是從分享的地址進來的,會有from
$request_uri=$_SERVER['REQUEST_URI'];
}
//end
$url = "$protocol$_SERVER[HTTP_HOST]$request_uri";
$timestamp = time();
$nonceStr = $this->createNonceStr();
這個是針對功能需求進行的修改。
5. 個人中心:member.app.php index() $this->_curitem('overview'); //這個方法呼叫了_get_member_menu() 選單資料就是從這裡拿到的
個人中心的選單在 frontend.base.php裡的 _get_member_menu()方法中以陣列的形式定義的
6.$user = $this->visitor->get();獲取使用者資訊
$this->visitor->呼叫的方法 在ecapp.base.php裡 訪問者基礎類 class BaseVisitor extends Object 中,訪問者基礎類,集合了當前訪問使用者的操作。
2017-7-4
1.在ecmall.php 中 336行有一個函式
function lang_file($file)
{
return ROOT_PATH . '/languages/' . LANG . '/' . $file . '.lang.php';
}
這個是函式不在LANG 類中。函式可以直接用。類的函式也叫成員方法,不能在類外直接呼叫,要例項化類。
ecmall.php中 有四個類:ecmall,object,lang,conf,其他的還有系統常量,相容配置,主要的還是 函式方法。
2.conf 類 (跟配置相關)
/**
* 載入配置項
*
* @author Garbin
* @param mixed $conf
* @return bool
*/
function load($conf)
{
$old_conf = isset($GLOBALS['ECMALL_CONFIG']) ? $GLOBALS['ECMALL_CONFIG'] : array();
if (is_string($conf))
{
$conf = include_once($conf);
}
if (is_array($old_conf) && is_array($conf))
{
$GLOBALS['ECMALL_CONFIG'] = array_merge($old_conf, $conf);
}
else
{
$GLOBALS['ECMALL_CONFIG'] = $conf;
}
}
/**
* 獲取配置項
*
* @author Garbin
* @param string $k
* @return mixed
*/
static function get($key = '')
{
$vkey = $key ? strtokey("{$key}", '$GLOBALS[\'ECMALL_CONFIG\']') : '$GLOBALS[\'ECMALL_CONFIG\']';
return eval('if(isset(' . $vkey . '))return ' . $vkey . ';else{ return null; }');
}
一般用到載入配置項,都是 先 load 再 get 。
load() 就是將 配置檔案賦值給全域性變數 $GLOBALS['ECMALL_CONFIG']
get() 就通過鍵 來獲取在load()中剛剛被賦值的 $GLOBALS['ECMALL_CONFIG'] 中對應鍵的值。
小例子:
控制器程式碼:
goods.inc.php中的部分配置:
在控制器中載入配置項:
load()傳參是字串,也就是引入了配置項並且賦值給了全域性變數$GLOBALS['ECMALL_CONFIG'];
然後在呼叫get方法 載入鍵為category_good_num對應的值。 從而獲得商品配置。
2017-7-7.點滴知識,重在積累。
---------------------------華麗的分隔線--------------------------------------
1.ecmall.php中的
import()函式:
function import()
{
$c = func_get_args();
if (empty($c))
{
return;
}
array_walk($c, create_function('$item, $key', 'include_once(ROOT_PATH . \'/includes/libraries/\' . $item . \'.php\');'));
}
func_get_args() 將傳給當前函式所有的引數 組成 牽引 陣列 並返回:
function foo() { // returns an array of all passed arguments
$args = func_get_args();
foreach ($args as $k => $v) {
echo “arg”.($k+1).”: $v\n”;
}
}
foo(); /* 沒用任何輸出*/
foo(‘hello’); /* 輸出 arg1: hello */
foo(‘hello’, ‘world’, ‘again’); /*輸出 arg1: hello arg2: world arg3: again */
現在舉個例子 (=_=)
import("function.lib"); //呼叫上面的引入類函式
// 然後 function_get_args() 返回的是
// array(1) { [0]=> string(12) "function.lib" }
// 接著 create_function()建立了一個新函式: 有兩個引數$item和$key,方法體是 :
// include_once(ROOT_PATH . \'/includes/libraries/\' . $item . \'.php\');
// 即引入 根目錄下指定路徑裡的 $item.php檔案 //然後 array_walk($c,areate_function(...))
// array_walk()作用就是 將第一個引數$c(陣列) 遍歷迴圈,$c 的每一個值都傳到creat_function 中執行一次。
// 根據上面$c只有一個鍵值對, 那麼,import("functions.lib")執行的結果就是引入了 專案根目錄/includes/libraries/functions.lib.php
原來以為import()是把整個專案目錄遍歷查詢同名檔案引進來,還琢磨著萬一有了同名檔案怎麼辦,直到看了類庫才知道,同名檔案的想法是有多蠢(→_→)
2.ecmall 適配php5.5 需要用到的 preg_replace_callback()函式:
<?php
// 將文字中的年份增加一年.
$text = "today is 04/01/2002\n";
function next_year($matches)
{
// 通常: $matches[0]是完成的匹配
// $matches[1]是第一個捕獲子組的匹配
// 以此類推
return $matches[1].($matches[2]+1);
}
echo preg_replace_callback(
"|(\d{2}/\d{2}/)(\d{4})|",
"next_year",
$text);
?>
一個例子,定義$text,定義了回撥函式next_year,呼叫preg_replace_callback()
第一個引數:正則表示式,第二個是引數是回撥函式,最好是直接將函式寫進來,第三個是要進行匹配的字串。
在next_year中列印 $matches:
array(3) { [0]=> string(10) "04/01/2002" [1]=> string(6) "04/01/" [2]=> string(4) "2002" }
為什麼會分成04/01 和 2002 呢?
這和正則表示式有關係:(\d{2}/\d{2}/)(\d{4}) 第一對()就是$matches[1]。也叫做第一個捕獲子組的匹配,第二對()就是$matches[2];
通常: $matches[0]是完成的匹配 , $matches[1]是第一個捕獲子組的匹配 , 以此類推
然後會執行年份加一,並且將結果返回。先看最終結果: today is 04/01/2003
修改next_year的ruturn 語句為 $matches[1]."------".($matches[2]+1);
再進行輸出,結果為today is 04/01/------2003
這樣看來,preg_replace_callback('匹配表示式a','回撥函式b',‘需要匹配的內容c’)就是 將 c 在 a 中匹配到的 內容 d 替換 成 經過 b 處理後的 d 最終返回處理後的 c。
在preg_replace_callback()中傳入 回撥函式 b 的 $matches 是陣列的形式,要用下標【1】【2】(我是這麼理解的 = =) 在正則表示式中 \1 \2 同樣是指 第一個捕獲子組 第二個捕獲子組
在model.app.php中 //$fields = preg_replace('/([a-zA-Z0-9_]+)\.([a-zA-Z0-9_*]+)/e', "\$this->_getFieldTable('\\1') . '.\\2'", $fields); 這裡的'\\1'. '.\\2' 就是指第一,第二個捕獲子組的匹配,用了轉義符號 \ 。
也就是這樣:
<?php
// 將文字中的年份增加一年.
$text = "today is 04/01/2002\n";
// echo preg_replace_callback(
// "|(\d{2}/\d{2}/)(\d{4})|",
// function ($matches)
// {
// return $matches[1].($matches[2]+1);
// },
// $text);
echo preg_replace('|(\d{2}/\d{2}/)(\d{4})|', "\\1 ----\\2", $text); //在這裡 加 1, 我試了半天也沒加成功,難道是被拋棄了?
?>
輸出結果是:today is 04/01/ ----2002 同樣也是 用 \1 ----\2 (這裡我把轉義符去掉了)來替換了已經匹配到的內容,現在這個函式好像不太用了,都用preg_replace_callback()
上面可以寫成這樣:
<?php
// 將文字中的年份增加一年.
$text = "today is 04/01/2002\n";
echo preg_replace_callback(
"|(\d{2}/\d{2}/)(\d{4})|",
function ($matches)
{
return $matches[1].($matches[2]+1);//新的日月年來替換文字內被匹配的內容
},
$text);
?>
執行結果是一樣的。
測試:
$string = 'April 15, 2003' ;
$pattern = '/(\w+) (\d+), (\d+)/i' ;
$replacement = '\\1 18,\\3';
echo preg_replace ( $pattern , $replacement , $string ); //輸出 April 18,2003
修改後:
$string = 'April 15, 2003' ;
$pattern = '/(\w+) (\d+), (\d+)/i' ;
echo preg_replace_callback(
$pattern,
function($msg){
return $msg[1]." ".($msg[2]+3).",".$msg[3];
},
$string
) //輸出 April 18,2003
2017/7/10