Back-End

8 abr, 2015

Trabalhando com framework CodeIgniter HMVC, template Smarty e Doctrine ORM

Publicidade

Este é um artigo para mostrar como combinar o framework CodeIgniter HMVC com template Smarty e Doctrine ORM.

Leia este texto para saber como podemos usar vários comandos ORM em seus sites sem a necessidade de usar ferramentas de linha de comando.

O artigo apresenta um projeto de exemplo que você pode usar como ponto de partida para os seus próprios projetos PHP.

Começando

Neste artigo, vamos combinar os seguintes pacotes em conjunto:

  1. CodeIgniter 2.2.0
  2. Extensões modulares CodeIgniter
  3. Smarty 3.1.21
  4. Doctrine 2.2.3

Você precisa fazer o download deste pacote ORM.

Comece baixando o CodeIgniter 2.2.0. Extraia-o para a pasta www do seu servidor web. Navegue até /index.php/welcome. Você deverá ver a página de boas-vindas do CodeIgniter.

Configuração CI

  1. Abra /application/config/config.php em um editor de sua escolha.
  2. Remova index.php da Linha #29. Depois de editada, a linha deve se parecer com o seguinte:
$ config ['index_page'] = '';
  1. Na linha 227 do arquivo de configuração, defina uma chave de encriptação aleatória.
  2. Na linha 344, mude rewrite_short_tags de FALSE para TRUE. Depois da edição, a linha deve se parecer com o seguinte:
$ config ['rewrite_short_tags'] = TRUE;
  1. Salvar e fechar o arquivo.
  2. Crie um novo arquivo na pasta raiz do seu projeto chamado .htaccess e escreva o seguinte nele:
 php_flag display_errors off
 AddType text/x-component .htc
 <IfModule mod_rewrite.c>
  DirectoryIndex index.php
  RewriteEngine On
  RewriteCond $1 !^(index\.php|assets|robots\.txt|favicon\.ico)
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule ^(.*)$ index.php/$1 [L]
 </IfModule>
 <IfModule !mod_rewrite.c>
  ErrorDocument 404 /index.php
 </IfModule>

 # BEGIN REQUIRED FOR WEBFONTS
 AddType font/ttf .ttf
 AddType font/eot .eot
 AddType font/otf .otf
 AddType font/woff .woff
 <FilesMatch "\.(ttf|otf|eot|woff)quot;>
 <IfModule mod_headers.c>
  Header set Access-Control-Allow-Origin "*"
 </IfModule>
 </FilesMatch>
 # END REQUIRED FOR WEBFONTS

7. Navegue até /welcome e, nesse momento, você deve ver a página de boas-vindas do CI.

Convertendo para utilizar CodeIgniter com padrão HMVC usando extensões modulares

O HMVC faz o framework modular CodeIgniter PHP. Os módulos são grupos de componentes independentes, tipicamente model, controller e view, dispostos em subdiretórios de módulos de aplicativos que pode ser colocado em outros aplicativos CodeIgniter.

HMVC significa Hierarchical Model View Controller. Os controllers de módulo podem ser usados como controllers normais ou controllers HMVC, e podem ser usados como widgets para ajudar a criar views parciais.

Instalação:

  1. Faça o download e extraia extensões modulares CI a partir do link acima.
  2. Despeje arquivos das extensões modulares de terceiros no seu diretório application/third_party.
  3. Despeje os arquivos principais das extensões modulares em application/core.
  4. Acesse a URL / welcome => shows Welcome to CodeIgniter.
  5. Crie estrutura de módulo de diretório de application/modules welcome/controllers.
  6. Mova o controller application/controllers/ welcome.php para application/modules/welcome/controllers/welcome.php.
  7. Acesse a URL / welcome => shows Welcome to CodeIgniter.
  8. Crie o diretório application/modules/welcome/views.
  9. Mova applications/views/welcome_message.php para application/modules/welcome/views/welcome_message.php.
  10. Acesse a URL / welcome => shows Welcome to CodeIgniter.

Se você conseguir ver a página de boas-vindas corretamente, então instalou com sucesso o padrão HMVC em CI.

Instalando Smarty

Smarty é um sistema de templates para PHP, facilitando a separação de apresentação (HTML/CSS) da lógica do aplicativo. Isso implica que o código PHP e a lógica do aplicativo estão separados da apresentação.

“Por baixo dos panos”, o Smarty compila as cópias dos templates como scripts PHP. Dessa forma, você obtém os benefícios de usar a sintaxe de tags no template e também velocidade do PHP.

A compilação acontece quando cada template é processado pela primeira vez e, em seguida, as versões compiladas são utilizadas a partir daquele momento. O Smarty cuida disso para você, então, o designer do template só edita os templates Smarty e nunca tem que gerenciar as versões compiladas.

Essa abordagem torna os templates fáceis de manter e ainda mantém a execução extremamente rápida. Como as versões compiladas são PHP, aceleradores op-code, como APC ou ZendCache, continuam a funcionar nos scripts compilados.

