Advertisement
  1. Code
  2. OpenCart

Criar um plugin personalizado no OpenCart 2.1.x.x: Parte 1

Scroll to top
Read Time: 12 min

Portuguese (Português) translation by Anderson (you can also view the original English article)

Como um desenvolvedor, é sempre interessante criar materiais personalizados em qualquer estruturas, assim é para os plug-ins OpenCart também.

Nesta série de duas partes, vou explicar como desenvolver plugins personalizados no OpenCart. Do ponto de vista de um desenvolvedor iniciante, vamos passar os detalhes de desenvolvimento de extensão no OpenCart. Também criaremos um plugin personalizado pequeno para demonstrar cada aspecto da estrutura do plugin OpenCart.

Nesta primeira parte, criaremos um plug-in personalizado que ira exibir produtos novos na frente de sua loja e você poderá configurar o número de produtos no próprio painel administrativo. Este é o objetivo deste artigo que é desenvolver um plug-in de back-end com um formulário de configuração.

Eu suponho que você configurou a versão mais recente do OpenCart, que é 2.1.0.2 como de escrever isso. Antes de prosseguir e desenvolver um plugin real, eu vou orientá-lo através da arquitetura básica do OpenCart na próxima seção.

MVCL em poucas palavras

O OpenCart é desenvolvido com um dos mais populares padrões de desenvolvimento web, o padrão MVC, com uma pequena variação, ou melhor, eu diria que é uma adição. A adição é na forma de um componente de linguagem que torna MVCL no mundo do OpenCart. Pode ser que você já tenha ouvido falar deste padrão, mas para quem é iniciante, vou rapidamente resumir o que é este padrão.

O M em MVC significa modelo, e é aí que reside a maior parte da lógica desse negócio. No contexto do OpenCart, é o modelo que interage com a camada de abstração de banco de dados para fazer todo o trabalho pesado necessário para executar o armazenamento. É uma área onde você vai encontrar-se na maioria das vezes como um desenvolvedor.

Em seguida, o V significa Ver, e representa a camada de apresentação do aplicativo. Como o nome sugere, ele só lida com a lógica de apresentação de qualquer página, e recebe a entrada de outras camadas e gera a saída HTML na maioria das vezes. A lógica dessa aplicação deve ser mantida afastada dessa camada; Ele só deve se preocupar com o que fazer em vez de como fazê-lo.

É o C, o controlador, no MVC que se senta na frente de tudo, lidar com cada pedido e tratá-lo em conformidade É uma área que inclui a maior parte da lógica do aplicativo, desde manipulação e validação de entrada do usuário até o carregamento do modelo adequado e visualização de componentes para preparar a saída da página.

Finalmente, há um componente adicional, L, que significa linguagem Faz com que a criação de sites multilíngue seja bem mais facil.

Essa é uma visão rápida da arquitetura do OpenCart, e isso fará mais sentido à medida que avançarmos para a explicação detalhada de cada componente.

O esqueleto de um plugin OpenCart

Vamos dar uma rápida olhada na lista de arquivos que precisamos implementar o plug-in de back-end personalizado.

  • admin/english/portuguese-br/module/recent_products.php: É um arquivo que contém etiquetas estáticas usadas em toda a aplicação do administrador.
  • admin/controller/module/recent_products.php: É um arquivo de controlador que contém toda lógica de  aplicação do nosso módulo.
  • admin/view/template/module/recent_products.tpl: É um arquivo de modelo de visualização e contém código XHTML.

Na próxima seção, vamos criar cada arquivo mencionado acima, com uma explicação em profundidade.

De acordo com as convenções, precisamos colocar os arquivos de plug-ins personalizados no diretório do módulo. Neste caso, como estamos desenvolvendo um plugin de backend, serão os diretórios sob admin que mantêm nossos arquivos. É claro que os arquivos estão espalhados em diretórios diferentes, ou melhor, componentes, de acordo com a arquitetura OpenCart mostrada acima.

