Habilitando Layouts No CodeIgniter (Template Engine) – Parte 2

Categorias: desenvolvimento, php

Atenção!! Este artigo foi escrito em cima da versão 1 do Codeigniter. Para detalhes de como usar com a versão 2 do framework clique aqui.

Continuando a parte 1 deste post.
Se você perdeu a primeira parte clique aqui para ler a primeira parte.

5 – Construindo sua View

Sua View deve ser feita normalmente, como voce já está acostumado a fazer, com o nome que você colocaria normalmente.
Apenas com o conteúdo que muda de uma página para outra.

O HTML que você colocar aqui na View irá substituir a variável {content_for_layout} que definimos no layout acima.
Vou colocar nessa nossa view de exemplo apenas um título e um parágrafo para demonstrar.
Ficando assim:

<h1>Titulo VIEW</h1>

<p>Paragrafo teste teste teste teste.</p>

Chamei essa view de home.php.

6 – Desenvolvendo a Classe

Quando definimos nosso Hook no passo 2, setamos que a pasta onde ficaria nossa classe seria a pasta hooks que vem por padrão no projeto do CodeIgniter.

Vamos criar nossa classe dentro dessa pasta, e, com o nome que também especificamos na definição do Hook que foi Layout.php
Se você não seguiu o exemplo, faça suas devidas adaptações.

A classe é um pouco extensa, leia com atenção.
Para ajudar ela está com os comentários do próprio Mozart Petter.

// Padrao do CI para não acessar a Classe direto pelo Browser
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
 * Layout Class
 *
 * @package hooks
 * @description Implementa as views do tipo layout no framework.
 */

class Layout
{

public $base_url;

/**
* Metodo que executa as implementacoes.
* Este metodo e chamado atraves do arquivo hooks.php
* na pasta config.
*
* @return
*/
public function init()
{
// Instancia do CI.
$CI =& get_instance();

// Definindo o base_url.
$this->base_url = $CI->config->slash_item('base_url');

// Pegando a saida que o CI gera normalmente.
$output = $CI->output->get_output();

// Pegando o valor de title, se definido no controller.
$title = (isset($CI->title)) ? $CI->title : '';

// Links CSS definidos no controlador.
$css = (isset($CI->css)) ? $this->createCSSLinks($CI->css) : '';

// Links JS definidos no controlador.
$js = (isset($CI->js)) ? $this->createJSLinks($CI->js) : '';

// Se layout estiver definido e a regexp nao bater.
if (isset($CI->layout) && !preg_match('/(.+).php$/', $CI->layout))
{
$CI->layout .= '.php';
}
else
{
$CI->layout = 'default.php';
}

// Definindo caminho completo do layout.
$layout = LAYOUTPATH . $CI->layout;

// Se o layout for diferente do default, e o arquivo nao existir.
if ($CI->layout !== 'default.php' && !file_exists($layout))
{
// Exibe a mensagem, se o layout for diferente de '.php'.
if ($CI->layout != '.php') show_error("You have specified a invalid layout: " . $CI->layout);
}

// Se o arquivo layout existir.
if (file_exists($layout))
{
// Carrega o conteudo do  arquivo.
$layout = $CI->load->file($layout, true);

// Substitui o texto {content_for_layout} pelo valor de output em layout.
$view = str_replace('{content_for_layout}', $output, $layout);

// Substitui o texto {title_for_layout} pelo valor de title em view.
$view = str_replace('{title_for_layout}', $title, $view);

// Links CSS.
$view = str_replace('{css_for_layout}', $css, $view);

// Links JS.
$view = str_replace('{js_for_layout}', $js, $view);
}
else
{
$view = $output;
}

echo $view;
}

/**
* Gera os links CSS utilizados no layout.
*
* @return void
*/
private function createCSSLinks($links)
{
$html = "";

for ($i = 0; $i < count($links); $i++)
{
$html .= "<link rel='stylesheet' type='text/css' href='" . $this->base_url . CSSPATH . $links[$i] . ".css' media='screen' />n";
}

return $html;

}

/**
* Gera os links JS utilizados no layout.
*
* @return void
*/
private function createJSLinks($links)
{
$html = "";

for ($i = 0; $i < count($links); $i++)
{
$html .= "<script type='text/javascript' src='" . $this->base_url . JSPATH . $links[$i] . ".js'></script> n";
}

return $html;
}

}

