opencart源码解析之 index.php
//访问index.php,安全过滤、加载配置文件、核心启动文件、函数库、类库
//转载请注明: http://blog.csdn.net/dabao1989/article/details/21223585
//new注册表
$registry = new Registry(); //$registry里保存的config是根据当前店店铺(`oc_store`)获取`store_id`,然后到`oc_setting`里取出该店的配置信息,跟配置文件config.php无关
$query = $db->query("SELECT * FROM " . DB_PREFIX . "setting WHERE store_id = '0' OR store_id = '" . (int)$config->get('config_store_id') . "' ORDER BY store_id ASC");
foreach ($query->rows as $setting) {
if (!$setting['serialized']) {
$config->set($setting['key'], $setting['value']);
} else {
$config->set($setting['key'], unserialize($setting['value']));
}
} //依次new核心类,压入$registry,最后几个类需要当前$registry作为参数,new之后再重新压入$registry
$registry->set('customer', new Customer($registry)); //new Front();加载前置Action
$controller = new Front($registry);
$controller->addPreAction(new Action('common/seo_url'));
$controller->addPreAction(new Action('common/maintenance')); //根据当前URL,加载指定Action,默认加载Action('common/home');
if (isset($request->get['route'])) {
$action = new Action($request->get['route']);
} else {
$action = new Action('common/home');
} //new Action()所进行的操作,根据URL路由,判断是否是一个控制器文件,如果是,break
//保存此控制器文件路径、当前需要执行的方法、参数等,假如方法名为空则要执行的方法名保存为index
function __construct($route, $args = array()) {
$path = ''; $parts = explode('/', str_replace('../', '', (string)$route)); foreach ($parts as $part) {
$path .= $part; if (is_dir(DIR_APPLICATION . 'controller/' . $path)) {
$path .= '/'; array_shift($parts); continue;
} if (is_file(DIR_APPLICATION . 'controller/' . str_replace(array('../', '..\\', '..'), '', $path) . '.php')) {
$this->file = DIR_APPLICATION . 'controller/' . str_replace(array('../', '..\\', '..'), '', $path) . '.php'; $this->class = 'Controller' . preg_replace('/[^a-zA-Z0-9]/', '', $path); array_shift($parts); break;
}
} if ($args) {
$this->args = $args;
} $method = array_shift($parts); if ($method) {
$this->method = $method;
} else {
$this->method = 'index';//默认index
}
} //Front执行控制器, 先执行之前压入的前置控制器, 然后执行当前请求的控制器, 失败则执行控制器error/not_found
//前置控制器有seo_url,maintenance,后台应该可配置SEO,可能会根据SEO创建新的控制器并返回,覆盖,执行
//Front->dispatch()会调用$this->execute()执行控制器
//execute()内部通过调用is_callable()判断控制器方法是否可以调用,所以可以在子Controller中将index()定义为protected,防止直接调用
//当直接调用时child Controller中的protected方法时,将会转到error/not_found
$controller->dispatch($action, new Action('error/not_found'));
function dispatch($action, $error) {
$this->error = $error; foreach ($this->pre_action as $pre_action) {
$result = $this->execute($pre_action); if ($result) {
$action = $result;//重置 break;
}
} while ($action) {
$action = $this->execute($action);
}
}
function execute($action) {
if (file_exists($action->getFile())) {
require_once($action->getFile()); $class = $action->getClass(); $controller = new $class($this->registry); if (is_callable(array($controller, $action->getMethod()))) {
$action = call_user_func_array(array($controller, $action->getMethod()), $action->getArgs());
} else {
$action = $this->error;//当不可用时,会调用$this->error $this->error = '';
}
} else {
$action = $this->error; $this->error = '';
} return $action;
} //假设执行的控制器是common/home, 没有指定方法, 则执行index()
class ControllerCommonHome extends Controller {
public function index() {
$this->document->setTitle($this->config->get('config_title'));
$this->document->setDescription($this->config->get('config_meta_description')); $this->data['heading_title'] = $this->config->get('config_title'); if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/common/home.tpl')) {
$this->template = $this->config->get('config_template') . '/template/common/home.tpl';
} else {
$this->template = 'default/template/common/home.tpl';
} $this->children = array(
'common/column_left',
'common/column_right',
'common/content_top',
'common/content_bottom',
'common/footer',
'common/header'
); $this->response->setOutput($this->render());
}
} //Controller中的render()方法
//会判断children属性是否赋值,有的话会逐个new child Controller,child Controller仍可以$this->render(),但调用$this->render()必须设定$this->template
//$this->data数组存储的值可在模板中使用
//$this->data[basename[$child]]保存的是子模板,common/home.tpl可以通过调用echo $column_left、$column_right、$content_top、$content_bottom输出
//应注意$this->data数组中的键值不要和子模板名重复!
function render() {
foreach ($this->children as $child) {
$this->data[basename($child)] = $this->getChild($child);
} if (file_exists(DIR_TEMPLATE . $this->template)) {
extract($this->data);//模板中使用 ob_start(); require(DIR_TEMPLATE . $this->template); $this->output = ob_get_contents(); ob_end_clean(); return $this->output;
} else {
trigger_error('Error: Could not load template ' . DIR_TEMPLATE . $this->template . '!');
exit();
}
} //controller中的getChild()方法
//只有在child Controller中执行了$this->render(),父Controller在$this->data[basename($child)]才能捕获到子模板,否则捕获的是空字符串
//虽然child Controller中的index()被定义为protected, 但是可以被父Controller调用, 因为他们都继承自Controller
function getChild($child, $args = array()) {
$action = new Action($child, $args); if (file_exists($action->getFile())) {
require_once($action->getFile()); $class = $action->getClass(); $controller = new $class($this->registry); $controller->{$action->getMethod()}($action->getArgs()); return $controller->output;
} else {
trigger_error('Error: Could not load controller ' . $child . '!');
exit();
}
} //在主Controlle中,this->render()返回的模板需要传送给$this->response->setOutput()才能输出
$this->response->setOutput($this->render()); //Controller中的语言包使用,$this->language保存在$registry中
$this->language->load('common/footer');
$this->data['text_information'] = $this->language->get('text_information');
$this->data['text_service'] = $this->language->get('text_service'); //Controller中session使用,$this->session保存在$registry中
$this->session->data[$key];
$this->session->data[$key] = 'hello'; //Controller中的$this->request数组
$this->get = $_GET;
$this->post = $_POST;
$this->request = $_REQUEST;
$this->cookie = $_COOKIE;
$this->files = $_FILES;
$this->server = $_SERVER;
$this->request->get['route'];//获取方式 //Controller中的$this->response使用
$this->response->setOutput($this->render());
$this->response->setOutput(json_encode($json));
$this->response->addHeader('Content-Type: application/xml'); //Controller中的$this->customer
$this->customer->isLogged();//判断登录状态
$this->customer->logout();//退出操作
$this->customer->login();//登录操作
$this->getId();//获取用户ID,存储在customer表中的customer_id //Controller中的页面跳转,$url->link()用于生成控制器的链接,如下
$this->redirect($this->url->link('catalog/information', 'token=' . $this->session->data['token'] . $url, 'SSL')); //Controller中的forward(),用于new 新的控制器,并返回
function forward($route, $args = array()) {
return new Action($route, $args);
} //Controller中的模型加载
$this->load->model('catalog/category');
$this->model_catalog_category;//使用格式 //cache使用(原始使用文件缓存)
$this->cache->get($key);
$this->cache->set($key, $value);
$this->cache->delete($key); //js,css等静态文件加载,通过Document对象加载额外的JS,CSS链接,在common子模板中会自动输出
$registry->document;
$registry->document->addLink($href, $rel);
$registry->addStyle($href, $rel = 'stylesheet', $media = 'screen');
$registry->addScript($script); //币种 //模型机制
//在index.php创建数据库连接,并保存在$registry,根据DB_DRIVER不同,调用system/database/下指定的数据库引擎
//拥有4个方法:query(),escape(),countAffected(),getLastId()
//当验证外部数据时要用escape()进行安全过滤
$db = new DB(DB_DRIVER, DB_HOSTNAME, DB_USERNAME, DB_PASSWORD, DB_DATABASE);
$registry->set('db', $db); //数据表解析
//oc_setting 配置
//oc_url_alias 配合apache rewrite,进行商品及分类URL优化
opencart源码解析之 index.php的更多相关文章
- phpcms v9 源码解析-1 index.php
这个是phpcms V9 的入口文件index.php. V9程序的执行绝大多数是从这个文件开始的,但不绝对,在项目下面的api.php和plugin.php是另外的入口文件,这里我们先不做深究. 在 ...
- 【转】opencart 源码解析
前台控制程序列表-catalog/controller Catalog|controller|account 会员功能 |—— account.php 会员功能主頁|—— address.php 会员 ...
- Redux系列x:源码解析
写在前面 redux的源码很简洁,除了applyMiddleware比较绕难以理解外,大部分还是 这里假设读者对redux有一定了解,就不科普redux的概念和API啥的啦,这部分建议直接看官方文档. ...
- jQuery2.x源码解析(设计篇)
jQuery2.x源码解析(构建篇) jQuery2.x源码解析(设计篇) jQuery2.x源码解析(回调篇) jQuery2.x源码解析(缓存篇) 这一篇笔者主要以设计的角度探索jQuery的源代 ...
- HashMap 源码解析
HashMap简介: HashMap在日常的开发中应用的非常之广泛,它是基于Hash表,实现了Map接口,以键值对(key-value)形式进行数据存储,HashMap在数据结构上使用的是数组+链表. ...
- Surface在C++层的创建源码解析
Surface在C++层的创建源码解析 源码为:android4.4.4 1.创建SurfaceComposerClient绘图客户端 // create a client to surfacefli ...
- 小学徒成长系列—StringBuilder & StringBuffer关键源码解析
在前面的博文<小学徒成长系列—String关键源码解析>和<小学徒进阶系列—JVM对String的处理>中,我们讲到了关于String的常用方法以及JVM对字符串常量Strin ...
- Java集合---Array类源码解析
Java集合---Array类源码解析 ---转自:牛奶.不加糖 一.Arrays.sort()数组排序 Java Arrays中提供了对所有类型的排序.其中主要分为Prim ...
- solr&lucene3.6.0源码解析(三)
solr索引操作(包括新增 更新 删除 提交 合并等)相关UML图如下 从上面的类图我们可以发现,其中体现了工厂方法模式及责任链模式的运用 UpdateRequestProcessor相当于责任链模式 ...
随机推荐
- Perl按行分割文件
Perl按行分割文件 将一个文件按照行数,均等的分割成多个小文件,例如,一个550行的文件,分割为每个文件有100行,则将分割为6个小文件 运行结果 参考代码(split_file.pl) #!/us ...
- AHB接口转APB
AHB接口转APB 情景 有一个以AHB接口时序设计的IP,现在需将其移至APB总线上,即将使用APB接口时序驱动该IP. 基本思路 将APB的接口信号映射到AHB的接口信号 要点 APB挂接在AHB ...
- [AngularFire2] Signup and logout
import {AuthProviders, FirebaseAuthState, FirebaseAuth, AuthMethods} from "angularfire2";i ...
- swift学习第六天:数组
数组 数组的介绍 数组(Array)是一串有序的由相同类型元素构成的集合 数组中的集合元素是有序的,可以重复出现 Swift中的数组 swift数组类型是Array,是一个泛型集合 数组的初始化 数组 ...
- 摘录-MYSQL5.7版本sql_mode=only_full_group_by问题
下载安装的是最新版的mysql5.7.x版本,默认是开启了 only_full_group_by 模式的,但开启这个模式后,原先的 group by 语句就报错,然后又把它移除了. 一旦开启 only ...
- 【死磕Java并发】—–J.U.C之AQS(一篇就够了)
[隐藏目录] 1 独占式 1.1 独占式同步状态获取 1.2 独占式获取响应中断 1.3 独占式超时获取 1.4 独占式同步状态释放 2 共享式 2.1 共享式同步状态获取 2.2 共享式同步状态释放 ...
- eclipse 远程debug tomcat web项目
1.首先须要在linux系统tomcat/bin文件夹下配置catalina.sh这个文件里添加: CATALINA_OPTS="-Xdebug -Xrunjdwp:transport=d ...
- ahks
!+F11:: newStr := clipboard ;newStr := RegExReplace(newStr, "<[^>]*>", "&quo ...
- 文件上传api——MultipartFile
MultipartFile 方法总结 byte[] getBytes() 返回文件的内容作为一个字节数组. String getContentType() 返回文件的内容类型. InputStr ...
- 手把手教你完成App支付JAVA后台-支付宝支付JAVA
接着上一篇博客,我们暂时完成了手机端的部分支付代码,接下来,我们继续写后台的代码. 后台基本需要到以下几个参数,我都将他们写在了properties文件中: 支付宝参数 AliPay.payURL = ...