Instalação:

  1. Faça o download e extraia o Smarty partir do link acima.
  2. Crie a estrutura de diretório smarty /application/third_party /Smarty.
  3. Copie os arquivos libs da pasta extraída para a pasta /third_party /Smarty.
  4. Crie a estrutura de diretório /application/cache/smarty/cache.
  5. Crie a estrutura de diretório /application/cache/smarty/compiled.
  6. Certifique-se de que ambas as pastas acima têm acesso de gravação.
  7. Crie e abra um arquivo em /application/core/MY_Output.php e preencha com o seguinte conteúdo:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
 * Turn Smarty debug compatible whith Ci-Smarty parse fetch method
 *
 * Responsible for sending debug Smarty final output to browser (Smarty_Internal_Debug::display_debug) 
 * using debug console (pop-window)
 * (tks for Redn0x - http://www.smarty.net/docs/en/chapter.debugging.console.tpl)
 *
 * @category Output
 * @package  CodeIgniter
 * @author   Tariqul Islam <tareq@webkutir.net>
 * @license  http://directory.fsf.org/wiki/License:ReciprocalPLv1.3 Reciprocal Public License v1.3
 * @link     http://webkutir.net
*/
class MY_Output extends CI_Output
{
    /**
     * _display
     *
     * Turn Smarty debug compatible whith Ci-Smarty parse fetch method
     *
     * @param string $output output of the method
     *
     * @return void
     */
    function _display($output = '')
    {
        parent::_display($output);
        //If Smarty is active - NOTE: $this->output->enable_profiler(TRUE) active Smarty debug to simplify
        if (class_exists('CI_Controller') 
            && class_exists('Smarty_Internal_Debug') 
            && (config_item('smarty_debug') || $this->enable_profiler)
        ) {
            $CI =& get_instance();
            Smarty_Internal_Debug::display_debug($CI->smarty);
        }
    }
}
// END MY_Output Class
/* End of file MY_Output.php */
/* Location: ./application/core/MY_Output.php */
  1. Salve e feche o arquivo. Esse arquivo será usado para mostrar informações de depuração sobre Smarty quando o debug do Smarty estiver ativado.
  2. Crie e abra um arquivo em /application/config/smarty.php e preencha-o com o seguinte conteúdo:
<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/**
 * CI Smarty
 *
 * Smarty templating for Codeigniter
 *
 * @package   CI Smarty
 * @author    Dwayne Charrington
 * @copyright Copyright (c) 2012 Dwayne Charrington and Github contributors
 * @link      http://ilikekillnerds.com
 * @license   http://www.apache.org/licenses/LICENSE-2.0.html
 * @version   2.0
 */
// Smarty caching enabled by default unless explicitly set to FALSE
$config['cache_status']         = TRUE;
// The path to the themes
// Default is implied root directory/themes/
$config['theme_path'] = 'themes/';
// The default name of the theme to use (this can be overridden)
$config['theme_name'] = "default";
// Cache lifetime. Default value is 3600 seconds (1 hour) Smarty's default value
$config['cache_lifetime']       = 3600;
// Where templates are compiled
$config['compile_directory']    = APPPATH."cache/smarty/compiled/";
// Where templates are cached
$config['cache_directory']      = APPPATH."cache/smarty/cache/";
// Where Smarty configs are located
$config['config_directory']     = APPPATH."third_party/Smarty/configs/";
// Where my plugins are located
$config['plugins_directory']     = APPPATH."third_party/Smarty/myplugins/";
// Default extension of templates if one isn't supplied
$config['template_ext']         = 'tpl';
// Error reporting level to use while processing templates
$config['template_error_reporting'] = E_ALL & ~E_NOTICE;
// Debug mode turned on or off (TRUE / FALSE)
$config['smarty_debug'] = FALSE;
  1. Salve e feche o arquivo. Esse arquivo será usado para configurar Smarty na CI. Defina smarty debug para TRUE na linha 48, se você precisa habilitar a depuração.
  2. Crie e abra um arquivo em /application/libraries/smarty.php e preencha-o com o seguinte conteúdo:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
require_once APPPATH."third_party/Smarty/SmartyBC.class.php";

/**
 * CI Smarty
 *
 * Smarty templating for Codeigniter
 *
 * @category CodeIgniter
 * @package  CI_Smarty
 * @author   Dwayne Charrington <email@email.com>
 * @license  http://www.apache.org/licenses/LICENSE-2.0.html Apache License
 * @link     http://ilikekillnerds.com
 */
class CI_Smarty extends SmartyBC
{
    public $template_ext = '.php';
    /**
     * Class Constructor
     */
    public function __construct()
    {
        parent::__construct();
        // Store the Codeigniter super global instance... whatever
        $CI = get_instance();
        // Load the Smarty config file
        $CI->load->config('smarty');
        // Turn on/off debug
        $this->debugging = config_item('smarty_debug');
        // Set some pretty standard Smarty directories
        $this->setCompileDir(config_item('compile_directory'));
        $this->setCacheDir(config_item('cache_directory'));
        $this->setConfigDir(config_item('config_directory'));
        $this->addPluginsDir(config_item('plugins_directory'));
        // Default template extension
        $this->template_ext = config_item('template_ext');
        $this->force_compile = 1;
        // How long to cache templates for
        $this->cache_lifetime = config_item('cache_lifetime');
        // Disable Smarty security policy
        $this->disableSecurity();
        // If caching is enabled, then disable force compile and enable cache
        if (config_item('cache_status') === true) {
            $this->enable_caching();
        } else {
            $this->disable_caching();
        }
        // Set the error reporting level
        $this->error_reporting   = config_item('template_error_reporting');
        // This will fix various issues like filemtime errors that some people experience
        // The cause of this is most likely setting the error_reporting value above
        // This is a static function in the main Smarty class
        //Smarty::muteExpectedErrors();
        // Should let us access Codeigniter stuff in views
        // This means we can go for example {$this->session->userdata('item')}
        // just like we normally would in standard CI views
        $this->assign("this", $CI);
        //My Vars
        $this->assign('APPPATH', APPPATH);
        $this->assign('BASEPATH', BASEPATH);
        $this->assign('systemurl', base_url());
        $this->assign('template', 'default');
        $this->assign("CI", $CI);
    }
    /**
     * Enable Caching
     *
     * Allows you to enable caching on a page by page basis
     * 
     * @example $this->smarty->enable_caching(); then do your parse call
     * 
     * @return void
     */
    public function enable_caching()
    {
        $this->caching = 1;
    }
    /**
     * Disable Caching
     *
     * Allows you to disable caching on a page by page basis
     * 
     * @example $this->smarty->disable_caching(); then do your parse call
     * 
     * @return void
     */
    public function disable_caching()
    {
        $this->caching = 0; 
    }
}
  1. Salve e feche o arquivo.
  2. Crie e abra um arquivo em /application/helpers/parser_helper.php e preencha-o com o seguinte conteúdo:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
 * CI Smarty
 *
 * Smarty templating for Codeigniter
 *
 * @package   CI Smarty
 * @author    Dwayne Charrington
 * @copyright Copyright (c) 2012 Dwayne Charrington and Github contributors
 * @link      http://ilikekillnerds.com
 * @license   http://www.apache.org/licenses/LICENSE-2.0.html
 * @version   2.0
 */
/**
 * Theme URL
 *
 * A helper function for getting the current theme URL
 * in a web friendly format.
 *
 * @param string $location Theme Location
 * 
 * @return mixed
 */
function theme_url($location = '')
{
    $CI =& get_instance();
    return $CI->parser->theme_url($location);
}
/**
 * CSS
 *
 * A helper function for getting the current theme CSS embed code
 * in a web friendly format
 *
 * @param string $file       File Name
 * @param array  $attributes Array of the Attributes
 * 
 * @return void
 */
function css($file, $attributes = array())
{
    $CI =& get_instance();
    echo $CI->parser->css($file, $attributes);
}
/**
 * JS
 *
 * A helper function for getting the current theme JS embed code
 * in a web friendly format
 *
 * @param string $file       File Name
 * @param array  $attributes Array of the Attributes
 * 
 * @return void
 */
function js($file, $attributes = array())
{
    $CI =& get_instance();
    echo $CI->parser->js($file, $attributes);
}
/**
 * IMG
 *
 * A helper function for getting the current theme IMG embed code
 * in a web friendly format
 *
 * @param string $file       File Name
 * @param array  $attributes Array of the Attributes
 * 
 * @return void
 */
function img($file, $attributes = array())
{
    $CI =& get_instance();
    echo $CI->parser->img($file, $attributes);
}
  1. Salve e feche o arquivo.
  2. Crie e abra um arquivo em /application/libraries/MY_Parser.php e preencha-o com o seguinte conteúdo:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
 * CI Smarty
 *
 * Smarty templating for Codeigniter
 *
 * @category CodeIgniter
 * @package  CI_Smarty
 * @author   Dwayne Charrington <email@email.com>
 * @license  http://www.apache.org/licenses/LICENSE-2.0.html Apache License Version 2.0
 * @link     http://ilikekillnerds.com
 */
class MY_Parser extends CI_Parser
{
    protected $CI;
    protected $_module = '';
    protected $_template_locations = array();
    // Current theme location
    protected $_current_path = null;
    // The name of the theme in use
    protected $_theme_name = '';
    /**
     * Class Constructor
     */
    public function __construct()
    {
        // Codeigniter instance and other required libraries/files
        $this->CI =& get_instance();
        //$this->CI->load->library('smarty');
        $this->CI->load->helper('parser');
        // Detect if we have a current module
        if ($this->_module=='') {
            $this->_module = $this->current_module();
        }
        // What controllers or methods are in use
        $this->_controller  = $this->CI->router->fetch_class();
        $this->_method      = $this->CI->router->fetch_method();
        // If we don't have a theme name stored
        if ($this->_theme_name == '') {
            $this->set_theme(config_item('theme_name'));
        }
        // Update theme paths
        $this->_update_theme_paths();
    }
    /**
     * Set the Module
     *
     * @param string $module Name of the Module to set
     *
     * @return void
     */
    public function setModule($module)
    {
        $this->_module=$module;
        $this->_update_theme_paths();
    }
    /**
     * Get the Module
     *
     * @return void
     */
    public function getModule()
    {
        return $this->_module;
    }
    /**
     * Call
     * able to call native Smarty methods
     *
     * @param string $method Name of Method
     * @param array  $params Array of the Params
     *
     * @return mixed
     */
    public function __call($method, $params=array())
    {
        if (!method_exists($this, $method)) {
            return call_user_func_array(array($this->CI->smarty, $method), $params);
        }
    }
    /**
     * Set Theme
     *
     * Set the theme to use
     *
     * @param string $name Name of the Theme to set
     *
     * @return string
     */
    public function set_theme($name)
    {
        // Store the theme name
        $this->_theme_name = trim($name);
        // Our themes can have a functions.php file just like WordPress
        $functions_file  = config_item('theme_path') . $this->_theme_name . '/functions.php';
        // Incase we have a theme in the application directory
        $functions_file2 = APPPATH."themes/" . $this->_theme_name . '/functions.php';
        // If we have a functions file, include it
        if (file_exists($functions_file)) {
            include_once $functions_file;
        } elseif (file_exists($functions_file2)) {
            include_once $functions_file2;
        }
        // Update theme paths
        $this->_update_theme_paths();
    }
    /**
     * Get Theme
     *
     * Does what the function name implies: gets the name of
     * the currently in use theme.
     *
     * @return string
     */
    public function get_theme()
    {
        return (isset($this->_theme_name)) ? $this->_theme_name : '';
    }
    /**
     * Current Module
     *
     * Just a fancier way of getting the current module
     * if we have support for modules
     *
     * @return string
     */
    public function current_module()
    {
        // Modular Separation / Modular Extensions has been detected
        if (method_exists($this->CI->router, 'fetch_module')) {
            $module = $this->CI->router->fetch_module();
            return (!empty($module)) ? $module : '';
        } else {
            return '';
        }
    }
    /**
     * Parse
     *
     * Parses a template using Smarty 3 engine
     *
     * @param string  $template Name of the Template
     * @param array   $data     Array of Data
     * @param boolean $return   Indicates if it return the view or not
     * @param boolean $caching  Indicates if caching is enabled or not
     * @param string  $theme    Theme Name
     *
     * @return string
     */
    public function parse($template, $data = array(), $return = false, $caching = true, $theme = '')
    {
        // Check the Permission and read dir if necessary
        /*
        if (is_array($this->CI->session->userdata('permission'))
            && in_array("all", $this->CI->session->userdata('permission'))
        ) {
            $this->CI->load->helper('file');
            $data['files']=get_filenames(APPPATH.'views/default/navigation/');
            sort($data['files']);
        }
        */
        // If we don't want caching, disable it
        if ($caching === false) {
            $this->CI->smarty->disable_caching();
        }
        // If no file extension dot has been found default to defined extension for view extensions
        if ( ! stripos($template, '.')) {
            $template = $template.".".$this->CI->smarty->template_ext;
        }
        // Are we overriding the theme on a per load view basis?
        if ($theme !== '') {
            $this->set_theme($theme);
        }
        // Get the location of our view, where the hell is it?
        // But only if we're not accessing a smart resource
        if ( ! stripos($template, ':')) {
            $template = $this->_find_view($template);
        }
        // If we have variables to assign, lets assign them
        if ( ! empty($data)) {
            foreach ($data AS $key => $val) {
                $this->CI->smarty->assign($key, $val);
            }
        }
        // Load our template into our string for judgement
        $template_string = $this->CI->smarty->fetch($template);
        // If we're returning the templates contents, we're displaying the template
        if ($return === false) {
            $this->CI->output->append_output($template_string);
            return true;
        }
        // We're returning the contents, fo' shizzle
        return $template_string;
    }
    /**
     * CSS
     *
     * An asset function that returns a CSS stylesheet
     *
     * @param string $file       File Name
     * @param array  $attributes Attributes array
     *
     * @return string
     */
    public function css($file, $attributes = array())
    {
        $defaults = array(
                'media' => 'screen',
                'rel'   => 'stylesheet',
                'type'  => 'text/css'
        );
        $attributes = array_merge($defaults, $attributes);
        $return  = '<link rel="'.$attributes['rel'].'" type="'.$attributes['type'].'" ';
        $return .= 'href="'.base_url(config_item('theme_path').$this->get_theme()."/css/".$file);
        $return .= '" media="'.$attributes['media'].'">';
        return $return;
    }
    /**
     * JS
     *
     * An asset function that returns a script embed tag
     *
     * @param string $file       File Name
     * @param array  $attributes Attributes array
     *
     * @return string
     */
    public function js($file, $attributes = array())
    {
        $defaults = array(
                'type'  => 'text/javascript'
        );
        $attributes = array_merge($defaults, $attributes);
        $return = '<script type="'.$attributes['type'].'" src="'.
                base_url(config_item('theme_path').$this->get_theme()."/js/".$file).'"></script>';
        return $return;
    }
    /**
     * IMG
     *
     * An asset function that returns an image tag
     *
     * @param string $file       File Name
     * @param array  $attributes Attributes array
     *
     * @return string
     */
    public function img($file, $attributes = array())
    {
        $defaults = array(
                'alt'    => '',
                'title'  => ''
        );
        $attributes = array_merge($defaults, $attributes);
        $return = '<img src ="'.base_url(config_item('theme_path').$this->get_theme()."/img/".$file).
        '" alt="'.$attributes['alt'].'" title="'.$attributes['title'].'" />';
        return $return;
    }
    /**
     * Theme URL
     *
     * A web friendly URL for determining the current
     * theme root location.
     *
     * @param string $location Theme Location
     *
     * @return string
     */
    public function theme_url($location = '')
    {
        // The path to return
        $return = base_url(config_item('theme_path').$this->get_theme())."/";
        // If we want to add something to the end of the theme URL
        if ($location !== '') {
            $return = $return.$location;
        }
        return trim($return);
    }
    /**
     * Find View
     *
     * Searches through module and view folders looking for your view, sir.
     *
     * @param string $file File Name
     *
     * @return string The path and file found
     */
    protected function _find_view($file)
    {
        // We have no path by default
        $path = null;
        // Iterate over our saved locations and find the file
        foreach ($this->_template_locations AS $location) {
            if (file_exists($location.$file)) {
                // Store the file to load
                $path = $location.$file;
                $this->_current_path = $location;
                // Stop the loop, we found our file
                break;
            }
        }
        // Return the path
        return $path;
    }
    /**
     * Add Paths
     *
     * Traverses all added template locations and adds them
     * to Smarty so we can extend and include view files
     * correctly from a slew of different locations including
     * modules if we support them.
     *
     * @return void
     */
    protected function _add_paths()
    {
        // Iterate over our saved locations and find the file
        foreach ($this->_template_locations AS $location) {
            $this->CI->smarty->addTemplateDir($location);
        }
    }
    /**
     * Update Theme Paths
     *
     * Adds in the required locations for themes
     *
     * @return void
     */
    protected function _update_theme_paths()
    {
        // Store a whole heap of template locations
        $this->_template_locations = array(
                config_item('theme_path') . $this->_theme_name . '/views/modules/' . $this->_module .'/layouts/',
                config_item('theme_path') . $this->_theme_name . '/views/modules/' . $this->_module .'/',
                config_item('theme_path') . $this->_theme_name . '/views/layouts/',
                config_item('theme_path') . $this->_theme_name . '/views/',
                APPPATH . 'modules/' . $this->_module . '/views/layouts/',
                APPPATH . 'modules/' . $this->_module . '/views/' . $this->_theme_name . '/',
                APPPATH . 'modules/' . $this->_module . '/views/',
                APPPATH . 'views/layouts/',
                APPPATH . 'views/',
                APPPATH . 'views/' . $this->_theme_name . '/'
        );
        // Will add paths into Smarty for "smarter" inheritance and inclusion
        $this->_add_paths();
    }
    /**
     * String Parse
     *
     * Parses a string using Smarty 3
     *
     * @param string  $template   Template Name
     * @param array   $data       Data Array
     * @param boolean $return     Indicates if it will be returned or not
     * @param boolean $is_include Indicates if included or not
     *
     * @return void
     */
    public function string_parse($template, $data = array(), $return = false, $is_include = false)
    {
        return $this->CI->smarty->fetch('string:'.$template, $data);
    }
    /**
     * Parse String
     *
     * Parses a string using Smarty 3. Never understood why there
     * was two identical functions in Codeigniter that did the same.
     *
     * @param string  $template   Template Name
     * @param array   $data       Data Array
     * @param boolean $return     Indicates if it will be returned or not
     * @param boolean $is_include Indicates if included or not
     *
     * @return void
     */
    public function parse_string($template, $data = array(), $return = false, $is_include = false)
    {
        return $this->string_parse($template, $data, $return, $is_include);
    }
}
  1. Salve e feche o arquivo.
  2. Abra o arquivo /application/config/autoload.php e edite a linha 55 da seguinte forma:
$autoload['libraries'] = array('smarty', 'parser');
  1. e a linha # 67 da seguinte forma:
$autoload['helper'] = array('url');
  1. Salve e feche o arquivo.
  2. Substitua o conteúdo do arquivo /application/modules/welcome/controllers/welcome.php com o seguinte:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
 * Welcome Controller
 *
 * @category Controller
 * @package  CodeIgniter
 * @author   Tariqul Islam <tareq@webkutir.net>
 * @license  http://directory.fsf.org/wiki/License:ReciprocalPLv1.3 Reciprocal Public License v1.3
 * @link     http://webkutir.net
 */
class Welcome extends MX_Controller
{
    /**
     * Class Constructor
     */
    function __construct()
    {
        parent::__construct();
        $this->parser->setModule("welcome");
    }
    /**
     * Default Method
     * 
     * @return void
     */
    public function index()
    {
        $this->parser->parse("welcome_message");
    }
}
/* End of file welcome.php */
/* Location: ./application/modules/welcome/controllers/welcome.php */
  1. Apague o arquivo /application/modules/welcome/views/welcome_message.php.
  2. Crie um novo arquivo em /application/modules/welcome/views/welcome_message.tpl com o seguinte conteúdo:
<!DOCTYPE html>
<html lang="en">
<head>
	<meta charset="utf-8">
	<title>Welcome to CodeIgniter</title>
	<style type="text/css">
	::selection{ background-color: #E13300; color: white; }
	::moz-selection{ background-color: #E13300; color: white; }
	::webkit-selection{ background-color: #E13300; color: white; }
	body {
		background-color: #fff;
		margin: 40px;
		font: 13px/20px normal Helvetica, Arial, sans-serif;
		color: #4F5155;
	}
	a {
		color: #003399;
		background-color: transparent;
		font-weight: normal;
	}
	h1 {
		color: #444;
		background-color: transparent;
		border-bottom: 1px solid #D0D0D0;
		font-size: 19px;
		font-weight: normal;
		margin: 0 0 14px 0;
		padding: 14px 15px 10px 15px;
	}
	code {
		font-family: Consolas, Monaco, Courier New, Courier, monospace;
		font-size: 12px;
		background-color: #f9f9f9;
		border: 1px solid #D0D0D0;
		color: #002166;
		display: block;
		margin: 14px 0 14px 0;
		padding: 12px 10px 12px 10px;
	}
	#body{
		margin: 0 15px 0 15px;
	}
	
	p.footer{
		text-align: right;
		font-size: 11px;
		border-top: 1px solid #D0D0D0;
		line-height: 32px;
		padding: 0 10px 0 10px;
		margin: 20px 0 0 0;
	}
	
	#container{
		margin: 10px;
		border: 1px solid #D0D0D0;
		-webkit-box-shadow: 0 0 8px #D0D0D0;
	}
	</style>
</head>
<body>
<div id="container">
	<h1>Welcome to CodeIgniter!</h1>
	<div id="body">
		<p>The page you are looking at is being generated dynamically by CodeIgniter.</p>
		<p>If you would like to edit this page you'll find it located at:</p>
		<code>application/views/welcome_message.php</code>
		<p>The corresponding controller for this page is found at:</p>
		<code>application/controllers/welcome.php</code>
		<p>If you are exploring CodeIgniter for the very first time, you should start by reading the <a href="user_guide/">User Guide</a>.</p>
	</div>
	<p class="footer">Page rendered in <strong>{$CI->benchmark->elapsed_time()}</strong> seconds</p>
</div>
</body>
</html>
  1. Acesse a URL /welcome => deve aparecer Welcome to CodeIgniter. Observe a página Render Time. Para o meu caso, foram 7,5080 segundos para a primeira vez.
  2. Acesse novamente a URL /welcome. Agora, observe a página Render Time. Para o meu caso, foi 0,1046 segundo para a segunda vez, e 0,0794 segundo para a terceira.

Nota: Se aparecer uma página em branco ou qualquer erro, então deve verificar as permissões de pasta dos diretórios /application/cache/smarty/cache e /application/cache/smarty/compiled.

Parabéns!!! Seu Smarty está trabalhando com sua CI com sucesso.

Instalando Doctrine

  1. Faça o download e extraia Doctrine usando o link acima.
  2. Copie a pasta Doctrine para a pasta /application/third_party.
  3. Crie um arquivo em /application/libraries/Doctrine.php e preencha-o com o seguinte:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
use Doctrine\ORM\EntityManager,
    Doctrine\ORM\Configuration,
    Doctrine\ORM,
    Doctrine\Common\Cache\ArrayCache,
    Doctrine\OXM;
 
define('DEBUGGING', false);
/**
 * Doctrine
 *
 * @category Libraries
 * @package  CodeIgniter
 * @author   Tariqul Islam <tareq@webkutir.net>
 * @license  http://directory.fsf.org/wiki/License:ReciprocalPLv1.3 Reciprocal Public License v1.3
 * @link     http://webkutir.net
 */
class Doctrine
{
    public $em = null;
    /**
     * Class Constructor
     */
    public function __construct()
    {
        // load database configuration and custom config from CodeIgniter
        include APPPATH . 'config/database.php';
        // Set up class loading.
        include_once APPPATH . 'third_party/Doctrine/Common/ClassLoader.php';
        $doctrineClassLoader = new \Doctrine\Common\ClassLoader('Doctrine', APPPATH . 'third_party');
        $doctrineClassLoader->register();
        $entitiesClassLoader = new \Doctrine\Common\ClassLoader('entities', APPPATH . 'models/doctrine');
        $entitiesClassLoader->register();
        $proxiesClassLoader = new \Doctrine\Common\ClassLoader('proxies', APPPATH . 'cache/doctrine');
        $proxiesClassLoader->register();
        $symfonyClassLoader = new \Doctrine\Common\ClassLoader('Symfony', APPPATH . 'third_party/Doctrine');
        $symfonyClassLoader->register();
        // Choose caching method based on application mode (ENVIRONMENT is defined in /index.php)
        if (ENVIRONMENT == 'development' || ENVIRONMENT == 'testing') {
            $cache = new \Doctrine\Common\Cache\ArrayCache;
        } else {
            $cache = new \Doctrine\Common\Cache\ApcCache;
        }
        // Set some configuration options
        $config = new Configuration;
        // Metadata driver
        $driverImpl = $config->newDefaultAnnotationDriver(APPPATH . 'models/doctrine/entities');
        $config->setMetadataDriverImpl($driverImpl);
        // Caching
        $config->setMetadataCacheImpl($cache);
        $config->setQueryCacheImpl($cache);
        // Proxies
        $config->setProxyDir(APPPATH . 'cache/doctrine/proxies');
        $config->setProxyNamespace('Proxies');
        if (ENVIRONMENT == 'development') {
            $config->setAutoGenerateProxyClasses(true);
        } else {
            $config->setAutoGenerateProxyClasses(false);
        }
        // SQL query logger
        if (DEBUGGING) {
            $logger = new \Doctrine\DBAL\Logging\EchoSQLLogger;
            $config->setSQLLogger($logger);
        }
        // Database connection information
        if (ENVIRONMENT == 'testing') {
            $active_group = 'default_test';
        }
        $connectionOptions = array(
            'driver'   => 'pdo_mysql',
            'user'     => $db[$active_group]['username'],
            'password' => $db[$active_group]['password'],
            'host'     => $db[$active_group]['hostname'],
            'dbname'   => $db[$active_group]['database']
        );
        // Create EntityManager
        $this->em = EntityManager::create($connectionOptions, $config);
    }
}
  1. Crie as seguintes estruturas de pastas:

/application/models/doctrine/entities

/application/cache/doctrine/generated_entities (concede permissão de gravação)

/application/cache/doctrine/proxies (concede permissão de gravação)

  1. Abra o arquivo /application/config/autoload.php e modifique-o da seguinte forma:
$autoload['libraries'] = array('smarty', 'parser', 'doctrine');
  1. Crie um arquivo em /application/core/MY_Controller.php e preencha-o com o seguinte:
<?php (defined('BASEPATH')) OR exit('No direct script access allowed');
/**
 * MY_Controller
 *
 * @category MY_Controller
 * @package  CodeIgniter
 * @author   Tariqul Islam <tareq@webkutir.net>
 * @license  http://directory.fsf.org/wiki/License:ReciprocalPLv1.3 Reciprocal Public License v1.3
 * @link     http://webkutir.net
 */
class MY_Controller extends MX_Controller
{
    public $em;
    /**
     * Constructor of MY Controller
     */
    function __construct()
    {
        parent::__construct();
        $this->em=$this->doctrine->em;
        $this->smarty->assign('currenturl', $this->uri->uri_string());
    }
}
  1. A partir de agora, todos os seus controllers em todos os módulos devem estender MY_Controller.
  2. Acesse a URL /welcome => shows Welcome to CodeIgniter.
  3. Agora precisamos definir Doctrine Models. Nós vamos construir Doctrine Models usando AnnotationDriver, que é muito simples de usar.
  4. Crie um arquivo /application/models/doctrine/entities/User.php com o seguinte:
<?php

namespace entities;
/**
 * User
 *
 * @Table(name="user")
 * @Entity
 */
class User
{
  /**
   * @var integer
   *
   * @Column(name="id", type="bigint", nullable=false)
   * @Id
   * @GeneratedValue(strategy="IDENTITY")
   */
  private $id;
  /**
   * @var string
   *
   * @Column(name="username", type="string", length=100, nullable=false)
   */
  private $username;
  /**
   * @var string
   *
   * @Column(name="email", type="string", length=150, nullable=false)
   */
  private $email;
  /**
   * @var string
   *
   * @Column(name="password", type="string", length=40, nullable=true)
   */
  private $password;
  /**
   * @var string
   *
   * @Column(name="first_name", type="string", length=100, nullable=false)
   */
  private $firstName;
  /**
   * @var string
   *
   * @Column(name="last_name", type="string", length=100, nullable=true)
   */
  private $lastName;
  /**
   * @var string
   *
   * @Column(name="mobile", type="string", length=15, nullable=true)
   */
  private $mobile;
  /**
   * @var string
   *
   * @Column(name="timezone", type="string", length=6, nullable=false)
   */
  private $timezone;
  /**
   * @var string
   *
   * @Column(name="validation_key", type="string", length=40, nullable=true)
   */
  private $validationKey;
  /**
   * @var string
   *
   * @Column(name="image_path", type="string", length=255, nullable=true)
   */
  private $imagePath;
  /**
   * @var string
   *
   * @Column(name="logo_path", type="string", length=500, nullable=true)
   */
  private $logoPath;
  /**
   * @var DateTime
   *
   * @Column(name="last_log_in", type="datetime", nullable=true)
   */
  private $lastLogIn;
  /**
   * @var string
   *
   * @Column(name="ip_address", type="string", length=15, nullable=true)
   */
  private $ipAddress;
  /**
   * @var string
   *
   * @Column(name="host", type="string", length=500, nullable=true)
   */
  private $host;
  /**
   * @var string
   *
   * @Column(name="phone", type="string", length=50, nullable=true)
   */
  private $phone;
  /**
   * @var string
   *
   * @Column(name="land_phone", type="string", length=50, nullable=true)
   */
  private $landPhone;
  /**
   * @var boolean
   *
   * @Column(name="is_active", type="boolean", nullable=false, options={"default":0})
   */
  private $isActive;
  /**
   * @var User
   *
   * @ManyToOne(targetEntity="User")
   * @JoinColumns({
   *   @JoinColumn(name="parent_id", referencedColumnName="id", onDelete="CASCADE")
   * })
   */
  private $parent;
  /**
   * @var UserType
   *
   * @ManyToOne(targetEntity="UserType")
   * @JoinColumns({
   *   @JoinColumn(name="user_type_id", referencedColumnName="id")
   * })
   */
  private $userType;
  
  /**
   * Constructor
   */
  public function __construct()
  {
      $this->isActive = 0;
      $this->lastLogIn = new \DateTime("now");
  }
  /**
   * Get id
   *
   * @return integer 
   */
  public function getId()
  {
    return $this->id;
  }
  /**
   * Set username
   *
   * @param string $username
   * @return User
   */
  public function setUsername($username)
  {
    $this->username = $username;
  
    return $this;
  }
  /**
   * Get username
   *
   * @return string 
   */
  public function getUsername()
  {
    return $this->username;
  }
  /**
   * Set email
   *
   * @param string $email
   * @return User
   */
  public function setEmail($email)
  {
    $this->email = $email;
  
    return $this;
  }
  /**
   * Get email
   *
   * @return string 
   */
  public function getEmail()
  {
    return $this->email;
  }
  /**
   * Set password
   *
   * @param string $password
   * @return User
   */
  public function setPassword($password)
  {
    $this->password = $password;
  
    return $this;
  }
  /**
   * Get password
   *
   * @return string 
   */
  public function getPassword()
  {
    return $this->password;
  }
  /**
   * Set firstName
   *
   * @param string $firstName
   * @return User
   */
  public function setFirstName($firstName)
  {
    $this->firstName = $firstName;
  
    return $this;
  }
  /**
   * Get firstName
   *
   * @return string 
   */
  public function getFirstName()
  {
    return $this->firstName;
  }
  /**
   * Set lastName
   *
   * @param string $lastName
   * @return User
   */
  public function setLastName($lastName)
  {
    $this->lastName = $lastName;
  
    return $this;
  }
  /**
   * Get lastName
   *
   * @return string 
   */
  public function getLastName()
  {
    return $this->lastName;
  }
  
  /**
   * Get fullName
   *
   * @return string
   */
  public function getFullName()
  {
      return $this->firstName.' '.$this->lastName;
  }
  /**
   * Set mobile
   *
   * @param string $mobile
   * @return User
   */
  public function setMobile($mobile)
  {
    $this->mobile = $mobile;
  
    return $this;
  }
  /**
   * Get mobile
   *
   * @return string 
   */
  public function getMobile()
  {
    return $this->mobile;
  }
  /**
   * Set timezone
   *
   * @param string $timezone
   * @return User
   */
  public function setTimezone($timezone)
  {
    $this->timezone = $timezone;
  
    return $this;
  }
  /**
   * Get timezone
   *
   * @return string 
   */
  public function getTimezone()
  {
    return $this->timezone;
  }
  /**
   * Set validationKey
   *
   * @param string $validationKey
   * @return User
   */
  public function setValidationKey($validationKey)
  {
    $this->validationKey = $validationKey;
  
    return $this;
  }
  /**
   * Get validationKey
   *
   * @return string 
   */
  public function getValidationKey()
  {
    return $this->validationKey;
  }
  /**
   * Set imagePath
   *
   * @param string $imagePath
   * @return User
   */
  public function setImagePath($imagePath)
  {
    $this->imagePath = $imagePath;
  
    return $this;
  }
  /**
   * Get imagePath
   *
   * @return string 
   */
  public function getImagePath()
  {
    return $this->imagePath;
  }
  /**
   * Set logoPath
   *
   * @param string $logoPath
   * @return User
   */
  public function setLogoPath($logoPath)
  {
    $this->logoPath = $logoPath;
  
    return $this;
  }
  /**
   * Get logoPath
   *
   * @return string 
   */
  public function getLogoPath()
  {
    return $this->logoPath;
  }
  /**
   * Set lastLogIn
   *
   * @param DateTime $lastLogIn
   * @return User
   */
  public function setLastLogIn($lastLogIn)
  {
    $this->lastLogIn = $lastLogIn;
  
    return $this;
  }
  /**
   * Get lastLogIn
   *
   * @return DateTime 
   */
  public function getLastLogIn()
  {
    return $this->lastLogIn;
  }
  /**
   * Set ipAddress
   *
   * @param string $ipAddress
   * @return User
   */
  public function setIpAddress($ipAddress)
  {
    $this->ipAddress = $ipAddress;
  
    return $this;
  }
  /**
   * Get ipAddress
   *
   * @return string 
   */
  public function getIpAddress()
  {
    return $this->ipAddress;
  }
  /**
   * Set host
   *
   * @param string $host
   * @return User
   */
  public function setHost($host)
  {
    $this->host = $host;
  
    return $this;
  }
  /**
   * Get host
   *
   * @return string 
   */
  public function getHost()
  {
    return $this->host;
  }
  /**
   * Set phone
   *
   * @param string $phone
   * @return User
   */
  public function setPhone($phone)
  {
    $this->phone = $phone;
  
    return $this;
  }
  /**
   * Get phone
   *
   * @return string 
   */
  public function getPhone()
  {
    return $this->phone;
  }
  /**
   * Set landPhone
   *
   * @param string $landPhone
   * @return User
   */
  public function setLandPhone($landPhone)
  {
    $this->landPhone = $landPhone;
  
    return $this;
  }
  /**
   * Get landPhone
   *
   * @return string 
   */
  public function getLandPhone()
  {
    return $this->landPhone;
  }
  /**
   * Set isActive
   *
   * @param boolean $isActive
   * @return User
   */
  public function setIsActive($isActive)
  {
    $this->isActive = $isActive;
  
    return $this;
  }
  /**
   * Get isActive
   *
   * @return boolean 
   */
  public function getIsActive()
  {
    return $this->isActive;
  }
  /**
   * Set parent
   *
   * @param User $parent
   * @return User
   */
  public function setParent(User $parent = null)
  {
    $this->parent = $parent;
  
    return $this;
  }
  /**
   * Get parent
   *
   * @return User 
   */
  public function getParent()
  {
    return $this->parent;
  }
  /**
   * Set userType
   *
   * @param UserType $userType
   * @return User
   */
  public function setUserType(UserType $userType = null)
  {
    $this->userType = $userType;
  
    return $this;
  }
  /**
   * Get userType
   *
   * @return UserType 
   */
  public function getUserType()
  {
    return $this->userType;
  }
}
  1. Crie um arquivo em /application/models/doctrine/entities/UserType.php e preencha-o com o seguinte:
<?php


namespace entities;
/**
 * UserType
 *
 * @Table(name="user_type")
 * @Entity
 */
class UserType
{
  /**
   * @var integer
   *
   * @Column(name="id", type="smallint", nullable=false)
   * @Id
   * @GeneratedValue(strategy="IDENTITY")
   */
  private $id;
  /**
   * @var string
   *
   * @Column(name="type_name", type="string", length=150, nullable=false)
   */
  private $typeName;

  /**
   * Get id
   *
   * @return integer 
   */
  public function getId()
  {
    return $this->id;
  }
  /**
   * Set typeName
   *
   * @param string $typeName
   * @return UserType
   */
  public function setTypeName($typeName)
  {
    $this->typeName = $typeName;
  
    return $this;
  }
  /**
   * Get typeName
   *
   * @return string 
   */
  public function getTypeName()
  {
    return $this->typeName;
  }
}
  1. Nós definimos os nossos modelos de entidade Doctrine. Para uma lista completa das anotações disponíveis e seus usos, veja a Annotation Reference.
  2. Agora é hora de criar esquema de banco de dados, atualizar o esquema do banco de dados, remover o esquema do banco de dados, etc. Para usar esses comandos no navegador, vamos agora escrever um módulo no CI.
  3. Crie um banco de dados no servidor do seu banco de dados e configure a CI de acordo editando o arquivo /application/config/database.php.
  4. Baixe este módulo e extraia-o. Copie a pasta ORM na pasta /application/modules.
  5. Copie a pasta assets na pasta /assets.
  6. Copie generic_helper.php na pasta /application/helpers.
  7. Acesse a URL /orm=> mostrará 7 botões.
  8. Clique no botão Create Schema. Quando ele mostrar a mensagem de sucesso, verifique o seu banco de dados no seu servidor de banco de dados, e você verá que agora possui duas tabelas chamadas user e user_type.
  9. Agora é hora de preencher alguns dados padrão na nossa DB. Clique no botão Load Fixture e verifique suas tabelas de banco de dados. Legal. 🙂

Nota: Não se esqueça de remover o módulo ORM no servidor de produção. Ele será prejudicial por lá.

Bem, é isso. Sinta-se à vontade para comentar se tiver qualquer dúvida.

***

Tariqul Islam faz parte do time de colunistas internacionais do iMasters. A tradução do artigo é feita pela redação iMasters, com autorização do autor, e você pode acompanhar o artigo em inglês no link: http://www.phpclasses.org/blog/post/261-Working-with-CodeIgniter-HMVC-Framework-Smarty-Template-and-Doctrine-ORM-all-together.html