7 – Fazendo as chamadas no Controller

Chegou o momento final!
É hora de juntar tudo isso que fizemos até agora.

A construção do seu controller é normal, como você está acostumado, mas temos que inserir algumas variáveis globais nele.

  • Uma para o Layout default do controller, para que você não precise fazer a mesma definição várias vezes.
  • Uma para o título, onde você pode definir um default para todos as páginas que vão surgir desse controller mas, o interessante é estar um título por página.
  • Outra para guardar um Array dos CSS’s que você vai usar na página.
  • E por último, outro Array para guardar os JavaScripts que você vai usar na página.

Vejamos como fica.
Acompanhe pelos comentários.

<?php

/**
 *
 */
class Principal extends Controller
{

/**
* Layout default utilizado pelo controlador.
*/
public $layout = 'default';

/**
* Titulo default.
*/
public $title = '::: Titulo default :::';

/**
* Definindo os css default.
*/
public $css = array('default');

/**
* Carregando os js default.
*/
public $js = array('home');

/**
* Construtora.
* @return
*/
function Principal()
{

parent::Controller();

}

// Metodoo index
function index()
{
// Carregando a view.
$this->load->view('home');
}

// Metodo teste
function teste()
{
//Title
$this->title = '::: TESTE Título :::';

//CSS
$this->css = array('test');

//JS
$this->js = array('jquery');

// Carregando a View
$this->load->view('teste');
}

}

?>

Vamos reparar no seguinte.
Há dois métodos nesse controller que vão chamar páginas diferentes, o index e o teste.

Para o index não definimos nada de Layout, Titulo, CSS ou JS.
Ou seja, vai vir tudo do valor default que usamos quando definimos as variáveis globais.

Já no método teste, por algum motivo precisamos de um CSS, um JS e um Título diferente.
Então redefinimos esses valores no nosso método com o que precisamos.

A gente poderia ter definido um outro Layout caso tivesse a necessidade, da mesma forma com que fiz com esses valores.
Aí, claro, teria que criar um outro Layout na pasta layouts.



UPDATE 20 DE NOVEMBRO DE 2010
Detalhe importante observado pelo Diego Felix (@diegofelix), que comentou esse detalhe abaixo nos comentários, no dia 16 de setembro desse mesmo ano.

 

Eu tenho como costume em meus projetos com CI, retirar a pasta system no qual ele vem por padrão.
Faço então a alteração da variável $system_folder no arquivo de configuração e tudo segue sem problemas.

Exceto esse tutorial, que não leva em consideração essa pasta system.
Você tem duas opções para consertar isso:

Primeiro:
No local onde são definidas as variáveis contantes, adicionar sua pasta system antes de $application_folder.
Exemplo: define(‘LAYOUTPATH’, ‘system/’ . $application_folder.’/layouts/’);

Particularmente acho essa solução acima atrasada, por deixar o projeto estático.
Se ocorrer de você alterar a pasta system, terá que alterar nesse local também. Chato.

Segundo:
Seguindo essa linha de raciocínio, de não deixar o projeto estático, prefiro fazer o seguinte:
No local onde são definidas as variáveis constantes, adicionar a variável $system_folder.
Exemplo: define(‘LAYOUTPATH’, $system_folder . ‘/’ . $application_folder.’/layouts/’);

Mas há um detalhe.
No arquivo index.php, em torno da linha 53, é adicionado a variável $system_folder o seu caminho completo do servidor. Isso, claro, vai gerar problemas para o projeto.
O que eu faço então é pegar as variáveis constantes que usam a pasta system, e jogar antes desse bloco.
Se você seguir pelo projeto exemplo, verá que as coloquei logo depois do comentário “END OF USER CONFIGURABLE SETTINGS”.

Feito isso, caso você altera sua pasta system, basta alterar no local de sempre para o projeto continuar funcionando.


Pessoal é isso!
Fazia tempo que queria escrever sobre isso, espero que ajude a galera por aí.
Dúvidas podem mandar sem problemas, vou responder no que estiver a meu alcance.

Se você teve dificuldades, baixe o projeto pronto aqui e dê uma olhada mais de perto.

Agradeço novamente ao Mozart Petter, grande Brother, que implementou essa solução que uso até hoje em meus projetos. E, como sempre, também ao pessoal que garante minhas 30 visitas diárias, Valeu!

É isso pessoal.
Até a próxima!!!


Comments