Criar arquivos para o plug-in de back-end

Nesta seção, começaremos a criar os arquivos do módulo. Primeiro, criaremos um arquivo de idiomaadmin/language/english/module/recent_products.phpCom o seguinte conteúdo É um arquivo importante do ponto de vista do OpenCart, pois é uma obrigação para seu plugin ser detectado pelo OpenCart.

1
<?php
2
// admin/language/english/module/recent_products.php

3
// Heading

4
$_['heading_title']    = 'Recent Products';
5
6
// Text

7
$_['text_module']      = 'Modules';
8
$_['text_success']     = 'Success: You have modified Recent Products module!';
9
$_['text_edit']        = 'Edit Recent Products Module';
10
11
// Entry

12
$_['entry_name']       = 'Module Name';
13
$_['entry_limit']      = 'Limit';
14
$_['entry_status']     = 'Status';
15
16
// Error

17
$_['error_permission'] = 'Warning: You do not have permission to modify Recent Products module!';
18
$_['error_name']       = 'Module Name must be between 3 and 64 characters!';

Como você pode ver, estamos atribuindo rótulos estáticos a um array PHP. Mais adiante, você terá acesso a essas variáveis no arquivo de modelo de visualização conforme a matriz é convertida em variáveis PHP.

Você também pode ter notado que o arquivo é criado sob o diretório em english, pois é o idioma padrão da loja. Naturalmente, no caso de um site multilíngue, você precisará certificar-se de que você criá-lo para outros idiomas também. Por exemplo, a versão portugues do mesmo arquivo deve ser criada em:admin/language/portuguese-br/module/recent_products.php

Em seguida, criaremos um dos arquivos de plug-ins mais importantes: o arquivo do controlador. Vamos em frente e criaradmin/controller/module/recent_products.phpCom o seguinte conteúdo.

1
<?php
2
// admin/controller/module/recent_products.php

3
class ControllerModuleRecentProducts extends Controller {
4
    private $error = array();
5
6
    public function index() {
7
        $this->load->language('module/recent_products');
8
9
        $this->document->setTitle($this->language->get('heading_title'));
10
11
        $this->load->model('extension/module');
12
13
        if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
14
            if (!isset($this->request->get['module_id'])) {
15
                $this->model_extension_module->addModule('recent_products', $this->request->post);
16
            } else {
17
                $this->model_extension_module->editModule($this->request->get['module_id'], $this->request->post);
18
            }
19
20
            $this->session->data['success'] = $this->language->get('text_success');
21
22
            $this->response->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));
23
        }
24
25
        $data['heading_title'] = $this->language->get('heading_title');
26
27
        $data['text_edit'] = $this->language->get('text_edit');
28
        $data['text_enabled'] = $this->language->get('text_enabled');
29
        $data['text_disabled'] = $this->language->get('text_disabled');
30
31
        $data['entry_name'] = $this->language->get('entry_name');
32
        $data['entry_limit'] = $this->language->get('entry_limit');
33
        $data['entry_status'] = $this->language->get('entry_status');
34
35
        $data['button_save'] = $this->language->get('button_save');
36
        $data['button_cancel'] = $this->language->get('button_cancel');
37
38
        if (isset($this->error['warning'])) {
39
            $data['error_warning'] = $this->error['warning'];
40
        } else {
41
            $data['error_warning'] = '';
42
        }
43
44
        if (isset($this->error['name'])) {
45
            $data['error_name'] = $this->error['name'];
46
        } else {
47
            $data['error_name'] = '';
48
        }
49
50
        $data['breadcrumbs'] = array();
51
52
        $data['breadcrumbs'][] = array(
53
            'text' => $this->language->get('text_home'),
54
            'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
55
        );
56
57
        $data['breadcrumbs'][] = array(
58
            'text' => $this->language->get('text_module'),
59
            'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')
60
        );
61
62
        if (!isset($this->request->get['module_id'])) {
63
            $data['breadcrumbs'][] = array(
64
                'text' => $this->language->get('heading_title'),
65
                'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL')
66
            );
