1. 程式人生 > >ecmall 學習記錄

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]."&nbsp;".($msg[2]+3).",".$msg[3];
		},
		$string


	)    //輸出 April 18,2003
2017/7/10