译 PrestaShop开发者指南 第四篇 深入PrestaShop核心开发

简介: ## 访问数据库 ### 数据库结构 PrestaShop的数据库表默认带有ps_的前缀,前缀在安装时可以自定义。 所有表名都是小写,以下划线分割。当一个表表示要在两个实体间建立连接时,表名中两个实体的的名称都要出现,比如ps_category_product表示将产品关联到对应的分类。

## 访问数据库

### 数据库结构

PrestaShop的数据库表默认带有ps_的前缀,前缀在安装时可以自定义。

所有表名都是小写,以下划线分割。当一个表表示要在两个实体间建立连接时,表名中两个实体的的名称都要出现,比如ps_category_product表示将产品关联到对应的分类。

几点细节:
- 用id_lang字段来存储与一条记录相关的语言
- 用id_shop字段来存储与一条记录相关的店铺
- 以_lang后缀结尾的表表示包含翻译,如ps_product_lang表包含ps_product表的所有翻译
- 以_shop后缀结尾的表表示链接到指定店铺的记录,如ps_category_shop表包含每个分类对应在哪个店铺上

### ObjectModel 类

ObjectModel是一个AR类型的类,它的一个实例对应一条数据库记录。

当你继承了这个类以后,首先要定义模型的基本信息。

<pre class="brush:php">
/**
* Example from the CMS model (CMSCore)
*/
public static $definition = array(
'table' => 'cms',
'primary' => 'id_cms',
'multilang' => true,
'fields' => array(
'id_cms_category' => array('type' => self::TYPE_INT, 'validate' => 'isUnsignedInt'),
'position' => array('type' => self::TYPE_INT),
'active' => array('type' => self::TYPE_BOOL),
// Lang fields
'meta_description' =>
array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
'meta_keywords' =>
array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'size' => 255),
'meta_title' =>
array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isGenericName', 'required' => true, 'size' => 128),
'link_rewrite' =>
array('type' => self::TYPE_STRING, 'lang' => true, 'validate' => 'isLinkRewrite', 'required' => true, 'size' => 128),
'content' =>
array('type' => self::TYPE_HTML, 'lang' => true, 'validate' => 'isString', 'size' => 3999999999999),
),
);

'multilang' => true,
'multishop' => true,
'multilang_shop' => true,
</pre>

主要调用方法:

<table class="confluenceTable tablesorter"><thead><tr class="sortableHeader"><th style="text-align: center;" class="confluenceTh sortableHeader tablesorter-headerSortDown" data-column="0"><div class="tablesorter-header-inner"><span style="color: rgb(0,0,0);"><strong>Method name and parameters</strong></span></div></th><th style="text-align: center;" class="confluenceTh sortableHeader" data-column="1"><div class="tablesorter-header-inner"><span style="color: rgb(0,0,0);"><strong>Description</strong></span></div></th></tr></thead><tbody class=""><tr><td colspan="1" class="confluenceTd"><p>__construct($id = NULL, $id_lang = NULL)</p></td><td colspan="1" class="confluenceTd"><p>Build object.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>add($autodate = true, $nullValues = false)</p></td><td colspan="1" class="confluenceTd"><p>Save current object to database (add or update).</p></td></tr><tr><td colspan="1" class="confluenceTd">associateTo(integer|array $id_shops)</td><td colspan="1" class="confluenceTd"><p>Associate an item to its context.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>delete()</p></td><td colspan="1" class="confluenceTd"><p>Delete current object from database.</p></td></tr><tr><td colspan="1" class="confluenceTd">deleteImage(mixed $force_delete = false)</td><td colspan="1" class="confluenceTd"><p>Delete images associated with the object.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>deleteSelection($selection)</p></td><td colspan="1" class="confluenceTd"><p>Delete several objects from database.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>getFields()</p></td><td colspan="1" class="confluenceTd"><p>Prepare fields for ObjectModel class (add, update).</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>getValidationRules($className = _CLASS_)</p></td><td colspan="1" class="confluenceTd"><p>Return object validation rules (field validity).</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>save($nullValues = false, $autodate = true)</p></td><td colspan="1" class="confluenceTd"><p>Save current object to database (add or update).</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>toggleStatus()</p></td><td colspan="1" class="confluenceTd"><p>Toggle object's status in database.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>update($nullValues = false)</p></td><td colspan="1" class="confluenceTd"><p>Update current object to database.</p></td></tr><tr><td colspan="1" class="confluenceTd"><p>validateFields($die = true, $errorReturn = false)</p></td><td colspan="1" class="confluenceTd"><p>Check for field validity before database interaction.</p></td></tr></tbody></table>