67
        } else {
68
            $data['breadcrumbs'][] = array(
69
                'text' => $this->language->get('heading_title'),
70
                'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL')
71
            );
72
        }
73
74
        if (!isset($this->request->get['module_id'])) {
75
            $data['action'] = $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL');
76
        } else {
77
            $data['action'] = $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL');
78
        }
79
80
        $data['cancel'] = $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL');
81
82
        if (isset($this->request->get['module_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
83
            $module_info = $this->model_extension_module->getModule($this->request->get['module_id']);
84
        }
85
86
        if (isset($this->request->post['name'])) {
87
            $data['name'] = $this->request->post['name'];
88
        } elseif (!empty($module_info)) {
89
            $data['name'] = $module_info['name'];
90
        } else {
91
            $data['name'] = '';
92
        }
93
94
        if (isset($this->request->post['limit'])) {
95
            $data['limit'] = $this->request->post['limit'];
96
        } elseif (!empty($module_info)) {
97
            $data['limit'] = $module_info['limit'];
98
        } else {
99
            $data['limit'] = 5;
100
        }
101
102
        if (isset($this->request->post['status'])) {
103
            $data['status'] = $this->request->post['status'];
104
        } elseif (!empty($module_info)) {
105
            $data['status'] = $module_info['status'];
106
        } else {
107
            $data['status'] = '';
108
        }
109
110
        $data['header'] = $this->load->controller('common/header');
111
        $data['column_left'] = $this->load->controller('common/column_left');
112
        $data['footer'] = $this->load->controller('common/footer');
113
114
        $this->response->setOutput($this->load->view('module/recent_products.tpl', $data));
115
    }
116
117
    protected function validate() {
118
        if (!$this->user->hasPermission('modify', 'module/recent_products')) {
119
            $this->error['warning'] = $this->language->get('error_permission');
120
        }
121
122
        if ((utf8_strlen($this->request->post['name']) < 3) || (utf8_strlen($this->request->post['name']) > 64)) {
123
            $this->error['name'] = $this->language->get('error_name');
124
        }
125
126
        return !$this->error;
127
    }
128
}

Ele define a nova classe para o nosso plugin personalizado que estende a classe de Controller base. Conforme as convenções, o nome da classe deve imitar a estrutura de diretório sob a qual o arquivo é colocado. Assim, o caminho controller/module/recent_products.phpÉ convertido para ControllerModuleRecentProductssubstituindo a barra e caracteres sublinhado de acordo!

Em seguida, há um método index de fato que é chamado quando o plugin é carregado no front-end. Portanto, é um método de index que define a maior parte da lógica da aplicação do plug-in.

No contexto do presente pedido, a abreviatura$this->load->languageCarrega o arquivo de idioma correspondente. No nosso caso, ele carrega o arquivo de idioma definido na seção anterior. A sintaxe é bastante simples - você só precisa passar o nome do plugin prefixado por module/ As variáveis de idioma podem ser acessadas$this->language->getPelo método

Em seguida, define o título da página usando o método setTitle do objeto de documento.

Avançando, o modelo $this->load->model é usado para carregar o modelo do módulo. É a classe do modelo que fornece métodos de utilidade para salvar os parâmetros do módulo e similares.

Em seguida, há um trecho importante como mostrado abaixo que verifica se é POST envio de dados e salva a configuração do módulo nesse caso.

