OpenCart之解读商品管理
因为公司里做商城开发用的是OpenCart,上级让我先熟悉这个系统,借此机会详细解读一下商品管理这一功能(也是为了日后给自己加深印象)。
首先,单击商品管理进入商品列表后,像这样:
商品列表界面
上面的六个文本是用来筛选的,下面的商品列表是用来排序的;所以一个完整的url可能会包括(token:密钥,filter_name:商品名称,filter_model:商品型号,filter_price:销售价格,filter_quantity:商品数量,filter_status:状态,filter_category:分类,sort则为按: (商品名称,商品型号,价格,数量,状态)来排序,order:(DESC,ASC),page:分页);
上面的panel是用来筛选条件的,像 分页,如图六个字段,都是通过字段名加在url后面作为参数传递的;因此,只要商品信息有变化,就要像这样:
$url = '';
if (isset($this->request->get['filter_name'])) {
$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_model'])) {
$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_price'])) {
$url .= '&filter_price=' . $this->request->get['filter_price'];
}
if (isset($this->request->get['filter_quantity'])) {
$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}
if (isset($this->request->get['filter_category'])) {
$url .= '&filter_category=' . $this->request->get['filter_category'];
}
if (isset($this->request->get['filter_status'])) {
$url .= '&filter_status=' . $this->request->get['filter_status'];
}
if (isset($this->request->get['sort'])) {
$url .= '&sort=' . $this->request->get['sort'];
}
if (isset($this->request->get['order'])) {
$url .= '&order=' . $this->request->get['order'];
}
if (isset($this->request->get['page'])) {
$url .= '&page=' . $this->request->get['page'];
}
因为会刷新页面,所以要重新组织url及url后面的参数,这样就可以:删除某些数量商品后,还能够保持在原有的页数上,或是原来的筛选条件上;
在点了筛选按钮后,商品列表的首页中的js代码首先会获取到你在上图六个文本中填写的内容,然后拼接到url上去,再location跳转到url(其实还是商品列表首页,只不过带着筛选条件);
<script type="text/javascript">
$('#button-filter').on('click', function() {
var url = 'index.php?route=catalog/product&token=<?php echo $token; ?>';
var filter_name = $('input[name=\'filter_name\']').val();
if (filter_name) {
url += '&filter_name=' + encodeURIComponent(filter_name);
}
var filter_model = $('input[name=\'filter_model\']').val();
if (filter_model) {
url += '&filter_model=' + encodeURIComponent(filter_model);
}
var filter_price = $('input[name=\'filter_price\']').val();
if (filter_price) {
url += '&filter_price=' + encodeURIComponent(filter_price);
}
var filter_quantity = $('input[name=\'filter_quantity\']').val();
if (filter_quantity) {
url += '&filter_quantity=' + encodeURIComponent(filter_quantity);
}
var filter_status = $('select[name=\'filter_status\']').val();
if (filter_status != '*') {
url += '&filter_status=' + encodeURIComponent(filter_status);
}
var filter_category = $('select[name=\'filter_category\']').val();
if (filter_category != '*') {
url += '&filter_category=' + encodeURIComponent(filter_category);
}
location = url;
});
</script>
在跳转页面后,重新调用controller中的index方法加载(这里调用的getList()方法功能大概可理解为:按条件筛选遍历获取所有商品,加载首页商品列表的视图);
public function index() {
$this->language->load('catalog/product');
$this->document->setTitle($this->language->get('heading_title'));
$this->load->model('catalog/product');
$this->getList();
}
这里index中的意义为:加载语言包,设置title标题,最重要的是先载入要进行操作数据库的model,再调用同controller中的getList()方法;由于controller中的getList()方法内容实在太多,但我就要一一讲解一下:)
-- Start getList() --
首先,(是否点击了筛选按钮)先查看是否存在筛选条件:(不存在只要设为null即可);
if (isset($this->request->get['filter_name'])) {
$filter_name = $this->request->get['filter_name'];
} else {
$filter_name = null;
}
if (isset($this->request->get['filter_model'])) {
$filter_model = $this->request->get['filter_model'];
} else {
$filter_model = null;
}
if (isset($this->request->get['filter_price'])) {
$filter_price = $this->request->get['filter_price'];
} else {
$filter_price = null;
}
if (isset($this->request->get['filter_quantity'])) {
$filter_quantity = $this->request->get['filter_quantity'];
} else {
$filter_quantity = null;
}
if (isset($this->request->get['filter_status'])) {
$filter_status = $this->request->get['filter_status'];
} else {
$filter_status = null;
}
if (isset($this->request->get['filter_category'])) {
$filter_category = $this->request->get['filter_category'];
} else {
$filter_category = null;
}
其次,(是否点击了商品列表的标题栏排序)再查看是否有排序条件:(这里默认为按商品名称ASC排序,第一页);
if (isset($this->request->get['sort'])) {
$sort = $this->request->get['sort'];
} else {
$sort = 'pd.name';
}
if (isset($this->request->get['order'])) {
$order = $this->request->get['order'];
} else {
$order = 'ASC';
}
if (isset($this->request->get['page'])) {
$page = $this->request->get['page'];
} else {
$page = 1;
}
有了各字段后,再进行组织url:
$url = '';
if (isset($this->request->get['filter_name'])) {
$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_model'])) {
$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_price'])) {
$url .= '&filter_price=' . $this->request->get['filter_price'];
}
if (isset($this->request->get['filter_quantity'])) {
$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}
if (isset($this->request->get['filter_category'])) {
$url .= '&filter_category=' . $this->request->get['filter_category'];
}
if (isset($this->request->get['filter_status'])) {
$url .= '&filter_status=' . $this->request->get['filter_status'];
}
if (isset($this->request->get['sort'])) {
$url .= '&sort=' . $this->request->get['sort'];
}
if (isset($this->request->get['order'])) {
$url .= '&order=' . $this->request->get['order'];
}
if (isset($this->request->get['page'])) {
$url .= '&page=' . $this->request->get['page'];
}
// urlencode():此函数便于将字符串编码并将其用于 URL 的请求部分,同时它还便于将变量传递给下一页。
// html_entity_decode():此函数把 HTML 实体转换为字符。
完成之后我们就得到了一个完整的url;
接下来是面包屑导航:
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL')
);
再是三个按钮:新增商品,复制商品和删除商品(这个我们稍后再讲);
$data['add'] = $this->url->link('catalog/product/add', 'token=' . $this->session->data['token'] . $url, 'SSL'); //新增商品
$data['copy'] = $this->url->link('catalog/product/copy', 'token=' . $this->session->data['token'] . $url, 'SSL'); //复制商品
$data['delete'] = $this->url->link('catalog/product/delete', 'token=' . $this->session->data['token'] . $url, 'SSL'); //删除商品
再是从request中获取到的筛选条件:
$filter_data = array(
'filter_name' => $filter_name, //商品名称
'filter_model' => $filter_model, //商品型号
'filter_price' => $filter_price, //销售价格
'filter_quantity' => $filter_quantity, //商品数量
'filter_status' => $filter_status, //状态
'filter_category' => $filter_category, //分类
'filter_is_limit' => 0, //商品是启用还是停用
'sort' => $sort, //排序的字段
'order' => $order, //ASC还是DESC
'start' => ($page - 1) * $this->config->get('config_limit_admin'), //开始的页数
'limit' => $this->config->get('config_limit_admin') //配置文件中,一页多少条记录
);
然后再通过向model模型传递$filter_data筛选条件来获取:符合条件的商品数量:$product_total,符合条件的商品信息:$results
model_catalog_product文件中以下两个方法都是把筛选数据传递过去,然后相应的改变sql语句即可;
$product_total = $this->model_catalog_product->getTotalProducts($filter_data);
$results = $this->model_catalog_product->getProducts($filter_data);
再是组织商品的信息:
$data['products'] = array();
foreach ($results as $result) {
//这之前要先$this->load->model('tool/image')加载工具类(只是调整了图片的大小)
if (is_file(DIR_IMAGE . $result['image'])) {
$image = $this->model_tool_image->resize($result['image'], 40, 40);
} else {
$image = $this->model_tool_image->resize('no_image.png', 40, 40);
}
/********这里特惠商品,暂时不做介绍**********/
$special = false;
$product_specials = $this->model_catalog_product->getProductSpecials($result['product_id']);
foreach ($product_specials as $product_special) {
if (($product_special['date_start'] == '0000-00-00' || strtotime($product_special['date_start']) < time()) && ($product_special['date_end'] == '0000-00-00' || strtotime($product_special['date_end']) > time())) {
$special = $product_special['price'];
break;
}
}
/********这里特惠商品,暂时不做介绍**********/
//重新整理组织商品信息
$data['products'][] = array(
'product_id' => $result['product_id'],
'image' => $image,
'name' => $result['name'],
'model' => $result['model'],
'price' => $result['price'],
'special' => $special,
'quantity' => $result['quantity'],
'status' => ($result['status']) ? $this->language->get('text_enabled') : $this->language->get('text_disabled'),
'edit' => $this->url->link('catalog/product/edit', 'token=' . $this->session->data['token'] . '&product_id=' . $result['product_id'] . $url, 'SSL'), //编辑商品
'add_limit' => $this->url->link('catalog/product_limit/add', 'token=' . $this->session->data['token'] . '&product_id=' . $result['product_id'] . $url, 'SSL'),
);
}
$data['token'] = $this->session->data['token']; //从session中获取token的值
再给商品列表中的五个标题添加链接(就是配置相应的url,使得能有排序的功能):
$url = '';
if (isset($this->request->get['filter_name'])) {
$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_model'])) {
$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_price'])) {
$url .= '&filter_price=' . $this->request->get['filter_price'];
}
if (isset($this->request->get['filter_category'])) {
$url .= '&filter_category=' . $this->request->get['filter_category'];
}
if (isset($this->request->get['filter_quantity'])) {
$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}
if (isset($this->request->get['filter_status'])) {
$url .= '&filter_status=' . $this->request->get['filter_status'];
}
if ($order == 'ASC') {
$url .= '&order=DESC';
} else {
$url .= '&order=ASC';
}
if (isset($this->request->get['page'])) {
$url .= '&page=' . $this->request->get['page'];
}
$data['sort_name'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=pd.name' . $url, 'SSL');
$data['sort_model'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.model' . $url, 'SSL');
$data['sort_price'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.price' . $url, 'SSL');
$data['sort_quantity'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.quantity' . $url, 'SSL');
$data['sort_status'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.status' . $url, 'SSL');
$data['sort_order'] = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . '&sort=p.sort_order' . $url, 'SSL');
再配置分页功能:(配置一次就要重新组织一次url)
$url = '';
if (isset($this->request->get['filter_name'])) {
$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_model'])) {
$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_price'])) {
$url .= '&filter_price=' . $this->request->get['filter_price'];
}
if (isset($this->request->get['filter_quantity'])) {
$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}
if (isset($this->request->get['filter_category'])) {
$url .= '&filter_category=' . $this->request->get['filter_category'];
}
if (isset($this->request->get['filter_status'])) {
$url .= '&filter_status=' . $this->request->get['filter_status'];
}
if (isset($this->request->get['sort'])) {
$url .= '&sort=' . $this->request->get['sort'];
}
if (isset($this->request->get['order'])) {
$url .= '&order=' . $this->request->get['order'];
}
$pagination = new Pagination();
$pagination->total = $product_total;
$pagination->page = $page;
$pagination->limit = $this->config->get('config_limit_admin');
$pagination->url = $this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url . '&page={page}', 'SSL');
$data['pagination'] = $pagination->render(); //这个是分页
$data['results'] = sprintf($this->language->get('text_pagination'), ($product_total) ? (($page - 1) * $this->config->get('config_limit_admin')) + 1 : 0, ((($page - 1) * $this->config->get('config_limit_admin')) > ($product_total - $this->config->get('config_limit_admin'))) ? $product_total : ((($page - 1) * $this->config->get('config_limit_admin')) + $this->config->get('config_limit_admin')), $product_total, ceil($product_total / $this->config->get('config_limit_admin'))); //这个是分页的信息
最后再传递数据:
/*****************若有筛选信息,则传递到视图的文本框中******************/
$data['filter_name'] = $filter_name;
$data['filter_model'] = $filter_model;
$data['filter_price'] = $filter_price;
$data['filter_quantity'] = $filter_quantity;
$data['filter_status'] = $filter_status;
$data['filter_category'] = $filter_category;
/********传递排序的信息过去,在视图页面进行判断*********/
$data['sort'] = $sort;
$data['order'] = $order;
$data['header'] = $this->load->controller('common/header');
$data['column_left'] = $this->load->controller('common/column_left');
$data['footer'] = $this->load->controller('common/footer');
//加载视图,传递数据
$this->response->setOutput($this->load->view('catalog/product_list.tpl', $data));
-- END getList() --
-- Start delete() --
现在介绍删除功能:
下面的商品列表看起来是一个表格,实际上外层包含了一个表单标签,当你点击删除时,给删除按钮绑定了submit()事件,提交表单到对应的action地址上去;
注意:要删除某件商品时,要在那件商品前打上勾,不然就直接跳到主页而没有变化了;
打上勾之后就有了:
$this->request->post['selected']; //这是所有勾选中的商品,值为商品id
<button type="button" data-toggle="tooltip" title="<?php echo $button_delete; ?>" class="btn btn-danger" onclick="confirm('<?php echo $text_confirm; ?>') ? $('#form-product').submit() : false;"><i class="fa fa-trash-o"></i></button> //删除按钮
<form action="<?php echo $delete; ?>" method="post" enctype="multipart/form-data" id="form-product"> //表单标签
$data['delete'] = $this->url->link('catalog/product/delete', 'token=' . $this->session->data['token'] . $url, 'SSL'); //调用controller中的delete方法
进入delete方法:
首先加载相应的资源:(大家都知道了);
若勾选中了该商品,并且该用户有修改的权限:
if (isset($this->request->post['selected']) && $this->validateDelete()){}
进入if后
到数据库中循环删除选中的商品:
foreach ($this->request->post['selected'] as $product_id) {
$this->model_catalog_product->deleteProduct($product_id);
}
这里再次修改或确认$url,其功能是:删除某些数量商品后,还能够保持在原有的页数上,或是原来的筛选条件上;
$url = '';
if (isset($this->request->get['filter_name'])) {
$url .= '&filter_name=' . urlencode(html_entity_decode($this->request->get['filter_name'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_model'])) {
$url .= '&filter_model=' . urlencode(html_entity_decode($this->request->get['filter_model'], ENT_QUOTES, 'UTF-8'));
}
if (isset($this->request->get['filter_price'])) {
$url .= '&filter_price=' . $this->request->get['filter_price'];
}
if (isset($this->request->get['filter_quantity'])) {
$url .= '&filter_quantity=' . $this->request->get['filter_quantity'];
}
if (isset($this->request->get['filter_status'])) {
$url .= '&filter_status=' . $this->request->get['filter_status'];
}
if (isset($this->request->get['sort'])) {
$url .= '&sort=' . $this->request->get['sort'];
}
if (isset($this->request->get['order'])) {
$url .= '&order=' . $this->request->get['order'];
}
if (isset($this->request->get['page'])) {
$url .= '&page=' . $this->request->get['page'];
}
if最后,删除成功,跳转到商品列表首页:
$this->response->redirect($this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL'));
if外(也就是没有选中任何商品):
$this->getList(); //就跟index方法一样,只是单纯的遍历数据
-- END delete() --
-- Start add() --
下面是新增功能:
调用controller中的add方法:
$data['add'] = $this->url->link('catalog/product/add', 'token=' . $this->session->data['token'] . $url, 'SSL');
首先,加载相应的资源;
一开始,$this->request->server['REQUEST_METHOD'] = GET,则不进入if循环,直接调用getForm()方法;
$this->getForm(); //加载要添加商品信息的表单
在getForm()方法中:
//首先重组url
//面包屑导航
//此时是加载表单的情况,因为视图中<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-product" class="form-horizontal">,所以这里要判断是add还是edit
//因为add和edit方法都调用了此方法,就根据是否传递了id来分别
if (!isset($this->request->get['product_id'])) {
$data['action'] = $this->url->link('catalog/product/add', 'token=' . $this->session->data['token'] . $url, 'SSL');
} else {
$data['action'] = $this->url->link('catalog/product/edit', 'token=' . $this->session->data['token'] . '&product_id=' . $this->request->get['product_id'] . $url, 'SSL');
}
//如果是编辑模式,则要先获取原有的商品信息
//这里表示编辑模式
if (isset($this->request->get['product_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
$product_info = $this->model_catalog_product->getProduct($this->request->get['product_id']);
}
//再是根据有无$this->request->get['product_id']或有无$product_info,来设置表单中文本框等其中的值;(add模式则为空值,edit模式则显示数据库中的值)
//再加载公用模板
//加载表单文件
$this->response->setOutput($this->load->view('catalog/product_form.tpl', $data));
当$this->request->server['REQUEST_METHOD'] =POST,也就是加载的表单提交之后:
//提交表单后,并验证通过
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validateForm())
//把提交的表单数据添加到数据库
$this->model_catalog_product->addProduct($this->request->post);
//又是重整url
//提交表单,新增商品成功后,跳转到商品列表首页
$this->response->redirect($this->url->link('catalog/product', 'token=' . $this->session->data['token'] . $url, 'SSL'));
-- END add() --
编辑和新增几乎一模一样,就不做介绍了。
其中的model文件都是sql操作,就没有贴上来了;
本篇只是加深自己对此系统的认知与记忆,希望大家多多指点;