美文网首页
openCart 3.0 启动

openCart 3.0 启动

作者: 爱折腾的傻小子 | 来源:发表于2018-12-13 15:59 被阅读30次
    • openCart 是国外的一个第三方电商项目
    • 根目录下 ./index.php文件 (入口文件)
    <?php
    // Version 版本号
    define('VERSION', '3.0.2.0');
    
    // Configuration  加载更目录下的config配置文件
    if (is_file('config.php')) {
        require_once('config.php');
    }
    
    // Install  安装判断
    // 如果安装过 会生成config.php配置文件 
    // 定义应用路径 DIR_APPLICATION
    if (!defined('DIR_APPLICATION')) {
        header('Location: install/index.php');
        exit;
    }
    
    // Startup  加载一些辅助函数 类文件等
    // 加载开始文件 ./system/startup.php 文件
    require_once(DIR_SYSTEM . 'startup.php');
    
    // 启动相关类文件等
    // 加载 ./system/framework.php 文件并传递 catalog 参数
    start('catalog');
    
    • ./config.php 配置文件
    <?php
    // HTTP
    define('HTTP_SERVER', 'http://b2c.dv:8080/');
    
    // HTTPS
    define('HTTPS_SERVER', 'http://b2c.dv/:8080');
    
    // DIR
    define('DIR_APPLICATION', 'c:/cole/laragon/www/b2c/catalog/');
    define('DIR_SYSTEM', 'c:/cole/laragon/www/b2c/system/');
    define('DIR_IMAGE', 'c:/cole/laragon/www/b2c/image/');
    define('DIR_STORAGE', 'c:/cole/laragon/www/b2c/storage/');
    define('DIR_LANGUAGE', DIR_APPLICATION . 'language/');
    define('DIR_TEMPLATE', DIR_APPLICATION . 'view/theme/');
    define('DIR_CONFIG', DIR_SYSTEM . 'config/');
    define('DIR_CACHE', DIR_STORAGE . 'cache/');
    define('DIR_DOWNLOAD', DIR_STORAGE . 'download/');
    define('DIR_LOGS', DIR_STORAGE . 'logs/');
    define('DIR_MODIFICATION', DIR_STORAGE . 'modification/');
    define('DIR_SESSION', DIR_STORAGE . 'session/');
    define('DIR_UPLOAD', DIR_STORAGE . 'upload/');
    
    // DB
    define('DB_DRIVER', 'mysqli');
    define('DB_HOSTNAME', 'localhost');
    define('DB_USERNAME', 'root');
    define('DB_PASSWORD', '123456');
    define('DB_DATABASE', 'uk');
    define('DB_PORT', '3306');
    define('DB_PREFIX', 'oc_');
    
    // 测试环境
    define('YIJIPAY_GATEWAY', 'http://openapi.yijifu.net/gateway.html');
    define('YIJIPAY_MERCHANTID', '2018xxxxxxxxxxxxxxxxxxx01');
    define('YIJIPAY_CKEY', '520xxxxxxxxxxxxxxxxxxxxxxx5e7');
    
    • ./system/startup 文件
    <?php
    // Error Reporting
    error_reporting(E_ALL);
    
    // Check Version
    // php 版本判断
    if (version_compare(phpversion(), '5.4.0', '<') == true) {
        exit('PHP5.4+ Required');
    }
    
    // php 时域设置
    if (!ini_get('date.timezone')) {
        date_default_timezone_set('UTC');
    }
    
    // Windows IIS Compatibility
    // server document_root 路径不存在时
    if (!isset($_SERVER['DOCUMENT_ROOT'])) {
        if (isset($_SERVER['SCRIPT_FILENAME'])) {
            $_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr($_SERVER['SCRIPT_FILENAME'], 0, 0 - strlen($_SERVER['PHP_SELF'])));
        }
    }
    
    if (!isset($_SERVER['DOCUMENT_ROOT'])) {
        if (isset($_SERVER['PATH_TRANSLATED'])) {
            $_SERVER['DOCUMENT_ROOT'] = str_replace('\\', '/', substr(str_replace('\\\\', '\\', $_SERVER['PATH_TRANSLATED']), 0, 0 - strlen($_SERVER['PHP_SELF'])));
        }
    }
    
    if (!isset($_SERVER['REQUEST_URI'])) {
        $_SERVER['REQUEST_URI'] = substr($_SERVER['PHP_SELF'], 1);
    
        if (isset($_SERVER['QUERY_STRING'])) {
            $_SERVER['REQUEST_URI'] .= '?' . $_SERVER['QUERY_STRING'];
        }
    }
    
    if (!isset($_SERVER['HTTP_HOST'])) {
        $_SERVER['HTTP_HOST'] = getenv('HTTP_HOST');
    }
    
    // Check if SSL
    if ((isset($_SERVER['HTTPS']) && (($_SERVER['HTTPS'] == 'on') || ($_SERVER['HTTPS'] == '1'))) || (isset($_SERVER['HTTPS']) && (isset($_SERVER['SERVER_PORT']) && $_SERVER['SERVER_PORT'] == 443))) {
        $_SERVER['HTTPS'] = true;
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_PROTO']) && $_SERVER['HTTP_X_FORWARDED_PROTO'] == 'https' || !empty($_SERVER['HTTP_X_FORWARDED_SSL']) && $_SERVER['HTTP_X_FORWARDED_SSL'] == 'on') {
        $_SERVER['HTTPS'] = true;
    } else {
        $_SERVER['HTTPS'] = false;
    }
    
    // Modification Override
    // 配置类文件加载 
    // 加载./admin下面文件   ./catalog下面文件 ./system下面文件
    function modification($filename) {
        if (defined('DIR_CATALOG')) {
            $file = DIR_MODIFICATION . 'admin/' .  substr($filename, strlen(DIR_APPLICATION));
        } elseif (defined('DIR_OPENCART')) {
            $file = DIR_MODIFICATION . 'install/' .  substr($filename, strlen(DIR_APPLICATION));
        } else {
            $file = DIR_MODIFICATION . 'catalog/' . substr($filename, strlen(DIR_APPLICATION));
        }
    
        if (substr($filename, 0, strlen(DIR_SYSTEM)) == DIR_SYSTEM) {
            $file = DIR_MODIFICATION . 'system/' . substr($filename, strlen(DIR_SYSTEM));
        }
    
        if (is_file($file)) {
            return $file;
        }
    
        return $filename;
    }
    
    // Autoloader 自动注册文件加载 composer
    if (is_file(DIR_STORAGE . 'vendor/autoload.php')) {
        require_once(DIR_STORAGE . 'vendor/autoload.php');
    }
    
    // 自动注册函数 加载./system/library/目录下的文件
    function library($class) {
        $file = DIR_SYSTEM . 'library/' . str_replace('\\', '/', strtolower($class)) . '.php';
    
        if (is_file($file)) {
            include_once(modification($file));
    
            return true;
        } else {
            return false;
        }
    }
    
    spl_autoload_register('library');
    spl_autoload_extensions('.php');
    
    // Engine
    // 调用 modification 函数加载下面类文件
    // 优先加载./storage/modification/system/engine/ 目录下的文件
    // 如果上面不存在 加载./system/engine/ 目录下的文件
    // Action 类作用 对象形式保存路由 并执行反射执行路由文件
    require_once(modification(DIR_SYSTEM . 'engine/action.php'));
    // 加载控制前抽象类controller 控制前类的继承类
    require_once(modification(DIR_SYSTEM . 'engine/controller.php'));
    // 加载事件Event类 处理事件  该类包括注册事件register 触发事件trigger 注销事件等
    // event触发controller/event目录文件控制器到方法
    require_once(modification(DIR_SYSTEM . 'engine/event.php'));
    // 加载路由文件 该类是集合action类的所有实例 并触发路由执行 先执行pre_action配置
    require_once(modification(DIR_SYSTEM . 'engine/router.php'));
    // 加载 model加载用到了proxy.php文件
    require_once(modification(DIR_SYSTEM . 'engine/loader.php'));
    // Model 抽象类 父类
    require_once(modification(DIR_SYSTEM . 'engine/model.php'));
    // Registry该类 记录各种实例对象 有点类似容器类
    require_once(modification(DIR_SYSTEM . 'engine/registry.php'));
    // 代理类
    require_once(modification(DIR_SYSTEM . 'engine/proxy.php'));
    
    // Helper
    // token 函数 创建一个指定长度的字符串
    // hash_equals 哈希字符串比较
    require_once(DIR_SYSTEM . 'helper/general.php');
    // utf8 字符处理函数引入
    // mbstring扩展存在优先引入 mb_*相关封装的函数
    // 否者判断 iconv 扩展是否存在 并引入相关封装的函数
    require_once(DIR_SYSTEM . 'helper/utf8.php');
    
    function start($application_config) {
        require_once(DIR_SYSTEM . 'framework.php'); 
    }
    
    • ./system/framework.php 文件
    • 应用启动文件 包含给各种类的添加等
    <?php
    // Registry
    // 实例化 Registry 类 参看./system/engine/registry.php 文件
    // 在前面 ./system/startup.php 文件引入 modification 函数
    $registry = new Registry();
    
    // Config
    // Config类文件 参考 ./system/library/config.php文件
    // 实例化Config类 在前面 ./system/startup.php 文件引入 spl_autoload_register('library'); 自动注入
    $config = new Config();
    // load方法记载config配置文件数据
    // ./system/config/default.php 默认所有配置文件信息
    $config->load('default');
    // ./system/config/catalog.php  session msysql Template 等相关配置信息
    $config->load($application_config);
    // 注册$registry->data['config'] = $config; 保存配置实例化对象
    $registry->set('config', $config);
    
    // Log
    // // 实例化Config类 在前面 ./system/startup.php 文件引入 spl_autoload_register('library'); 自动注入
    // $config->get('error_filename') = 'error.log';
    // 读取./storage/logs/error.log 文件信息并存储
    $log = new Log($config->get('error_filename'));
    // // 注册$registry->data['log'] = $log; 保存日志实例化对象
    $registry->set('log', $log);
    
    // 设置时区 默认UTC
    date_default_timezone_set($config->get('date_timezone'));
    
    // 设置用户自定义错误函数
    // code 错误发生的代码号
    // message 错误发生的提示信息
    // file 错误产生的文件
    // line 文件所在行号
    set_error_handler(function($code, $message, $file, $line) use($log, $config) {
        // error suppressed with @
        // 0 表示关闭所有的错误信息
        if (error_reporting() === 0) {
            return false;
        }
    
        // 错误级别标识
        switch ($code) {
            case E_NOTICE:
            case E_USER_NOTICE:
                $error = 'Notice';
                break;
            case E_WARNING:
            case E_USER_WARNING:
                $error = 'Warning';
                break;
            case E_ERROR:
            case E_USER_ERROR:
                $error = 'Fatal Error';
                break;
            default:
                $error = 'Unknown';
                break;
        }
    
        // 配置文件错误提示是否打开 默认 true 打开
        if ($config->get('error_display')) {
            // 错误提示输出
            echo '<b>' . $error . '</b>: ' . $message . ' in <b>' . $file . '</b> on line <b>' . $line . '</b>';
        }
    
        // 错误记录日志 是否打开 默认 true
        if ($config->get('error_log')) {
            // 错误信息写入 ./storage/logs/error.log 文件里面
            $log->write('PHP ' . $error . ':  ' . $message . ' in ' . $file . ' on line ' . $line);
        }
    
        return true;
    });
    
    // Event
    // Event 类文件 ./system/engine/event.php
    // 事件实例化 该类在前面 ./system/startup.php 文件引入 modification 函数
    // 传入 Registry 实例化类
    $event = new Event($registry);
    // 在registry类中绑定 event 实例化对象实例
    $registry->set('event', $event);
    
    // Event Register
    // 判断配置文件 action_event 配置参数是否设置
    // 参看 ./system/config/catalog.php 配置文件中的 action_event 参数
    /* {}表示备注 对应下面代码的值
      * 'view/* /before'{$key} => array(
      *     500{$priority}  => 'event/theme/override',{new Action($action)}
      *     998  => 'event/language',
      *     1000 => 'event/theme'
      * )
      * 'event/language' 被指向 ./catalog/controller/event/目录下面
     *   'event/language' => 等同于  'event/language/index'  默认是到index动作(默认省略)
     *   'event/theme/override' 默认到theme.php 的override动作
     */
    // Action 实例化类 在前面 ./system/startup.php 文件引入 modification 函数
    // ./storage/modifiction/system/engine/action.php 文件
    // Action 类参看 构造函数实现
    // $event->register方法 注册加载的event事件 $priority表示优先级 $key 触发节点
    // 对event以前的$this->data 数据根据$priority升序排序
    if ($config->has('action_event')) {
        foreach ($config->get('action_event') as $key => $value) {
            foreach ($value as $priority => $action) {
                $event->register($key, new Action($action), $priority);
            }
        }
    }
    
    // Loader
    // 类文件位置 ./storage/modification/system/engine/loader.php 文件
    // 该类在前面 ./system/startup.php 文件引入 modification 函数
    $loader = new Loader($registry); // 传递Registry 实例化对象
    // 绑定load 对应Loader实例化对象
    $registry->set('load', $loader);
    
    // Request
    // 请求实例化对象 
    // 在前面 ./system/startup.php 文件引入 spl_autoload_register('library'); 自动注入
    // 并绑定request对应Request实例化对象
    // 参看下面的 Request 类文件源码 处理请求数据等
    $registry->set('request', new Request());
    
    // Response
    // 响应 在前面 ./system/startup.php 文件引入 spl_autoload_register('library'); 自动注入
    // ./system/library/response.php 文件所在位置 实例化对象类
    $response = new Response();
    // 添加响应头信息
    $response->addHeader('Content-Type: text/html; charset=utf-8');
    // response 写入 level
    $response->setCompression($config->get('config_compression'));
    // 绑定响应 resopnse
    $registry->set('response', $response);
    
    // Database
    // 数据库 db_autostart 默认配置文件 true 数据库打开
    // new DB(); 在前面 ./system/startup.php 文件引入 spl_autoload_register('library'); 自动注入
    // db_engine 数据库类型 db_hostname hostname db_username 用户名 db_password 密码 db_database数据库名 db_port 端口
    // DB类源码参看一下
    // 绑定db 对应DB实例化对象属性
    if ($config->get('db_autostart')) {
        $registry->set('db', new DB($config->get('db_engine'), $config->get('db_hostname'), $config->get('db_username'), $config->get('db_password'), $config->get('db_database'), $config->get('db_port')));
    }
    
    // Session 默认支持db数据库 和 file文件
    // $config->get('session_engine') session引擎 默认db数据库
    // 参看session的处理机制 参看源码
    $session = new Session($config->get('session_engine'), $registry);
    $registry->set('session', $session);
    
    // session_autostart SESSION是否自动开启
    if ($config->get('session_autostart')) {
        /*
        We are adding the session cookie outside of the session class as I believe
        PHP messed up in a big way handling sessions. Why in the hell is it so hard to
        have more than one concurrent session using cookies!
    
        Is it not better to have multiple cookies when accessing parts of the system
        that requires different cookie sessions for security reasons.
    
        Also cookies can be accessed via the URL parameters. So why force only one cookie
        for all sessions!
        */
    
        // 判断session是否来自cookie里
        if (isset($_COOKIE[$config->get('session_name')])) {
            $session_id = $_COOKIE[$config->get('session_name')];
        } else {
            $session_id = '';
        }
    
        // 读取或生成session_id   读取session里面内容
        $session->start($session_id);
    
        // 设置cookie信息 SESSION相关配置参看配置文件
        setcookie($config->get('session_name'), $session->getId(), ini_get('session.cookie_lifetime'), ini_get('session.cookie_path'), ini_get('session.cookie_domain'));
    }
    
    // Cache 缓存 cache_engine 缓存引擎 cache_expire 缓存时间
    // 缓存绑定 cache
    $registry->set('cache', new Cache($config->get('cache_engine'), $config->get('cache_expire')));
    
    // Url 地址
    // site_url 网站http地址  http://b2c.dv:8080/
    // site_ssl 网站https地址 https://b2c.dv:8080/
    if ($config->get('url_autostart')) {
        $registry->set('url', new Url($config->get('site_url'), $config->get('site_ssl')));
    }
    
    // Language 语言设置 language_directory 默认en-gb
    $language = new Language($config->get('language_directory'));
    // 语言language绑定
    $registry->set('language', $language);
    
    // OpenBay Pro 第三方亚马逊等
    $registry->set('openbay', new Openbay($registry));
    
    // Document
    $registry->set('document', new Document());
    
    // 易极付验签 sign
    $registry->set('signhelper', new \yijipay\SignHelper());
    
    // 自动加载配置设置
    // Config Autoload
    // 触发 config_autoload 配置文件事件 before || after
    if ($config->has('config_autoload')) {
        foreach ($config->get('config_autoload') as $value) {
            $loader->config($value);
        }
    }
    
    // Language Autoload
    if ($config->has('language_autoload')) {
        foreach ($config->get('language_autoload') as $value) {
            $loader->language($value);
        }
    }
    
    // Library Autoload
    if ($config->has('library_autoload')) {
        foreach ($config->get('library_autoload') as $value) {
            $loader->library($value);
        }
    }
    
    // Model Autoload
    if ($config->has('model_autoload')) {
        foreach ($config->get('model_autoload') as $value) {
            $loader->model($value);
        }
    }
    
    // Route 路由
    $route = new Router($registry);
    
    // Pre Actions 添加路由
    if ($config->has('action_pre_action')) {
        foreach ($config->get('action_pre_action') as $value) {
            $route->addPreAction(new Action($value));
        }
    }
    
    // Dispatch 反射方法 控制器中
    $route->dispatch(new Action($config->get('action_router')), new Action($config->get('action_error')));
    
    // Output 输出
    $response->output();
    
    • Request 位置./system/library/request.php
    <?php
    /**
     * @package     OpenCart
     * @author      Daniel Kerr
     * @copyright   Copyright (c) 2005 - 2017, OpenCart, Ltd. (https://www.opencart.com/)
     * @license     https://opensource.org/licenses/GPL-3.0
     * @link        https://www.opencart.com
    */
    
    /**
    * Request class
    */
    class Request {
        public $get = array();        // $_GET
        public $post = array();      // $_POST
        public $cookie = array();  // $_COOKIE
        public $files = array();      // $_FILES
        public $server = array();  // $_SERVER
        
        /**
         * Constructor
        */
        public function __construct() {
            $this->get = $this->clean($_GET);
            $this->post = $this->clean($_POST);
            $this->request = $this->clean($_REQUEST);
            $this->cookie = $this->clean($_COOKIE);
            $this->files = $this->clean($_FILES);
            $this->server = $this->clean($_SERVER);
        }
        
        /**
         *  对请求参数进行实例化转义 htmlspecialchars 函数处理
         * @param   array   $data
         *
         * @return  array
         */
        public function clean($data) {
            if (is_array($data)) {
                foreach ($data as $key => $value) {
                    unset($data[$key]);
    
                    $data[$this->clean($key)] = $this->clean($value);
                }
            } else {
                $data = htmlspecialchars($data, ENT_COMPAT, 'UTF-8');
            }
    
            return $data;
        }
    }
    
    • db 封装 位置./system/library/db.php 该类是在数据库层面疯转的一个类 调用不同类型的数据库
    <?php
    /**
    * DB class
    */
    class DB {
        private $adaptor;
    
        /**
         * Constructor
         *
         * @param   string  $adaptor
         * @param   string  $hostname
         * @param   string  $username
         * @param   string  $password
         * @param   string  $database
         * @param   int     $port
         *
        */
        public function __construct($adaptor, $hostname, $username, $password, $database, $port = NULL) {
            // 这里传入的是 mysqli $class DB\\mysqli 空间名称namespace
            // 指向 自动注册 ./system/library/db/mysqli.php 被实例化对象 该对象主要是连接mysql数据库
            $class = 'DB\\' . $adaptor;
    
            if (class_exists($class)) {
                // 如果该文件存在 创建实例对象
                // 我们查看一下 ./system/library/db/mysqli.php 相关文件类实例
                $this->adaptor = new $class($hostname, $username, $password, $database, $port);
            } else {
                throw new \Exception('Error: Could not load database adaptor ' . $adaptor . '!');
            }
        }
    
        /**
         * 
         *
         * @param   string  $sql
         * 
         * @return  array
         */
        public function query($sql) {
            return $this->adaptor->query($sql);
        }
    
        /**
         * 
         *
         * @param   string  $value
         * 
         * @return  string
         */
        public function escape($value) {
            return $this->adaptor->escape($value);
        }
    
        /**
         * 
         * 
         * @return  int
         */
        public function countAffected() {
            return $this->adaptor->countAffected();
        }
    
        /**
         * 
         * 
         * @return  int
         */
        public function getLastId() {
            return $this->adaptor->getLastId();
        }
        
        /**
         * 
         * 
         * @return  bool
         */ 
        public function connected() {
            return $this->adaptor->connected();
        }
    }
    
    • ./system/library/db/mysqli.php
    <?php
    namespace DB;
    final class MySQLi {
        private $connection;
    
        public function __construct($hostname, $username, $password, $database, $port = '3306') {
            // 连接数据库
            $this->connection = new \mysqli($hostname, $username, $password, $database, $port);
    
            // 连接数据库判断
            if ($this->connection->connect_error) {
                throw new \Exception('Error: ' . $this->connection->error . '<br />Error No: ' . $this->connection->errno);
            }
    
            // 设置数据库字符集
            $this->connection->set_charset("utf8");
            // SET SQL_MODE = '' 不做输入检测 错误提示 语法检查等
            $this->connection->query("SET SQL_MODE = ''");
        }
    
        // 数据库sql语句执行
        public function query($sql) {
            // 执行sql语句
            $query = $this->connection->query($sql);
    
            // 语句被正常执行时
            if (!$this->connection->errno) {
                // 出路返回数据集 并返回数据对象
                if ($query instanceof \mysqli_result) {
                    $data = array();
    
                    while ($row = $query->fetch_assoc()) {
                        $data[] = $row;
                    }
    
                    $result = new \stdClass();
                    $result->num_rows = $query->num_rows;
                    $result->row = isset($data[0]) ? $data[0] : array();
                    $result->rows = $data;
    
                    $query->close();
    
                    return $result;
                } else {
                    return true;
                }
            } else {
                throw new \Exception('Error: ' . $this->connection->error  . '<br />Error No: ' . $this->connection->errno . '<br />' . $sql);
            }
        }
    
        // real_escape_string 对输入的特殊字符进行转义 以便进行sql查询
        public function escape($value) {
            return $this->connection->real_escape_string($value);
        }
        
        // 返回上次执行语句更改、删除或插入的行总数
        public function countAffected() {
            return $this->connection->affected_rows;
        }
    
        // 最有一次插入的id值
        public function getLastId() {
            return $this->connection->insert_id;
        }
        
        // 如果连接处于断开 重新连接
        public function connected() {
            return $this->connection->ping();
        }
        
        // 关闭连接
        public function __destruct() {
            $this->connection->close();
        }
    }
    

    相关文章

      网友评论

          本文标题:openCart 3.0 启动

          本文链接:https://www.haomeiwen.com/subject/fzdvhqtx.html