商城培訓內容
一、目錄結構(MVC模式)
(1)視圖(View)
存放在views文件夾下,主要存放顯示頁面的php文件
(2)模型(Model)
存放在models文件夾下,存放對數據庫表的操作方法
(3)控制(Controller)
存放在controllers文件夾下,存放控制方法。從用戶接受請求,講模型與視圖匹配在一起,共同完成用戶的請求。
(4)其他文件
config文件夾:存放商城的備置文件。例如數據庫文件(db.ini.php),備置文件(config.ini.php)等。
api文件夾:存放接口文件。例如快遞接口文件(logistic.php)。
static文件夾:存放css文件,js文件,圖片。
task文件夾:存放計劃任務文件。
二、查找文件
例子:根據 `http://shop.yuanfeng.com/index.php?ctl=Buyer_Cart&met=cart` 地址查找文件
`index.php` 是入口文件。
`ctl=Buyer_Cart` 控制器文件路徑 `shop/controllers/Buyer/CartCtl.php`
`met=cart` 是 `CartCtl.php` 中的`cart`方法。
public function cart(){
$data = $this->getCart();
$this->data->addBody(-140, $data);
if ($this->typ == 'json') {
$new_data = array();
$sum = 0;
$count = $data['count'];
unset($data['count']);
$new_data['count'] = $count;
$cart_list = array_values($data);
$new_data['cart_list'] = $cart_list;
if ( !empty($cart_list) ) {
foreach ($cart_list as $key => $val) {
foreach ($val['goods'] as $k => $v) {
$sum += $v['goods_num'] * $v['now_price'];
}
}
}
$new_data['sum'] = $sum;
$this->data->addBody(-140, $new_data);
}else{
include $this->view->getView();
}
}
$this->data->addBody(-140,$new_data); //返回數據
include $this->view->getView(); //加載頁面
}
如果是加載頁面,則頁面的路徑為 `shop/views/default/Buyer/CartCtl/cart.php`
在文件中有幾種表示路徑的方法:
<?=$this->view->js?>/cart.js //對應文件 shop/static/default/js/cart.js
<?= $this->view->js_com ?>/sppl.js //shop/static/common/js/sppl.js
<?= $this->view->css ?>/tips.css //shop/static/default/css/tips.css
<?=$this->view->img?>/mask.png //shop/static/default/images/mask.png
三、model方法(對數據表的操作)
例子:
shop/models/Cart.php
shop/models/CartModel.php
`Cart.php`與`CartModel.php`這兩個文件都是對購物車表進行操作的文件。Cart.php文件主要定義了增刪改查這四個方法。
<?php if (!defined('ROOT_PATH'))
{
exit('No Permission');
}
/**
*
*
* @category Framework
* @package __init__
* @author Yf <service@yuanfeng.cn>
* @copyright Copyright (c) 2010, 朱羽婷
* @version 1.0
* @todo
*/
class Cart extends Yf_Model
{
public $_cacheKeyPrefix = 'c|Cart|';
public $_cacheName = 'cart';
public $_tableName = 'cart';
public $_tablePrimaryKey = 'cart_id';
/**
* @param string $user User Object
* @var string $db_id 指定需要連接的數據庫Id
* @return void
*/
public function __construct(&$db_id = 'shop', &$user = null)
{
$this->_tableName = TABEL_PREFIX . $this->_tableName;
parent::__construct($db_id, $user);
}
/**
* @param int $config_key 主鍵值
* @return array $rows 返回的查詢內容
* @access public
*/
public function getCart($cart_id = null, $sort_key_row = null)
{
$rows = array();
$rows = $this->get($cart_id, $sort_key_row);
return $rows;
}
/**
* 插入
* @param array $field_row 插入數據信息
* @param bool $return_insert_id 是否返回inset id
* @param array $field_row 信息
* @return bool 是否成功
* @access public
*/
public function addCart($field_row, $return_insert_id = false)
{
$add_flag = $this->add($field_row, $return_insert_id);
//$this->removeKey($config_key);
return $add_flag;
}
/**
* 根據主鍵更新表內容
* @param mix $config_key 主鍵
* @param array $field_row key=>value數組
* @return bool $update_flag 是否成功
* @access public
*/
public function editCart($cart_id = null, $field_row = array(), $flag = true)
{
$update_flag = $this->edit($cart_id, $field_row, $flag);
return $update_flag;
}
public function editCartNum($cart_id = null, $field_row = array())
{
$update_flag = $this->edit($cart_id, $field_row);
return $update_flag;
}
/**
* 更新單個字段
* @param mix $config_key
* @param array $field_name
* @param array $field_value_new
* @param array $field_value_old
* @return bool $update_flag 是否成功
* @access public
*/
public function editCartSingleField($cart_id, $company)
{
$update_flag = $this->editSingleField($cart_id, $company);
return $update_flag;
}
/**
* 刪除操作
* @param int $config_key
* @return bool $del_flag 是否成功
* @access public
*/
public function removeCart($cart_id)
{
$del_flag = $this->remove($cart_id);
//$this->removeKey($config_key);
return $del_flag;
}
}
?>
*商城中只能單表查詢,不能多表聯查。
*`Cart.php`只寫最基本的增刪改查方法,最好不要把其他的方法寫入這個文件。
* editCart方法中的第3個參數表示的是修改數字符號為“+=” 還是“=”,例如editCart(1,array(goods_num=>3),true)),表示的是goods_num = goods_num + 3。editCart(1,array(goods_num=>3),false)),表示的是goods_num = 3。
幾種經常使用的查找方法
`listByWhere` 返回帶分頁的數據
`getOne` 根據主鍵查找數據
`getByWhere` 根據條件查找數據
更多方法可以在`libraries/Yf/Model.php`中查找。
四、controller方法
例子:獲取當前用戶的購物車數據
地址為:`http://shop.bbc-builder.com/index.php?ctl=Buyer_Cart&met=cart`
CartCtl.php中定義的cart方法上面已經寫出。其中`$data = $this->getCart();`的getCart()方法如下:
/**
* 獲取購物車列表
*
* @author Zhuyt
*/
public function getCart()
{
$user_id = Perm::$row['user_id'];
$Goods_BaseModel = new Goods_BaseModel();
$cord_row = array();
$order_row = array();
$cond_row = array('user_id' => $user_id);
$order_row['cart_id'] = 'DESC';
$data = $this->cartModel->getCardList($cond_row, $order_row);
foreach ($data as $key => $value) {
$goods_detail = $Goods_BaseModel->getGoodsDetailInfoByGoodId($value['goods'][0]['goods_id']);
if (!empty($goods_detail['common_base']['common_spec_name'])) {
//商品規格顏色圖
if (!empty($goods_detail['common_base']['common_spec_value_color'])) {
$data[$key]['goods'][0]['goods_base']['goods_image'] = $goods_detail['common_base']['common_spec_value_color'][$value['goods'][0]['goods_base']['color_id']];
}
}
}
if ($data) {
$status = 200;
$msg = __('success');
} else {
$status = 250;
$msg = __('failure');
}
$this->data->addBody(-140, $data, $msg, $status);
return $data;
}
使用model方法先實例化對象。
$this->cartModel = new CartModel();
獲取數據后根據實際需求決定是返回數據還是加載頁面。
五、view中顯示數據
例子:購物車頁面
<div class="cart_goods">
<ul class='cart_goods_head clearfix'><li class="done"><?=_('操作')?></li>? <li class="price_all"><?=_('小計')?>(<?=(Web_ConfigModel::value('monetary_unit'))?>)</li>? <li class="goods_num"><?=_('數量')?></li>? <li class="goods_price"><?=_('單價')?>(<?=(Web_ConfigModel::value('monetary_unit'))?>)</li>? <li class="goods_name"><?=_('商品')?></li>? <li class="cart_goods_all cart-checkbox " style="float:left;"><input class="checkall" type="checkbox" data-type="all"><div class="select_all"><?=_('全選')?></div></li>? </ul>? <form id="form" action="?ctl=Buyer_Cart&met=confirm" method='post'>? <ul class="cart_goods_list clearfix">? <?php foreach($data as $key=>$val){?>? <li class="carts_content">? <div class="bus_imfor clearfix">? <p class="bus_name">? <input class="checkshop checkitem" type="checkbox" data-type="all">? <span><i class="iconfont icon-icoshop"></i><a href="<?= Yf_Registry::get('url') ?>?ctl=Shop&met=index&id=<?=($key)?>"><?=($val['shop_name'])?></a></span>? </p>? </div>? <table id="table_list" class="table_list">? <tbody class="rel_good_infor">? <?php foreach($val['goods'] as $k=>$v){ ?>? <tr class="row_line">? <td class="goods_sel cart-checkbox">? <p>? <input class="checkitem" type="checkbox" name="product_id[]" value="<?=($v['cart_id'])?>" <?php if($v['IsHaveBuy']){?>disabled="" title="您已達限購數量" <?php }?> >? </p>? </td>? <td class="goods_img"><img src="<?=($v['goods_base']['goods_image'])?>"/></td>? <td class="goods_name_reset">? <a target="_blank" href="<?= Yf_Registry::get('url') ?>?ctl=Goods_Goods&met=goods&gid=<?=($v['goods_base']['goods_id'])?>"><?=($v['goods_base']['goods_name'])?></a>?? <?php if(isset($v['goods_base']['promotion_type'])): ?>? <p class="sal_price">? <?php if($v['goods_base']['promotion_type'] == 'groupbuy' && $v['goods_base']['down_price']): ?>? <?=_('團購,直降:')?><?=format_money($v['goods_base']['down_price'])?>? <?php endif;?>?? <?php if($v['goods_base']['promotion_type'] == 'xianshi' && $v['goods_base']['down_price']): ?>? <?=_('限時折扣,直降:')?><?=format_money($v['goods_base']['down_price'])?>? <?php endif;?>? </p>? <?php endif; ?>???? <p>? <?php if(!empty($v['goods_base']['spec'])){foreach($v['goods_base']['spec'] as $sk => $sv){ ?>? <?=($sv)?> ? <?php }}?>? </p>??? </td>?? <td class="goods_price">? <?php if($v['old_price'] > 0){?><p class="ori_price"><?=($v['old_price'])?></p><?php }?>? <p class="now_price"><?=($v['now_price'])?></p>? </td>? <td class="goods_num">? <?php? if($v['buy_limit'] && !$v['IsHaveBuy'])? {? $data_max = $v['buy_residue'];? }? else? {? $data_max = $v['goods_base']['goods_stock'];? }? ?>? <a class="<?php if($v['goods_num'] == 1){?>no_<?php }?>reduce" ><?=_('-')?></a><input id="nums" data-id="<?=($v['cart_id'])?>" data-max="<?=($data_max)?>" value="<?=($v['goods_num'])?>"><a class="<?php if($data_max <= 1){?>no_<?php }?>add" ><?=_('+')?></a>? </td>? <td class="price_all cell<?=($v['cart_id'])?>">? <span class="subtotal"><?=($v['sumprice'])?></span>? </td>? <td class="done del"><a data-param="{'ctl':'Buyer_Cart','met':'delCartByCid','id':'<?=($v['cart_id'])?>'}"><?=_('刪除')?></a></td>? </tr>? <?php }?>? </tbody>? </table>? </li>? <?php }?>? </ul>? </form>?</div>
五、其他
(1)在shop中調用其他項目的方法 `get_url_with_encrypt`
定義方法的文件:`libraries\__init__.php`
//可以判斷請求時間是否超過某個期限
function get_url_with_encrypt($key, $url, $formvars = array(), $typ = 'JSON', $method = 'POST')
{
$formvars['rtime'] = get_time();
$hash_row = $formvars;
array_multiksort($hash_row, SORT_STRING);
$hash_row['key'] = $key;
$tmp_str = http_build_query($hash_row);
Yf_Log::log('$tmp_str:' . $tmp_str, Yf_Log::INFO, 'get_url_with_encrypt');
Yf_Log::log('$url:' . $url, Yf_Log::INFO, 'get_url_with_encrypt');
$formvars["token"] = md5($tmp_str);
Yf_Log::log($hash_row, Yf_Log::INFO, 'get_url_with_encrypt');
Yf_Log::log($formvars, Yf_Log::INFO, 'get_url_with_encrypt');
$rs = get_url($url, $formvars, $typ, $method);
Yf_Log::log($rs, Yf_Log::INFO, 'get_url_with_encrypt');
return $rs;
}
例如:
在shop中調用paycenter中的用戶信息。
//會員的錢
$key = Yf_Registry::get('shop_api_key');
$formvars = array();
$user_id = Perm::$userId;
$formvars['user_id'] = $user_id;
$formvars['app_id'] = Yf_Registry::get('shop_app_id');
$money_row = get_url_with_encrypt($key, sprintf('%sindex.php?ctl=Api_User_Info&met=getUserResourceInfo&typ=json',
Yf_Registry::get('paycenter_api_url')), $formvars);
在shop中驗證接口合法性的方法`check_url_with_encrypt`
定義方法的文件:`libraries\__init__.php`
function check_url_with_encrypt($key, $formvars = array())
{
Yf_Log::log($formvars, Yf_Log::INFO, 'check_url_with_encrypt');
$token = $formvars['token'];
unset($formvars['token']);
$hash_row = $formvars;
array_multiksort($hash_row, SORT_STRING);
$hash_row['key'] = $key;
$tmp_str = http_build_query($hash_row);
Yf_Log::log('$tmp_str:' . $tmp_str, Yf_Log::INFO, 'check_url_with_encrypt');
Yf_Log::log('md5-key:' . md5($tmp_str), Yf_Log::INFO, 'check_url_with_encrypt');
//可以判斷請求時間是否超過某個期限, 1分鐘內
if ((get_time() - $hash_row['rtime'] < 60000) && $token == md5($tmp_str)) {
return true;
} else {
return false;
}
}
例如:`shop\controllers\Api\Controller.php`
if (!check_url_with_encrypt($key, $data)){
$this->data->setError(__('API接口有誤,請確保APP KEY及APP ID正確'), 301); $d = $this->data->getDataRows();
$protocol_data = Yf_Data::encodeProtocolData($d);
echo $protocol_data; exit();
}
底層防SQL注入:
/**
* 轉義字符函數
*
* @param mixed $content contents should be addslashes
*
* @return mixed $content
*
*/
function quotes(&$content)
{
if (is_array($content)) {
foreach ($content as $key => $value) {
$content[$key] = quotes($value);
}
} else {
$content = addslashes($content);
}
return $content;
}
在`libraries\Yf\Model.php`文件的174行
$value = htmlspecialchars($value);
驗證否登錄方法在該模塊下的控制器里controllers=>plugin 文件夾下Perm.php
添加免驗證登錄的控制器文件在此添加(一般用于未登錄下的數據顯示獲取)
public function checkPerm()
{
$data = new Yf_Data();
//無需權限判斷的文件
$not_perm = array(
'Upload',
'Login',
'Api',
'ImApi',
'Index',
'Base_District',
'Connect_Qq',
'Connect_Weixin',
'Connect_Weibo',
'Transport',
'Shop',
'GroupBuy',
'Points',
'Voucher',
'Article_Base',
'Shop_Index',
'RedPacket',
'Supplier_Index',
'Supplier_Goods',
'PinTuan',
'Qr',
'Informationlist',
'Webconfig',
'Explore_UnExplore',
'Bargain_UnBargain',
'WxPublicTool_Index',
'Bill',
'Special_Column',
'WxPublicTool_SellerWx',
'Common',
'Distribution_NewBuyer_UploadWap',
'Distribution_NewBuyer_Goods',
'WeChatCs_Index',
'Test',
'Live',
'Shop_GoodsCat',
'Seller_Trade_Order',
'QiShou_Base',
'QiShou_Cash',
'QiShou_Evaluation',
'QiShou_Income',
'QiShou_Info',
'UploadAlbum',
'Api_Album',
);
//不需要登錄
if (!isset($_REQUEST['ctl']) || (isset($_REQUEST['ctl']) && in_array($_REQUEST['ctl'], $not_perm)) || (isset($_REQUEST['ctl']) && 'Api_' == substr($_REQUEST['ctl'], 0, 4)) || (isset($_REQUEST['ctl']) && 'WebPosApi_' == substr($_REQUEST['ctl'], 0, 10)) || (isset($_REQUEST['ctl']) && 'Goods_' == substr($_REQUEST['ctl'], 0, 6)) ||(in_array($_REQUEST['ctl'],$GLOBALS['extends_ini'])))
{
if (Perm::checkUserPerm())
{
}
}
elseif (Perm::checkUserPerm())
{
}
else
{
// Perm::removeUserInfo();
if ('e' == $_REQUEST['typ'])
{
$url = Yf_Registry::get('url') . '?ctl=Login&met=login&typ=e';
if (request_string('forward_self'))
{
//$forward = '&forward=//:' . $_SERVER['HTTP_HOST'] . urlencode($_SERVER['REQUEST_URI']);
$forward = '&forward=' . urlencode('http://' . $_SERVER['HTTP_HOST'] . $_SERVER['REQUEST_URI']);
$forward = str_replace('forward_self', 'x_self', $forward);
$url = $url . $forward;
}
else
{
if (isset($_SERVER['HTTP_REFERER']))
{
$forward = '&forward=' . urlencode($_SERVER['HTTP_REFERER']);
$url = $url . $forward;
}
}
location_to($url);
}
else
{
if('json' == $_REQUEST['typ'] && Perm::checkUserPerm())
{
}
else
{
$data->setError(__('需要登錄'), 30);
return $this->outputError($data);
}
}
}
}
日志添加文件在開發過程中對于特定節點進行日志監控通過此方法提添加
```
$arra指要記錄的數據
$log_name指要添加的日志名稱
Yf_Log::log($array, Yf_Log::INFO, $log_name);
```
操作日志則是在controllers=>plugin 文件夾下的log.php添加
public function addLog()
{
//同步,直接操作日志數據庫
if (true || isset($ccmd_rows[$_REQUEST['ctl']][$_REQUEST['met']]['log']))
{
$Yf_Registry = Yf_Registry::getInstance();
$ccmd_rows = $Yf_Registry['ccmd_rows'];
$rights_id = @$ccmd_rows[$_REQUEST['ctl']][$_REQUEST['met']]['rid'];
$data = array();
if (Perm::$login)
{
$data['user_id'] = Perm::$row['user_id']; // 玩家Id
$data['user_account'] = Perm::$row['user_account']; // 角色賬戶
//$data['user_name'] = Perm::$row['user_realname'] ; // 角色名稱
}
else
{
}
$data['action_id'] = $rights_id; // 行為id == protocal_id -> rights_id
$data['log_param'] = $_REQUEST; // 請求的參數,|| 詳細數據,可以通過controller結束賦值全部變量來或獲取
$data['log_ip'] = get_ip(); //
$logActionModel = new Log_ActionModel();
$log_id = $logActionModel->addAction($data, true);
}
//異步,隊列操作
}
- 序言
- 系統要求
- 版本更新日志
- 遠豐商城技術對接說明
- 開發指導
- 系統架構
- 負載集群
- 云存儲
- 框架內容
- 基礎
- 開發規范
- 目錄結構
- 架構
- 架構總覽
- 數據庫
- 數據庫連接
- 基本使用
- 緩存
- 配置
- 路由
- 數據字典
- ucenter
- shop
- paycenter
- ucenter_admin
- shop_admin
- paycenter_admin
- shop1
- shop2
- shop3
- 通訊內容
- 商家中心
- 頂部導航欄
- 店鋪信息欄
- 店鋪及商品提示欄
- 交易提示欄
- 銷售情況統計欄
- 集群架構圖
- 單品銷量排行欄
- 店鋪運營推廣欄
- 平臺聯系方式欄
- 訂單物流
- 商品
- 商品列表
- 商品詳情
- 商品發布與編輯
- 分銷商品
- 關聯版式
- 商品規格
- 圖片空間
- 淘寶導入
- 訂單流程
- 交易訂單
- 訂單退款/退貨
- 促銷
- 團購管理
- 加價購
- 限時折扣
- 滿即送
- 代金券管理
- 分銷
- 店鋪
- 店鋪設置
- 自銷產品供應商
- 實體店鋪
- 品牌申請
- 店鋪信息
- 消費者保障服務
- 門店賬號
- 分銷商--產品供應商
- 分銷明細
- 批發市場
- 商家微信公眾號
- 售后服務
- 咨詢管理
- 投訴管理
- 退款管理
- 退貨管理
- 雜項
- 遠程上傳圖片
- 接口(廢棄,參考最外層接口項)
- 接口說明
- 品牌
- 商品規格
- 商品類型
- 商品分類
- 商品
- 訂單
- 商品/店鋪收藏
- 足跡
- 退款及退貨
- 商家店鋪
- 會員
- 入駐協議
- 訂單接口
- 商品接口
- 訂單物流接口
- 商家中心接口
- 促銷接口
- 快遞鳥物流接口
- 代金券接口
- 首頁版塊
- 團購
- 平臺紅包
- 限時折扣接口
- 拼團接口
- wap首頁模板
- JS
- 銀聯支付
- 多語言
- 商品評分
- 圖片加載
- 買家申請退款退貨
- 商家退款退貨
- 平臺退款退貨
- 添加發票
- 提交訂單
- 確認訂單
- 運費銷售區域
- 獲取會員地址
- 充值
- 導出XLS
- 商城系統集成
- 多語言實現
- 三級分銷推廣鏈接發展推廣員
- app.ini.php
- 去分銷
- 版本更新
- 物流支持
- 運營人員建議
- 業務邏輯
- 統計結算
- 客服消息
- 賬號
- 三級分銷
- IM
- 配置
- 平臺帳號
- 活動數據表說明
- 接口
- 數據庫中間鍵
- MyCat的優勢
- 概念說明
- Mycat的下載及安裝
- 參數配置案列
- Mycat讀寫分離
- 基本命令
- 常見錯誤