
OpenCart es una plataforma de comercio electrónica hecha en php, con un desarrollo impecable, 100% MVC. Como prueba de concepto he reescrito el sistema de plantillas de OpenCart a Haanga (plantillas “Django” para PHP, über eficiente) de César Rodas.
¿ Por que Haanga ?, simplemente porque me gusta.
¿ Por qué OpenCart ?, simplemente porque me gusta como está desarrollado.
Implementación, he creado una clase TemplateEngine con el siguiente código:
-
class TemplateEngine {
-
public $template = null ;
-
public $default = array();
-
public $config = array();
-
-
function __construct( $templateDir = null ) {
-
$this->loadDefaults( $templateDir);
-
}
-
-
-
protected function loadDefaults( $templateDir) {
-
$this->default = array();
-
$this->config = array(
-
'template_dir' => (( is_null( $templateDir )) ? Settings::getInstance()->getValue('Web.root') .'templates' : $templateDir),
-
'cache_dir' => Settings::getInstance()->getValue('Web.root'). 'cache.templates',
-
'compiler' => array(
-
'if_empty' => FALSE,
-
'autoescape' => FALSE,
-
'strip_whitespace' => TRUE,
-
'allow_exec' => TRUE,
-
'global' => array( ),
-
'use_hash_filename' => FALSE
-
)
-
);
-
}
-
-
function loadEngine() {
-
// incluimos Haanga
-
require_once Settings::getInstance()->getValue('Web.root') . 'lib/vendors/Haanga.php';
-
Haanga::configure($this->config);
-
-
-
-
}
-
function loadTemplate( $name ) {
-
$this->template = $name ;
-
}
-
function display( $vars = array()) {
-
$this->loadEngine();
-
$vars = array_merge( $this->default, $vars);
-
Haanga::Load( $this->template , $vars);
-
-
}
-
-
}
Ahora sólo queda indicarle al opencart que haga uso de esta clase:
en /system/engine/controller.php
Modificando los métodos render y fetch, renombrando el antiguo fetch a __fetch
-
[…]
-
protected function render($return = FALSE) {
-
foreach ($this->children as $child) {
-
$action = new Action($child);
-
$file = $action->getFile();
-
$class = $action->getClass();
-
$method = $action->getMethod();
-
$args = $action->getArgs();
-
-
if (file_exists($file)) {
-
require_once($file);
-
-
$controller = new $class($this->registry);
-
-
$controller->index();
-
$this->data[$controller->id] = $controller->output;
-
-
$this->addToModule( $controller->id, $controller->output );
-
} else {
-
exit('Error: Could not load controller ' . $child . '!');
-
}
-
}
-
-
if ($return) {
-
return $this->fetch($this->template);
-
} else {
-
$this->output = $this->fetch($this->template);
-
}
-
}
-
-
protected function addToModule( $module , $output ) {
-
$i = 0 ;
-
if ( !isset( $this->data['modules'] )) { return ;}
-
foreach( $this->data['modules'] as $item ) {
-
if ( $item['code'] == $module ) {
-
$this->data['modules'][$i]['output'] = $output;
-
return ;
-
-
}
-
$i++;
-
}
-
-
}
-
-
protected function fetch($filename) {
-
if ( substr( $_SERVER['REQUEST_URI'], 0, 7) == '/admin/') {
-
return $this->__fetch( $filename);
-
-
} else {
-
ob_start();
-
$this->templateEngine->loadTemplate( $filename );
-
$this->templateEngine->display( $this->data);
-
$content = ob_get_contents();
-
ob_end_clean();
-
return $content;
-
}
-
}
-
protected function __fetch($filename) {
-
$file = DIR_TEMPLATE . $filename;
-
if (file_exists($file)) {
-
extract($this->data);
-
ob_start();
-
-
require($file);
-
-
$content = ob_get_contents();
-
-
ob_end_clean();
-
-
return $content;
-
} else {
-
exit('Error: Could not load template ' . $file . '!');
-
}
-
}
-
-
[…]
Para evitar utilizar Haanga en la administración se comprueba que la url no sea de la administración, de ser así se utiliza el motor de plantillas original.
-
[…]
-
if ( substr( $_SERVER['REQUEST_URI'], 0, 7) == '/admin/') {
-
return $this->__fetch( $filename);
-
[…]
Una de las particularidades de las plantillas es que hacen uso de $$variable a la hora de mostrar la salida de los módulos, y es por esto (imposible, por lo que parece, en Haanga) que he añadido un método y comprobación para que cada módulo devuelva a la plantilla su salida en un elemento “output” de la matriz y es el que mostraremos.
Así, al final, una plantilla como la de la visualización de las categorías queda en algo como los siguientes ejemplos:
/catalog/view/theme/default/common/column_right.tpl
-
<div id="column_right">
-
-
{% for module in modules %}
-
-
{{ module.output }}
-
-
{% endfor %}
-
-
</div>
/catalog/view/theme/default/product/category.tpl
-
{% extends "layout/default.html" %}
-
{% block content %}
-
<div id="content">
-
<div class="top">
-
<div class="left"></div>
-
<div class="right"></div>
-
<div class="center">
-
<h1>{{ heading_title }}</h1>
-
</div>
-
</div>
-
<div class="middle">
-
<table style="padding-bottom:10px;">
-
<tr>
-
{% if thumb %}
-
<td><img src="{{ thumb }}" alt="{{ heading_title }}" /></td>
-
{% endif %}
-
{% if description %}
-
<td>{{ description }}</td>
-
{% endif %}
-
</tr>
-
</table>
-
-
{% if !categories && !products %}<div class="content">{{ text_error|default:"" }}</div>{% endif %}
-
-
{% if categories %}
-
-
<table>
-
{% for category in categories %}
-
-
-
<a href="{{ category['href'] }}"><img src="{{ category['thumb'] }}" title="{{ category['name'] }}" alt="{{ category['name'] }}" style="margin-bottom: 3px;" /></a><br />
-
<a href="{{ category['href'] }}">{{ category['name'] }}</a>
-
-
</table>
-
{% endfor %}
-
-
{% endif %}
-
-
-
-
{% if products %}
-
<div class="sort">
-
<div class="div1">
-
<select name="sort" onchange="location = this.value">
-
{% buffer sort_order %}{{sort}}-{{order}}{% endbuffer %}
-
-
{% for sort in sorts %}
-
<option value="{{ sort['href'] }}" {% if sort_order == sort['value'] %} selected="selected"{% endif %}>{{ sort['text'] }}</option>
-
{% endfor %}
-
</select>
-
</div>
-
<div class="div2">{{ text_sort }}</div>
-
</div>
-
-
-
{% inline "elements/lista_productos.html" %}
-
-
-
-
<div class="pagination">{{ pagination }}</div>
-
-
{% endif %}
-
-
</div>
-
<div class="bottom">
-
<div class="left"></div>
-
<div class="right"></div>
-
<div class="center"></div>
-
</div>
-
</div>
-
{% endblock %}




Se comenta por aquí