1
if (($this->request->server['REQUEST_METHOD'] == 'POST') && $this->validate()) {
2
    if (!isset($this->request->get['module_id'])) {
3
        $this->model_extension_module->addModule('recent_products', $this->request->post);
4
    } else {
5
        $this->model_extension_module->editModule($this->request->get['module_id'], $this->request->post);
6
    }
7
8
    $this->session->data['success'] = $this->language->get('text_success');
9
    $this->response->redirect($this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL'));
10
}

Além disso, estamos atribuindo rótulos de idioma como heading_title e text_edit à matriz de $data para que possamos usá-los no arquivo de modelo de visualização

Em seguida, há um snippet que constrói os links de breadcrumb corretos para a página de configuração.

1
$data['breadcrumbs'] = array();
2
3
$data['breadcrumbs'][] = array(
4
    'text' => $this->language->get('text_home'),
5
    'href' => $this->url->link('common/dashboard', 'token=' . $this->session->data['token'], 'SSL')
6
);
7
8
$data['breadcrumbs'][] = array(
9
    'text' => $this->language->get('text_module'),
10
    'href' => $this->url->link('extension/module', 'token=' . $this->session->data['token'], 'SSL')
11
);
12
13
if (!isset($this->request->get['module_id'])) {
14
    $data['breadcrumbs'][] = array(
15
        'text' => $this->language->get('heading_title'),
16
        'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'], 'SSL')
17
    );
18
} else {
19
    $data['breadcrumbs'][] = array(
20
        'text' => $this->language->get('heading_title'),
21
        'href' => $this->url->link('module/recent_products', 'token=' . $this->session->data['token'] . '&module_id=' . $this->request->get['module_id'], 'SSL')
22
    );
23
}

Se o módulo já tivesse sido configurado anteriormente e no modo de edição, o snippet a seguir preencherá a configuração de módulo padrão.

1
if (isset($this->request->get['module_id']) && ($this->request->server['REQUEST_METHOD'] != 'POST')) {
2
    $module_info = $this->model_extension_module->getModule($this->request->get['module_id']);
3
}

Finalmente, estamos carregando os elementos de página comuns como cabeçalho, rodapé e barra lateral esquerda. Exibe o arquivo recent_products.tpl e exibe o formulário de configuração

Há algumas notas importantes a serem lembradas no arquivo do controlador. Você verá muitas chamadas como $this-> load-> ELEMENT, onde ELEMENT pode ser view, model ou language. Ele carrega os componentes de view, model e language  correspondentes

O próximo e último arquivo para o artigo de hoje é um arquivo de template view admin/view/template/module/recent_products.tpl Vá em frente e criá-lo!

1
<!-- admin/view/template/module/recent_products.tpl -->
2
<?php echo $header; ?><?php echo $column_left; ?>
3
<div id="content">
4
  <div class="page-header">
5
    <div class="container-fluid">
6
      <div class="pull-right">
7
        <button type="submit" form="form-recent-products" data-toggle="tooltip" title="<?php echo $button_save; ?>" class="btn btn-primary"><i class="fa fa-save"></i></button>
8
        <a href="<?php echo $cancel; ?>" data-toggle="tooltip" title="<?php echo $button_cancel; ?>" class="btn btn-default"><i class="fa fa-reply"></i></a></div>
9
      <h1><?php echo $heading_title; ?></h1>
10
      <ul class="breadcrumb">
11
        <?php foreach ($breadcrumbs as $breadcrumb) { ?>
12
        <li><a href="<?php echo $breadcrumb['href']; ?>"><?php echo $breadcrumb['text']; ?></a></li>
13
        <?php } ?>
14
      </ul>
15
    </div>
16
  </div>
17
  <div class="container-fluid">
18
    <?php if ($error_warning) { ?>
19
    <div class="alert alert-danger"><i class="fa fa-exclamation-circle"></i> <?php echo $error_warning; ?>
20
      <button type="button" class="close" data-dismiss="alert">&times;</button>
21
    </div>
22
    <?php } ?>
23
    <div class="panel panel-default">
24
      <div class="panel-heading">
25
        <h3 class="panel-title"><i class="fa fa-pencil"></i> <?php echo $text_edit; ?></h3>
26
      </div>
27
      <div class="panel-body">
28
        <form action="<?php echo $action; ?>" method="post" enctype="multipart/form-data" id="form-recent-products" class="form-horizontal">
29
          <div class="form-group">
30
            <label class="col-sm-2 control-label" for="input-name"><?php echo $entry_name; ?></label>