### DBQuery类

DBQuery是是一个用于构造SQL 查询语句的助手类。

<pre class="brush: php">
$sql = new DbQuery();
$sql->select('*');
$sql->from('cms', 'c');
$sql->innerJoin('cms_lang', 'l', 'c.id_cms = l.id_cms AND l.id_lang = '.(int)$id_lang);
$sql->where('c.active = 1');
$sql->orderBy('position');
return Db::getInstance()->executeS($sql
</pre>

译注:这个类的方法很基本,跟国产的比差了一截,但一般的应用够了。

## 路由分发

路由分发是v1.5引入的一项特性。

如下,当未启用Url重写时,

<pre>
http://myprestashop.com/index.php?controller=category&id_category=3&id_lang=1
http://myprestashop.com/index.php?controller=product&id_product=1&id_lang=2
</pre>

启用重写后:

<pre>
http://myprestashop.com/en/3-music-ipods
http://myprestashop.com/fr/1-ipod-nano.html
</pre>

路由分发器使用三个抽象类: Controller, FrontController 及d AdminController (后两个继承自第一个)。


可以通过重载loadRoutes()方法来创建新的路由。在后台界面的"Preferences"菜单下访问"SEO & URLs"页面就可以改变控制器的URL。

## 控制器

MVC的模式在此跳过不谈。

所有的控制器实际上都重载了Controller类,如AdminController, ModuleAdminController, FrontController, ModuleFrontController等。

### FrontController类

主要属性列表:

<pre>
Property
Description
$template Template name for page content.
$css_files Array list of CSS files.
$js_files Array list of JavaScript files.
$errors Array of errors that have occurred.
$guestAllowed Whether a customer who has signed out can access the page.
$initialized Whether the init() function has been called.
$iso The ISO code of the currently selected language.
$n The number of items per page.
$orderBy The field used to sort.
$orderWay Whether to sort is ascending or descending ("ASC" or "DESC").
$p The current page number.
$ajax If the ajax parameter is detected in request, set this flag to true.
</pre>

### 控制器内部函数执行顺序

1. __contruct(): Sets all the controller's member variables.
1. init(): Initializes the controller.
1. setMedia() or setMobileMedia(): Adds all JavaScript and CSS specifics to the page so that they can be combined, compressed and cached (see PrestaShop's CCC tool, in the back-office "Performance" page, under the "Advanced preferences" menu).
1. postProcess(): Handles ajaxProcess.
1. initHeader(): Called before initContent().
1. initContent(): Initializes the content.
1. initFooter(): Called after initContent().
1. display() or displayAjax(): Displays the content.

### 系统已有的控制器

控制器都在/controllers目录下,自己去看。

### 重载控制器

系统自带的控制器都带了一个Core的后缀,如

<pre>
文件 /controllers/CategoryController.php
类名: CategoryControllerCore
</pre>

要重载该控制器的话,

<pre>
文件: /override/controllers/front/CategoryController.php
类名: CategoryController
</pre>

## 视图

使用的Smarty引擎,文件扩展名.tpl。


## Cookies

统一使用/classes/Cookie.php中的类进行Cookie的读写。

<pre class="brush:php">
$this->context->cookie->variable;
</pre>

前端用户存储的cookie:


<pre>
Token
Description
viewed The IDs of recently viewed products as a comma-separated list.
passwd The MD5 hash of the _COOKIE_KEY_ in config/settings.inc.php and the password the customer used to log in.
logged Whether the customer is logged in.
last_visited_category The ID of the last visited category of product listings.
id_wishlist The ID of the current wishlist displayed in the wishlist block.
id_lang The ID of the selected language.
id_guest The guest ID of the visitor when not logged in.
id_customer The customer ID of the visitor when logged in.
id_currency The ID of the selected currency.
id_connections The connection ID of the visitor's current session.
id_cart The ID of the current cart displayed in the cart block.
email The email address that the customer used to log in.
date_add The date and time the cookie was created (in YYYY-MM-DD HH:MM:SS format).
customer_lastname The last name of the customer.
customer_firstname The first name of the customer.
checksum The Blowfish checksum used to determine whether the cookie has been modified by a third party.
The customer will be logged out and the cookie deleted if the checksum doesn't match.
checkedTOS Whether the "Terms of service" checkbox has been ticked (1 if it has and 0 if it hasn't)
ajax_blockcart_display Whether the cart block is "expanded" or "collapsed".
</pre>


后台用户存储的cookie:

Token
Description
date_add The date and time the cookie was created (in YYYY-MM-DD HH:MM:SS format).
id_lang The ID of the selected language.
id_employee The ID of the employee.
lastname The last name of the employee.
firstname The first name of the employee.
email The email address the employee used to log in.
profile The ID of the profile that determines which tabs the employee can access.
passwd The MD5 hash of the _COOKIE_KEY_ in config/settings.inc.php and the password the employee used to log in.
checksum The Blowfish checksum used to determine whether the cookie has been modified by a third party.
If the checksum doesn't match, the customer will be logged out and the cookie is deleted .


## 钩子

钩子是将你的代码与一些特定PrestaShop事件进行关联的机制。

主要的钩子有:

<pre>
Hook name
Description
displayFooter
Displays the content in the page's footer area.
displayHeader Displays the content in the page's header area.
displayHome Displays the content in the page's central area.
displayLeftColumn Displays the content in the page's left column.
displayRightColumn Displays the content in the page's right column.
displayTop Displays the content in the page's top area.

</pre>

### 使用钩子

在控制器中,

<pre class="brush:php">
$this->context->smarty->assign('HOOK_LEFT_COLUMN', Module::hookExec('displayLeftColumn'));
</pre>

在模块中,

<pre class="brush:php">
public function hookDisplayNameOfHook($params)
{
// Your code.
}
</pre>

为了让模块响应钩子的调用,要在模块安装代码中将钩子注册到PrestaShop中,

<pre class="brush:php">
public function install()
{
return parent::install() && $this->registerHook('NameOfHook');
}
</pre>

在视图中调用钩子,很容易,

<pre class="brush:html">
{hook h='displayLeftColumn' mod='blockcart'}
</pre>

### 创建自己的钩子

就是像上面模块安装代码中的一样,你想注册自己的钩子到系统中,只要简单的调用:

<pre class="brush:php">
$this->registerHook('NameOfHook');
</pre>

即可。他等同于:

<pre class="brush:sql">
INSERT INTO `ps_hook` (`name`, `title`, `description`) VALUES ('nameOfHook', 'The name of your hook', 'This is a custom hook!');
</pre>

目录
相关文章
|
3月前
|
JavaScript 关系型数据库 MySQL
fastadmin 部署phpstudy,初步学习fastadmin,保姆级详细讲解
fastadmin 部署phpstudy,初步学习fastadmin,保姆级详细讲解
46 0
|
9月前
|
XML SQL JSON
程序员开发常用的云在线工具
云在线开发工具:代码格式化,base64/md5加密解密,utf-8转换,时间戳在线生成
173 0
|
开发工具 数据安全/隐私保护 git
三行代码搭建一个全能书籍系统(wiki)
三行代码搭建一个全能书籍系统(wiki)
三行代码搭建一个全能书籍系统(wiki)
|
JavaScript 前端开发
为方便大家使用,汇总一下VueAdminWork免费开源系列框架各版本
为方便大家使用,汇总一下VueAdminWork免费开源系列框架各版本
为方便大家使用,汇总一下VueAdminWork免费开源系列框架各版本
|
存储 自然语言处理 前端开发
我用这些开源项目轻松搭建了一个在线文档平台
我用这些开源项目轻松搭建了一个在线文档平台
1798 0
我用这些开源项目轻松搭建了一个在线文档平台
|
Web App开发 Python
4款基于Django框架的开源软件推荐
Django是一款高性能的Python web框架,鼓励快速开发和干净、务实的设计。Django项目是一个定制框架,它源自一个在线新闻Web站点,于2005年以开源的形式被释放出来。Django的重点是尽可能地自动化,坚持DRY原则。
4658 0
|
移动开发 PHP 数据库
社交系统ThinkSNS+安装部署演示
ThinkSNS+版本发布之后,很多小伙伴们反馈安装部署有些困难,那么今天我们就通过录制视频的形式,给大家演示安装部署的全过程,由于时间紧张没有字幕,敬请谅解,后续我们有时间的时候会进行后期处理。
1457 0
|
SQL 关系型数据库 Linux