Integração Flexível do Smarty no Yaf Framework com Diretórios Dinâmicos

Integrar o Smarty como motor de renderização no Yaf (Yet Another Framework) é uma prática comum, mas a abordagem padrão via Bootstrap.php geralmente limita a estrutura de pastas ao diretório fixo views. Para projetos que exigem caminhos de templates customizados ou baseados em módulos, uma estratégia baseada em Plugins é mais eficiente.

Por que evitar o Bootstrap para inicializar o View Engine?

Ao definir o Smarty dentro de _initSmarty() no Bootstrap.php, o Yaf ainda não processou as rotas. Isso significa que o nome do módulo, controller ou action ainda não está disponível. Ao utilizar um Plugin no gancho (hook) routerShutdown, garantimos que o roteamento foi concluído, permitindo definir diretórios de templates específicos para cada módulo.

Implementação do Plugin de Layout

O exemplo abaixo demonstra como interceptar o fluxo após o roteamento para injetar o adaptador do Smarty e desativar a renderização automática do Yaf.

<?php
class TemplatePlugin extends Yaf_Plugin_Abstract {

    public function routerShutdown(Yaf_Request_Abstract $request, Yaf_Response_Abstract $response) {
        $dispatcher = Yaf_Dispatcher::getInstance();
        
        // Desativa a renderização padrão para evitar conflitos de caminhos
        $dispatcher->autoRender(false);
        
        // Inicializa o adaptador customizado do Smarty
        $smartyEngine = new SmartyAdapter();
        $dispatcher->setView($smartyEngine);
    }
}

Desenvolvendo o Adaptador Smarty

Para que o Yaf aceite o Smarty, é necessário implementar a interface Yaf_View_Interface. Abaixo, uma implementação que gerencia caminhos de forma dinâmica conforme o módulo atual.

<?php
class SmartyAdapter implements Yaf_View_Interface {
    public $instance;
    protected $_tplDir;

    public function __construct() {
        // Supondo que a classe Smarty já esteja carregada via autoload
        $this->instance = new Smarty();
        $this->instance->left_delimiter = '{{';
        $this->instance->right_delimiter = '}}';
        $this->instance->setCompileDir(DATA_PATH . '/templates_c');
        $this->instance->setCacheDir(DATA_PATH . '/cache');

        $req = Yaf_Dispatcher::getInstance()->getRequest();
        $module = $req->getModuleName();

        // Define o caminho do template baseado no módulo (ex: application/modules/Admin/tpl)
        if (strtolower($module) == 'index') {
            $path = APP_PATH . '/templates';
        } else {
            $path = APP_PATH . '/modules/' . ucfirst($module) . '/tpl';
        }

        $this->setScriptPath($path);
    }

    public function setScriptPath($path) {
        $this->instance->setTemplateDir($path);
        $this->_tplDir = $path;
    }

    public function getScriptPath() {
        return $this->_tplDir;
    }

    public function assign($name, $value = NULL) {
        $this->instance->assign($name, $value);
    }

    public function display($tpl, $vars = NULL) {
        // É recomendável concatenar o caminho completo para evitar erros de localização
        $this->instance->display($this->_tplDir . '/' . $tpl);
    }

    public function render($tpl, $vars = NULL) {
        return $this->instance->fetch($this->_tplDir . '/' . $tpl);
    }
}

Considerações Técnicas Importantes

1. Gerenciamento do AutoRender

O método $dispatcher->autoRender(false) é crucial. Se mantido como true, o Yaf tentará localizar um arquivo .phtml dentro da pasta views padrão após a execução da action, o que resultará em erros de arquivo não encontrado, já que estamos movendo os templates para diretórios personalizadso (como tpl ou templates).

2. Sobrescrita do setScriptPath

O Yaf possui um comportamento interno que chama setScriptPath automaticamente antes do dispatch. Por isso, a implementação dentro do adaptador deve ser resiliente. No código acima, garantimos que o Smarty aponte para o local correto através da variável $this->_tplDir.

Exemplo de Uso no Controller

Com a configuração via Plugin, o uso dentro das Actions permanece limpo e intuitivo:

<?php
class UserController extends Yaf_Controller_Abstract {
    public function profileAction() {
        $this->getView()->assign("username", "DevSenior");
        // O arquivo será buscado em: application/modules/User/tpl/profile.tpl
        $this->getView()->display("profile.tpl");
    }
}

Esta abordagem oferece total controle sobre a estrutura de diretórios do projeto, permitindo que a camada de visão seja organizada de formma modular sem as restrições impostas pelas convenções padrão do framwork.

Tags: PHP Yaf Smarty MVC ViewEngine

Publicado em 7-17 03:18