31
            <div class="col-sm-10">
32
              <input type="text" name="name" value="<?php echo $name; ?>" placeholder="<?php echo $entry_name; ?>" id="input-name" class="form-control" />
33
              <?php if ($error_name) { ?>
34
              <div class="text-danger"><?php echo $error_name; ?></div>
35
              <?php } ?>
36
            </div>
37
          </div>
38
          <div class="form-group">
39
            <label class="col-sm-2 control-label" for="input-limit"><?php echo $entry_limit; ?></label>
40
            <div class="col-sm-10">
41
              <input type="text" name="limit" value="<?php echo $limit; ?>" placeholder="<?php echo $entry_limit; ?>" id="input-limit" class="form-control" />
42
            </div>
43
          </div>
44
          <div class="form-group">
45
            <label class="col-sm-2 control-label" for="input-status"><?php echo $entry_status; ?></label>
46
            <div class="col-sm-10">
47
              <select name="status" id="input-status" class="form-control">
48
                <?php if ($status) { ?>
49
                <option value="1" selected="selected"><?php echo $text_enabled; ?></option>
50
                <option value="0"><?php echo $text_disabled; ?></option>
51
                <?php } else { ?>
52
                <option value="1"><?php echo $text_enabled; ?></option>
53
                <option value="0" selected="selected"><?php echo $text_disabled; ?></option>
54
                <?php } ?>
55
              </select>
56
            </div>
57
          </div>
58
        </form>
59
      </div>
60
    </div>
61
  </div>
62
</div>
63
<?php echo $footer; ?>

Usuários com olhos afiados já terão notado que ele está apenas exibindo as variáveis que foram passadas do arquivo do controlador. Além disso, é simples código XHTML para exibir o formulário de configuração, é a cereja no topo do bolo.

Então, é isso, tanto quanto a configuração do arquivo está em causa para o nosso plug-in personalizado back-end.

Ativar o Plugin

Vá até o back-end do OpenCart e navegue até Extensões> Módulos. Você deve ver Produtos recentes na lista de modulos. Clique no sinal + para instalar o módulo, conforme mostrado na seguinte captura de tela.

Back-End ListingBack-End ListingBack-End Listing

Uma vez instalado, você verá um ícone de edição. Clique nesse botão para abrir o formulário de configuração do módulo.

Configuration FormConfiguration FormConfiguration Form

No formulário de configuração, você pode definir o número de produtos recentes que deseja exibir no bloco front-end. Além disso, não se esqueça de definir o campo de status como Habilitado! Salve o módulo, e ele deve ser algo parecido com isto.

Replicated ModuleReplicated ModuleReplicated Module

Há uma nova entrada para o módulo intitulado Produtos recentes> My Recent Block Plugin. A razão é que você pode replicá-lo várias vezes para páginas diferentes!

Então, estamos quase terminando! Fizemos um plugin personalizado de back-end completo no OpenCart. Na próxima parte, iremos passar pela parte frontal do mesmo que exibe um bloco de produtos bonitos no front-end!

Conclusão

Hoje, discutimos o desenvolvimento de plug-ins personalizados no OpenCart. Na primeira parte desta série de duas partes, passamos pelo desenvolvimento de plug-ins de back-end e criamos um plugin personalizado de trabalho que fornece um formulário de configuração.

Se você está procurando ferramentas OpenCart adicionais, utilitários, extensões e assim por diante que você pode aproveitar em seus próprios projetos ou para sua própria educação, ver o que temos disponíveis no mercado.

Na próxima parte, completaremos o plug-in criando a parte front-end que exibe as listagens de produtos no front-end. Para quaisquer dúvidas e comentários, use o feed de comentários abaixo.

Advertisement
Did you find this post useful?
Want a weekly email summary?
Subscribe below and we’ll send you a weekly email summary of all new Code tutorials. Never miss out on learning about the next big thing.
Advertisement
Looking for something to help kick start your next project?
Envato Market has a range of items for sale to help get you started.