今天,我们将介绍OpenCart 2.x中的控制器概念。 在OpenCart 2.x版本的发行中,他们引入了框架更改,如果您在较早版本的OpenCart 1.x中创建了任何自定义模块,则需要对其进行升级。 在本教程中,我们将逐步介绍一个称为Guestbook的实际示例。
在我们继续本文之前,您可以将其视为我之前撰写的后续文章 。 在那篇文章中,我解释了如何在OpenCart 1.x中创建自定义页面,如果您已经阅读了该文章,则可以快速跳过今天的大部分内容!
当然,今天将要讨论的是OpenCart 2.x,因此请确保您严格遵循该代码。
如果您想了解有关OpenCart框架模式和控制器的更多理论,则可以阅读该文章的前几个部分。 话虽如此,但没有什么可以阻止您立即关注本文,因为我不会跳过任何要点。
为什么要使用自定义控制器?
您可能首先要问的问题-为什么要使用自定义控制器? 在开始之前,让我们快速了解一下OpenCart中控制器的全部含义。
在OpenCart的上下文中, 控制器是框架中必不可少的组件,它直接处理路由过程并呈现UI。 在此过程中,它将处理其他重要组件,例如语言,模型和视图,以建立最终结果。
当您访问OpenCart中的任何页面时,OpenCart框架都会寻找相应的控制器,并将进一步的处理委托给它。 由于本质上是模块化的,OpenCart框架提供了多个控制器,这些控制器处理逻辑分组的功能。
例如, 帐户组包含处理登录,注册,配置文件和类似用例的控制器。 同样, 结帐的控制器组将处理订单创建过程。
简而言之,当您要创建不在OpenCart核心中的功能并且如果它采用新的URL(OpenCart术语中的路由)时,您应该使用自定义控制器。 它使您可以完全控制页面创建过程,即要在自定义页面上显示的元素。
创建一个自定义控制器
今天,我们将实现一个基本的Guestbook功能,以演示自定义控制器的概念。 在此过程中,我们将在前端建立一个界面,使来宾用户可以通过输入其名称和消息来提交反馈。
在继续之前,请确保您已经安装了OpenCart2.3.x。 这几乎可以开始使用我们的留言簿功能。
对于那些不熟悉OpenCart结构的人,寻找前端控制器的地方是catalog/controller
。 该目录根据组提供的功能按组管理所有控制器。
在本例中,我们将创建一个单独的组,名为guestbook 。 继续创建目录catalog/controller/guestbook
。 在该目录中,创建一个entry.php
以下内容的entry.php
文件。 这是一个控制器文件,用于处理Guestbook功能的应用程序逻辑和提交逻辑。
<?php
class ControllerGuestbookEntry extends Controller {
private $error = array();
public function index() {
$this->load->language('guestbook/guestbook');
$this->document->setTitle($this->language->get('heading_title'));
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$this->load->model('guestbook/guestbook');
$data['subject'] = sprintf('New guestbook entry submitted by %s', $this->request->post['guest_name']);
$data['message'] = $this->request->post['guest_message'];
$this->model_guestbook_guestbook->processGuestbookEntry($data);
$this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('guestbook/entry', '', true));
}
$data['success'] = '';
if (isset($this->session->data['success'])) {
$data['success'] = $this->session->data['success'];
unset($this->session->data['success']);
}
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/home')
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('guestbook/entry', '', true)
);
$data['heading_title'] = $this->language->get('heading_title');
$data['entry_guest_name'] = $this->language->get('entry_guest_name');
$data['entry_guest_message'] = $this->language->get('entry_guest_message');
$data['entry_submit'] = $this->language->get('entry_submit');
if (isset($this->error['guest_name'])) {
$data['error_guest_name'] = $this->error['guest_name'];
} else {
$data['error_guest_name'] = '';
}
if (isset($this->error['guest_message'])) {
$data['error_guest_message'] = $this->error['guest_message'];
} else {
$data['error_guest_message'] = '';
}
$data['action'] = $this->url->link('guestbook/entry', '', true);
if (isset($this->request->post['guest_name'])) {
$data['guest_name'] = $this->request->post['guest_name'];
} else {
$data['guest_name'] = '';
}
if (isset($this->request->post['guest_message'])) {
$data['guest_message'] = $this->request->post['guest_message'];
} else {
$data['guest_message'] = '';
}
$data['column_left'] = $this->load->controller('common/column_left');
$data['column_right'] = $this->load->controller('common/column_right');
$data['content_top'] = $this->load->controller('common/content_top');
$data['content_bottom'] = $this->load->controller('common/content_bottom');
$data['footer'] = $this->load->controller('common/footer');
$data['header'] = $this->load->controller('common/header');
$this->response->setOutput($this->load->view('guestbook/entry', $data));
}
protected function validate() {
if (utf8_strlen(trim($this->request->post['guest_name'])) < 1) {
$this->error['guest_name'] = $this->language->get('error_guest_name');
}
if (utf8_strlen(trim($this->request->post['guest_message'])) < 1) {
$this->error['guest_message'] = $this->language->get('error_guest_message');
}
return !$this->error;
}
}
根据OpenCart命名约定,类名以Controller
关键字开头,后跟目录名Guestbook
在本例中为该类文件所在的目录)。 此外,类文件名(在本例中为Entry
被附加在末尾。
每个控制器类都提供一个事实上的index
方法,该方法处理控制器的大多数逻辑。 接下来,我们将遍历index
方法中的代码,并根据需要创建其他文件。
大多数情况下,我们将从为特定组添加语言文件开始。 这是OpenCart在整个应用程序中管理静态语言标签的方式。 当然,这使多语言站点的实现变得轻而易举。
$this->load->language('guestbook/guestbook');
在继续之前,让我们创建相应的语言文件,以便我们的控制器可以找到它。 使用以下内容创建一个catalog/language/en-gb/guestbook/guestbook.php
文件。
<?php
// Heading
$_['heading_title'] = 'Guestbook';
// Entry
$_['entry_guest_name'] = 'Your Name';
$_['entry_guest_message'] = 'Message';
$_['entry_submit'] = 'Submit';
$_['text_success'] = 'Success: Your entry has been successfully submitted.';
// Error
$_['error_guest_name'] = 'Please enter Your Name!';
$_['error_guest_message'] = 'Please enter Message!';
如您所见,我们只是在语言数组中为其标签分配值。
回到我们的控制器,下一步是为页面设置HTML标题标签。
$this->document->setTitle($this->language->get('heading_title'));
眼神敏锐的用户会注意到,我们已经使用了heading_title
创建的语言文件中定义的heading_title
语言变量。
为了理解下一段代码,我们需要创建一个模型文件。 因此,暂时,我将带您在catalog/model/guestbook/guestbook.php
创建模型文件,其中包含以下内容。
<?php
class ModelGuestbookGuestbook extends Model {
public function processGuestbookEntry($data) {
// send email notification to store admin
$mail = new Mail();
$mail->protocol = $this->config->get('config_mail_protocol');
$mail->parameter = $this->config->get('config_mail_parameter');
$mail->smtp_hostname = $this->config->get('config_mail_smtp_hostname');
$mail->smtp_username = $this->config->get('config_mail_smtp_username');
$mail->smtp_password = html_entity_decode($this->config->get('config_mail_smtp_password'), ENT_QUOTES, 'UTF-8');
$mail->smtp_port = $this->config->get('config_mail_smtp_port');
$mail->smtp_timeout = $this->config->get('config_mail_smtp_timeout');
$mail->setTo($this->config->get('config_email'));
$mail->setFrom($this->config->get('config_email'));
$mail->setSender(html_entity_decode($this->config->get('config_name'), ENT_QUOTES, 'UTF-8'));
$mail->setSubject($data['subject']);
$mail->setText($data['message']);
$mail->send();
}
}
在OpenCart中,该模型负责处理应用程序的业务逻辑。 如果您希望实现涉及数据库的任何逻辑,则应该在其中放置数据库。
模型类的命名约定类似于控制器类的命名约定。 为简单processGuestbookEntry
,我们实现了processGuestbookEntry
方法,当用户提交访客留言条目时,该方法通过电子邮件通知商店管理员。 很简单吧?
让我们回到控制器,检查队列中的下一段代码。
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
$this->load->model('guestbook/guestbook');
$data['subject'] = sprintf('New guestbook entry submitted by %s', $this->request->post['guest_name']);
$data['message'] = $this->request->post['guest_message'];
$this->model_guestbook_guestbook->processGuestbookEntry($data);
$this->session->data['success'] = $this->language->get('text_success');
$this->response->redirect($this->url->link('guestbook/entry', '', true));
}
它检查有效的POST
请求,并通过调用validate
方法对用户提交的数据进行基本验证。
代码$this->load->model('guestbook/guestbook')
用于加载我们刚才定义的模型。 之后,我们立即根据用户输入准备$data
数组,并调用processGuestbookEntry
方法,该方法将有关Guestbook条目的信息通知商店管理员。 最后,我们将用户重定向回Guestbook输入页面。
在控制器中继续前进,以下代码段设置了成功消息,该消息将在提交表单时显示。
$data['success'] = '';
if (isset($this->session->data['success'])) {
$data['success'] = $this->session->data['success'];
unset($this->session->data['success']);
}
接下来,有一个代码片段用于构建页面的面包屑链接。
$data['breadcrumbs'] = array();
$data['breadcrumbs'][] = array(
'text' => $this->language->get('text_home'),
'href' => $this->url->link('common/home')
);
$data['breadcrumbs'][] = array(
'text' => $this->language->get('heading_title'),
'href' => $this->url->link('guestbook/entry', '', true)
);
下一个片段很重要,您将在大多数时间中使用该片段将信息从控制器方法传递到视图模板。
$data['heading_title'] = $this->language->get('heading_title');
$data['entry_guest_name'] = $this->language->get('entry_guest_name');
$data['entry_guest_message'] = $this->language->get('entry_guest_message');
$data['entry_submit'] = $this->language->get('entry_submit');
与分配变量相似,OpenCart初始化页面的公共元素(页眉,页脚等),如以下代码段所示。
$data['column_left'] = $this->load->controller('common/column_left');
$data['column_right'] = $this->load->controller('common/column_right');
$data['content_top'] = $this->load->controller('common/content_top');
$data['content_bottom'] = $this->load->controller('common/content_bottom');
$data['footer'] = $this->load->controller('common/footer');
$data['header'] = $this->load->controller('common/header');
最后,它调用视图模板来呈现实际页面!
$this->response->setOutput($this->load->view('guestbook/entry', $data));
当然,我们还没有构建视图模板。 现在是这样做的最佳时机! 继续创建具有以下内容的catalog/view/theme/default/template/guestbook/entry.tpl
文件。
<?php echo $header; ?>
<div class="container">
<ul class="breadcrumb">
<?php foreach ($breadcrumbs as $breadcrumb) { ?>
<li><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li>
<?php } ?>
</ul>
<?php if ($success) { ?>
<div class="alert alert-success"><i class="fa fa-check-circle"></i> <?php echo $success; ?></div>
<?php } ?>
<div class="row"><?php echo $column_left; ?>
<?php if ($column_left && $column_right) { ?>
<?php $class = 'col-sm-6'; ?>
<?php } elseif ($column_left || $column_right) { ?>
<?php $class = 'col-sm-9'; ?>
<?php } else { ?>
<?php $class = 'col-sm-12'; ?>
<?php } ?>
<div id="content" class="<?php echo $class; ?>"><?php echo $content_top; ?>
<h1><?php echo $heading_title; ?></h1>
<form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" class="form-horizontal">
<div class="form-group required">
<label class="col-sm-2 control-label" for="input-guest-name"><?php echo $entry_guest_name; ?></label>
<div class="col-sm-10">
<input type="text" value="<?php echo $guest_name; ?>" name="guest_name" placeholder="<?php echo $entry_guest_name; ?>" id="input-guest-name" class="form-control" size="10" />
<?php if ($error_guest_name) { ?>
<div class="text-danger"><?php echo $error_guest_name; ?></div>
<?php } ?>
</div>
</div>
<div class="form-group required">
<label class="col-sm-2 control-label" for="input-guest-message"><?php echo $entry_guest_message; ?></label>
<div class="col-sm-10">
<textarea name="guest_message" placeholder="<?php echo $entry_guest_message; ?>" id="input-guest-message" class="form-control"><?php echo $guest_message; ?></textarea>
<?php if ($error_guest_message) { ?>
<div class="text-danger"><?php echo $error_guest_message; ?></div>
<?php } ?>
</div>
</div>
<div class="form-group required">
<label class="col-sm-2"> </label>
<div class="col-sm-10">
<input type="submit" value="<?php echo $entry_submit; ?>" class="btn btn-primary" />
</div>
</div>
</form>
<?php echo $content_bottom; ?></div>
<?php echo $column_right; ?></div>
</div>
<?php echo $footer; ?>
这是我们的主视图模板文件,负责显示留言簿页面的内容。 在此文件中,我们仅使用了在控制器的index
方法中设置的变量。
重要的是要注意,响应性是Bootstrap框架支持的OpenCart最新版本中内置的。 除此之外,它是非常普通HTML内容,非常容易理解。
因此,就文件设置而言就是这样。
现在我们已经准备就绪,但是您如何从前端访问呢?
在前端,您可以通过添加route querystring变量来访问Guestbook页面,因此URL应该类似于http://your-opencart-store-url/index.php?route = guestbook / entry 。
让我们了解OpenCart如何将任何URL映射到特定的控制器文件。 路由变量的格式为{directory}/{filename}/{methodname}
。
-
{directory}
组件映射到catalog/controller
下的catalog/controller
。
-
{filename}
映射到catalog/controller/{directory}
下的控制器文件的名称。 - 最后,如果在路由中指定了控制器方法,则它将查找名为
{methodname}
的控制器方法,否则将调用默认的index
方法。
这就是最终结果。
当然,您可以提交表单来继续进行测试,并且您应该收到一封电子邮件通知,该电子邮件通知是注册为商店管理员的电子邮件地址。
结论
在任何框架中,继续实现自己的自定义功能总是令人兴奋。 这正是今天教程的主题,我们在其中扩展了OpenCart并通过构建一个非常简单而有用的Guestbook功能来开发自定义控制器。
在此过程中,我们意识到不仅仅是控制器,还有其他一些不可避免的关键要素。 因此,我们最后还介绍了它们:模型,语言和视图。
最后,很高兴看到我在本文开头承诺的工作用例。 所以,今天就这样,不要犹豫,留下您的疑问和评论。 另外,如果您希望我在下一篇文章中提出任何特定主题,我也很乐意听取您的意见!
与往常一样,如果您正在寻找其他OpenCart工具,实用程序,扩展等,以便可以在自己的项目中使用或用于自己的教育,请不要忘记查看我们在市场上提供的产品 。
如果你喜欢这篇文章,我有几个更以防万一你想通过他们去!
翻译自: https://code.tutsplus.com/tutorials/custom-controllers-in-opencart-2--cms-28090