Nội dung
- shares
- Facebook Messenger
- Gmail
- Viber
- Skype
Trong bài viết này chúng ta sẽ phát triển một module mới từ module đã có trong OpenCart, sau khi đọc xong bài viết hướng dẫn này bạn sẽ có module sản phẩm mới nhất với hiệu ứng slider Carousel. Chúng ta sẽ xem module đó làm việc như thế và cách tích hợp thêm tính năng trình chiếu vào module.
Mình sẽ không làm mất thời gian của bạn nữa, trước khi đi sâu vào nội dung cụ thể chúng ta sẽ chuẩn bị những files sau và thêm vào OpenCart của bạn.
Admin.
1. /admin/controller/module/carousel_latest.php (có thể nhân bản từ /admin/controller/module/carousel.php nếu bạn là người mới bắt đầu.)
2. /admin/language/english/module/carousel_latest.php (có thể copy từ file /admin/language/english/module/carousel.php nếu bạn là người mới bắt đầu.)
3. /admin/view/template/module/carousel_latest.tpl (có thể copy từ file /admin/view/template/module/carousel.tpl nếu bạn là người mới bắt đầu).
Catalog
1. /catalog/controller/module/carousel_latest.php (bạn có thể copy từ file /catalog/controller/module/carousel_latest.php)
2. /catalog/view/theme/default/template/module/carousel_latest.tpl (bạn có thể copy từ file /catalog/view/theme/default/template/module/carousel.tpl)
Ok, nào bây giờ chúng ta sẽ bắt đầu nhé.
1. /admin/controller/module/carousel_latest.php
Khi bạn xem chi tiết dữ liệu, nội dung nhập của module hay trên website module hiển thị, bạn có thể hoài nghi, chúng là cái gì? bạn có thể thêm một số mục khác? làm sao bạn có thể tùy biến chúng? ví dụ: layout, vị trí (Position), xắp xếp (Sort Order),..
Bạn xem thử module Carousel và so sánh nó với ảnh dưới đây:
Giải thích:
1. Limit: giới hạn số sản phẩm sẽ hiển thị ra.
2. Scroll: số sản phẩm tối đa hiển thị trong một lần scroll.
3. Image (W x H): Kích thước, áp dụng cho ảnh của sản phẩm.
4. Layout
5. Vị trí
6. Trạng thái.
7. Xắp xếp
Tại sao Limit Product? mình không thấy nó trên quản trị Carousel Module.
Vâng Đúng vậy, chúng ta sẽ thêm một biến vào Model để có thể lấy giới hạn số lượng sản phẩm trong Module. Nó sẽ tốt cho tốc độ load trang website của bạn.
Và ở đây bạn cần thêm $this->data['entry_limit_product'] = $this->language->get(‘entry_limit_product’);
vào file /admin/controller/module/carousel_latest.php. Xem thay đổi dưới đây:
<?php class ControllerModuleCarouselLatest extends Controller { private $error = array(); public function index() { $this->load->language('module/carousel_latest'); $this->document->setTitle($this->language->get('heading_title')); $this->load->model('setting/setting'); if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) { $this->model_setting_setting->editSetting('carousel_latest', $this->request->post); $this->cache->delete('product'); $this->session->data['success'] = $this->language->get('text_success'); $this->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')); } $this->data['heading_title'] = $this->language->get('heading_title'); $this->data['text_enabled'] = $this->language->get('text_enabled'); $this->data['text_disabled'] = $this->language->get('text_disabled'); $this->data['text_content_top'] = $this->language->get('text_content_top'); $this->data['text_content_bottom'] = $this->language->get('text_content_bottom'); $this->data['text_column_left'] = $this->language->get('text_column_left'); $this->data['text_column_right'] = $this->language->get('text_column_right'); $this->data['entry_limit_product'] = $this->language->get('entry_limit_product'); $this->data['entry_limit'] = $this->language->get('entry_limit'); $this->data['entry_scroll'] = $this->language->get('entry_scroll'); $this->data['entry_image'] = $this->language->get('entry_image'); $this->data['entry_layout'] = $this->language->get('entry_layout'); $this->data['entry_position'] = $this->language->get('entry_position'); $this->data['entry_status'] = $this->language->get('entry_status'); $this->data['entry_sort_order'] = $this->language->get('entry_sort_order'); $this->data['button_save'] = $this->language->get('button_save'); $this->data['button_cancel'] = $this->language->get('button_cancel'); $this->data['button_add_module'] = $this->language->get('button_add_module'); $this->data['button_remove'] = $this->language->get('button_remove'); if (isset($this->error['warning'])) { $this->data['error_warning'] = $this->error['warning']; } else { $this->data['error_warning'] = ''; } if (isset($this->error['image'])) { $this->data['error_image'] = $this->error['image']; } else { $this->data['error_image'] = array(); } $this->data['breadcrumbs'] = array(); $this->data['breadcrumbs'][] = array( 'text' => $this->language->get('text_home'), 'href' => $this->url->link('common/home', 'token=' . $this->session->data['token'], 'SSL'), 'separator' => false ); $this->data['breadcrumbs'][] = array( 'text' => $this->language->get('text_module'), 'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'), 'separator' => ' :: ' ); $this->data['breadcrumbs'][] = array( 'text' => $this->language->get('heading_title'), 'href' => $this->url->link('module/carousel_latest', 'token=' . $this->session->data['token'], 'SSL'), 'separator' => ' :: ' ); $this->data['action'] = $this->url->link('module/carousel_latest', 'token=' . $this->session->data['token'], 'SSL'); $this->data['cancel'] = $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'); $this->data['modules'] = array(); if (isset($this->request->post['carousel_latest_module'])) { $this->data['modules'] = $this->request->post['carousel_latest_module']; } elseif ($this->config->get('carousel_latest_module')) { $this->data['modules'] = $this->config->get('carousel_latest_module'); } $this->load->model('design/layout'); $this->data['layouts'] = $this->model_design_layout->getLayouts(); $this->template = 'module/carousel_latest.tpl'; $this->children = array( 'common/header', 'common/footer' ); $this->response->setOutput($this->render()); } private function validate() { if (!$this->user->hasPermission('modify', 'module/carousel_latest')) { $this->error['warning'] = $this->language->get('error_permission'); } if (isset($this->request->post['carousel_latest_module'])) { foreach ($this->request->post['carousel_latest_module'] as $key => $value) { if (!$value['image_width'] || !$value['image_height']) { $this->error['image'][$key] = $this->language->get('error_image'); } } } if (!$this->error) { return true; } else { return false; } } } ?>
2. /admin/language/english/module/carousel_latest.php
Chúng ta có phải tạo thêm file language cho module carousel lastest? câu trả lời là có. Bởi vì file ‘/admin/controller/extension/module.php’ sẽ luôn kiểm tra file language có tên tương ứng với tên controller của module mới này do đó, chúng ta sẽ tạo nó ngay bây giờ. module.php sẽ tìm file carousel_latest.php trong thư mục ‘/admin/language/english’.
Chép nội dung sau vào file /admin/language/english/module/carousel_latest.php và sửa lại nếu cần:
<?php // Heading $_['heading_title'] = 'Carousel Latest'; // Text $_['text_module'] = 'Modules'; $_['text_success'] = 'Success: You have modified module carousel latest!'; $_['text_content_top'] = 'Content Top'; $_['text_content_bottom'] = 'Content Bottom'; $_['text_column_left'] = 'Column Left'; $_['text_column_right'] = 'Column Right'; // Entry $_['entry_limit_product'] = 'Limit Products:'; $_['entry_limit'] = 'Limit:'; $_['entry_scroll'] = 'Scroll:'; $_['entry_image'] = 'Image (W x H):'; $_['entry_layout'] = 'Layout:'; $_['entry_position'] = 'Position:'; $_['entry_status'] = 'Status:'; $_['entry_sort_order'] = 'Sort Order:'; // Error $_['error_permission'] = 'Warning: You do not have permission to modify module carousel latest!'; $_['error_image'] = 'Image width & height dimensions required!'; ?>
3. /admin/view/template/module/carousel_latest.tpl
Chúng ta sẽ sử dụng file /admin/view/template/module/latest.tpl nếu bạn là người mới học OpenCart, cho bạn dễ tiếp cận và hình dung.
Có một số thứ bạn cần để ý trong admin template đó là thuộc tính name của mọi thẻ input (vd: carousel_latest_module, google_talk_module, featured_module,..) Tại sao vậy? dễ hiểu thôi vì chúng ta sẽ tương tác với chúng thông qua javascript/jQuery.
Tìm dòng.
<td colspan="6"></td>
thay bởi:
<td colspan="8"></td>
Lý do chúng ta có 8 biến sẽ điền ở đây:
<td class="left"><?php echo $entry_limit_product; ?></td> <td class="left"><?php echo $entry_limit; ?></td> <td class="left"><?php echo $entry_scroll; ?></td> <td class="left"><?php echo $entry_image; ?></td> <td class="left"><?php echo $entry_layout; ?></td> <td class="left"><?php echo $entry_position; ?></td> <td class="left"><?php echo $entry_status; ?></td> <td class="right"><?php echo $entry_sort_order; ?></td>
Và sau đây là toàn bộ nội dung của file /admin/view/template/module/carousel_latest.tpl
<?php echo $header; ?> <div id="content"> <div class="breadcrumb"> <?php foreach ($breadcrumbs as $breadcrumb) { ?> <?php echo $breadcrumb['separator']; ?><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a> <?php } ?> </div> <?php if ($error_warning) { ?> <div class="warning"><?php echo $error_warning; ?></div> <?php } ?> <div class="box"> <div class="heading"> <h1><img src="view/image/module.png" alt="" /> <?php echo $heading_title; ?></h1> <div class="buttons"><a onclick="$('#form').submit();" class="button"><?php echo $button_save; ?></a><a onclick="location = '<?php echo $cancel; ?>';" class="button"><?php echo $button_cancel; ?></a></div> </div> <div class="content"> <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form"> <table id="module" class="list"> <thead> <tr> <td class="left"><?php echo $entry_limit_product; ?></td> <td class="left"><?php echo $entry_limit; ?></td> <td class="left"><?php echo $entry_scroll; ?></td> <td class="left"><?php echo $entry_image; ?></td> <td class="left"><?php echo $entry_layout; ?></td> <td class="left"><?php echo $entry_position; ?></td> <td class="left"><?php echo $entry_status; ?></td> <td class="right"><?php echo $entry_sort_order; ?></td> <td></td> </tr> </thead> <?php $module_row = 0; ?> <?php foreach ($modules as $module) { ?> <tbody id="module-row<?php echo $module_row; ?>"> <tr> <td class="left"><input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][limit_product]" value="<?php echo $module['limit_product']; ?>" size="5" /></td> <td class="left"><input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][limit]" value="<?php echo $module['limit']; ?>" size="5" /></td> <td class="left"><input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][scroll]" value="<?php echo $module['scroll']; ?>" size="3" /></td> <td class="left"><input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][image_width]" value="<?php echo $module['image_width']; ?>" size="3" /> <input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][image_height]" value="<?php echo $module['image_height']; ?>" size="3" /> <?php if (isset($error_image[$module_row])) { ?> <span class="error"><?php echo $error_image[$module_row]; ?></span> <?php } ?></td> <td class="left"><select name="carousel_latest_module[<?php echo $module_row; ?>][layout_id]"> <?php foreach ($layouts as $layout) { ?> <?php if ($layout['layout_id'] == $module['layout_id']) { ?> <option value="<?php echo $layout['layout_id']; ?>" selected="selected"><?php echo $layout['name']; ?></option> <?php } else { ?> <option value="<?php echo $layout['layout_id']; ?>"><?php echo $layout['name']; ?></option> <?php } ?> <?php } ?> </select></td> <td class="left"><select name="carousel_latest_module[<?php echo $module_row; ?>][position]"> <?php if ($module['position'] == 'content_top') { ?> <option value="content_top" selected="selected"><?php echo $text_content_top; ?></option> <?php } else { ?> <option value="content_top"><?php echo $text_content_top; ?></option> <?php } ?> <?php if ($module['position'] == 'content_bottom') { ?> <option value="content_bottom" selected="selected"><?php echo $text_content_bottom; ?></option> <?php } else { ?> <option value="content_bottom"><?php echo $text_content_bottom; ?></option> <?php } ?> <?php if ($module['position'] == 'column_left') { ?> <option value="column_left" selected="selected"><?php echo $text_column_left; ?></option> <?php } else { ?> <option value="column_left"><?php echo $text_column_left; ?></option> <?php } ?> <?php if ($module['position'] == 'column_right') { ?> <option value="column_right" selected="selected"><?php echo $text_column_right; ?></option> <?php } else { ?> <option value="column_right"><?php echo $text_column_right; ?></option> <?php } ?> </select></td> <td class="left"><select name="carousel_latest_module[<?php echo $module_row; ?>][status]"> <?php if ($module['status']) { ?> <option value="1" selected="selected"><?php echo $text_enabled; ?></option> <option value="0"><?php echo $text_disabled; ?></option> <?php } else { ?> <option value="1"><?php echo $text_enabled; ?></option> <option value="0" selected="selected"><?php echo $text_disabled; ?></option> <?php } ?> </select></td> <td class="right"><input type="text" name="carousel_latest_module[<?php echo $module_row; ?>][sort_order]" value="<?php echo $module['sort_order']; ?>" size="3" /></td> <td class="left"><a onclick="$('#module-row<?php echo $module_row; ?>').remove();" class="button"><?php echo $button_remove; ?></a></td> </tr> </tbody> <?php $module_row++; ?> <?php } ?> <tfoot> <tr> <td colspan="8"></td> <td class="left"><a onclick="addModule();" class="button"><?php echo $button_add_module; ?></a></td> </tr> </tfoot> </table> </form> </div> </div> </div> <script type="text/javascript"><!-- var module_row = <?php echo $module_row; ?>; function addModule() { html = '<tbody id="module-row' + module_row + '">'; html += ' <tr>'; html += ' <td class="left"><input type="text" name="carousel_latest_module[' + module_row + '][limit_product]" value="10" size="1" /></td>'; html += ' <td class="left"><input type="text" name="carousel_latest_module[' + module_row + '][limit]" value="5" size="1" /></td>'; html += ' <td class="left"><input type="text" name="carousel_latest_module[' + module_row + '][scroll]" value="3" size="1" /></td>'; html += ' <td class="left"><input type="text" name="carousel_latest_module[' + module_row + '][image_width]" value="80" size="3" /> <input type="text" name="carousel_latest_module[' + module_row + '][image_height]" value="80" size="3" /></td>'; html += ' <td class="left"><select name="carousel_latest_module[' + module_row + '][layout_id]">'; <?php foreach ($layouts as $layout) { ?> html += ' <option value="<?php echo $layout['layout_id']; ?>"><?php echo addslashes($layout['name']); ?></option>'; <?php } ?> html += ' </select></td>'; html += ' <td class="left"><select name="carousel_latest_module[' + module_row + '][position]">'; html += ' <option value="content_top"><?php echo $text_content_top; ?></option>'; html += ' <option value="content_bottom"><?php echo $text_content_bottom; ?></option>'; html += ' <option value="column_left"><?php echo $text_column_left; ?></option>'; html += ' <option value="column_right"><?php echo $text_column_right; ?></option>'; html += ' </select></td>'; html += ' <td class="left"><select name="carousel_latest_module[' + module_row + '][status]">'; html += ' <option value="1" selected="selected"><?php echo $text_enabled; ?></option>'; html += ' <option value="0"><?php echo $text_disabled; ?></option>'; html += ' </select></td>'; html += ' <td class="right"><input type="text" name="carousel_latest_module[' + module_row + '][sort_order]" value="" size="3" /></td>'; html += ' <td class="left"><a onclick="$(\'#module-row' + module_row + '\').remove();" class="button"><?php echo $button_remove; ?></a></td>'; html += ' </tr>'; html += '</tbody>'; $('#module tfoot').before(html); module_row++; } //--></script> <?php echo $footer; ?>
Bây giờ, chúng ta refresh lại website, và xem những thay đổi !
4. /catalog/controller/module/carousel_latest.php
Mình nghĩ có nhiều lợi thê khi sử dụng một file có sẵn nếu bạn có ý định mở rộng thêm tính năng, như bạn thấy mình chỉ thay đổi chút xíu thay vì viết lại toàn bộ code trong file. Tiếp theo, nhân bản từ file ‘/catalog/controller/module/latest.php’ thành ‘/catalog/controller/module/carousel_latest.php’.
Biến $setting
Mình muốn chia sẻ thêm một chút trong file controller. Bạn đã từng tìm hiểu về biến $setting
trong controller?
Dĩ nhiên là có đúng không, chúng ta đang sử dụng nó để tạo module. Nhưng nó hình như không được sử dụng nhiều khi tùy biến module này cho tính năng carousel. Biến $setting
sử dụng trong admin controller và nó chứa dữ liệu về Layout, Position, Sort Order, ..
Và Ở đây nó là cái này:
<>Limit: giới hạn số sản phẩm sẽ hiển thị ra.
Scroll: số sản phẩm tối đa hiển thị trong một lần scroll.
Image (W x H): Kích thước, áp dụng cho ảnh của sản phẩm.
Layout
Position
Status.
Sort Order.
Và chúng ta sẽ lấy một trong số các giá trị chứa trong biến mảng này bằng cách viết ví dụ: $setting['layout']
.
Ok, tất cả các biến chúng ta xây dựng cho module lastest carousel đều được định nghĩa ở biến này, vì nhớ rằng chúng ta kế thừa sử dụng /catalog/controller/module/latest.php và chỉ thêm tính năng Limit Product như đề cập ở trên.
Do đó, chúng ta cần lấy giá trị option ‘limit product’ mà đã định nghĩa ở Admin Controller ( /admin/controller/module/carousel_latest.php).
Hãy xem biến $data
trong ‘/catalog/controller/module/carousel_latest.php’. Nó là dữ liệu mảng và sẽ truyền vào tham số hàm $this->model_catalog_product->getProducts($data)
.
$data = array( 'sort' => 'p.date_added', 'order' => 'DESC', 'start' => 0, 'limit' => $setting['limit_product'] // set how many total products will be retrieved here. );
Đoạn code trên, mình đã thêm key ‘limit’ lấy từ admin controller của module là $setting['limit_product']
.
Và đây là nội dung của file ‘/catalog/controller/module/carousel_latest.php’.
<?php class ControllerModuleCarouselLatest extends Controller { protected function index($setting) { static $module = 0; $this->document->addScript('catalog/view/javascript/jquery/jquery.jcarousel.min.js'); if (file_exists('catalog/view/theme/' . $this->config->get('config_template') . '/stylesheet/carousel.css')) { $this->document->addStyle('catalog/view/theme/' . $this->config->get('config_template') . '/stylesheet/carousel.css'); } else { $this->document->addStyle('catalog/view/theme/default/stylesheet/carousel.css'); } $this->data['limit'] = $setting['limit']; $this->data['scroll'] = $setting['scroll']; $this->load->model('catalog/product'); $this->load->model('tool/image'); $this->data['products'] = array(); $this->language->load('module/latest'); $this->data['heading_title'] = $this->language->get('heading_title'); $this->data['button_cart'] = $this->language->get('button_cart'); $data = array( 'sort' => 'p.date_added', 'order' => 'DESC', 'start' => 0, 'limit' => $setting['limit_product'] ); $results = $this->model_catalog_product->getProducts($data); foreach ($results as $result) { if ($result['image']) { $image = $this->model_tool_image->resize($result['image'], $setting['image_width'], $setting['image_height']); } else { $image = false; } if (($this->config->get('config_customer_price') && $this->customer->isLogged()) || !$this->config->get('config_customer_price')) { $price = $this->currency->format($this->tax->calculate($result['price'], $result['tax_class_id'], $this->config->get('config_tax'))); } else { $price = false; } if ((float)$result['special']) { $special = $this->currency->format($this->tax->calculate($result['special'], $result['tax_class_id'], $this->config->get('config_tax'))); } else { $special = false; } if ($this->config->get('config_review_status')) { $rating = $result['rating']; } else { $rating = false; } $this->data['products'][] = array( 'product_id' => $result['product_id'], 'thumb' => $image, 'name' => $result['name'], 'price' => $price, 'special' => $special, 'rating' => $rating, 'reviews' => sprintf($this->language->get('text_reviews'), (int)$result['reviews']), 'href' => $this->url->link('product/product', 'product_id=' . $result['product_id']), ); } $this->data['module'] = $module++; if (file_exists(DIR_TEMPLATE . $this->config->get('config_template') . '/template/module/carousel_latest.tpl')) { $this->template = $this->config->get('config_template') . '/template/module/carousel_latest.tpl'; } else { $this->template = 'default/template/module/carousel_latest.tpl'; } $this->render(); } } ?>
5. /catalog/view/theme/default/module/carousel_latest.tpl
Một lần nữa, chúng ta khẳng định không phải viết module này từ đâu. Tiếp tục copy file ‘/catalog/view/theme/default/module/carousel.tpl’ thành file ‘/catalog/view/theme/default/carousel_latest.tpl’ và sửa đôi chỗ.
Trong trường hợp này, chúng ta cần thay đổi dòng chữ “Banner” thành “Products”.
<div class="box"> <div class="box-heading"><?php echo $heading_title; ?></div> <div class="box-content"> <div class="box-product"> <div id="carousel_latest<?php echo $module; ?>" style="display: block; width: 100%; margin-right: 0px; margin-bottom: 0px;"> <ul class="jcarousel-skin-opencart"> <?php foreach ($products as $product) { ?> <li> <?php if ($product['thumb']) { ?> <div class="image"><a href="<?php echo $product['href']; ?>"><img src="<?php echo $product['thumb']; ?>" alt="<?php echo $product['name']; ?>" /></a></div> <?php } ?> <div class="name"><a href="<?php echo $product['href']; ?>"><?php echo $product['name']; ?></a></div> <?php if ($product['price']) { ?> <div class="price"> <?php if (!$product['special']) { ?> <?php echo $product['price']; ?> <?php } else { ?> <span class="price-old"><?php echo $product['price']; ?></span> <span class="price-new"><?php echo $product['special']; ?></span> <?php } ?> </div> <?php } ?> <?php if ($product['rating']) { ?> <div class="rating"><img src="catalog/view/theme/default/image/stars-<?php echo $product['rating']; ?>.png" alt="<?php echo $product['reviews']; ?>" /></div> <?php } ?> <div class="cart"><input type="button" value="<?php echo $button_cart; ?>" onclick="addToCart('<?php echo $product['product_id']; ?>');" class="button" /></div> </li> <?php } ?> </ul> </div> </div> </div> </div> <script type="text/javascript"><!-- $('#carousel_latest<?php echo $module; ?> ul').jcarousel({ vertical: false, visible: <?php echo $limit; ?>, scroll: <?php echo $scroll; ?> }); //--></script>
Okay, vậy là đã hoàn tất, bước cuối cùng bạn thêm module mới trong admin panel và thiết lập với Home Layout, hãy load lại trang chủ và thưởng thức nhá.
Để nhận được bài viết mới vui lòng đăng ký kênh kiến thức WordPress từ A-Z ở Form bên dưới. Bạn cũng có thể nhận được sự trợ giúp trên Twitter và Facebook
- shares
- Facebook Messenger
- Gmail
- Viber
- Skype