<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Fernando Mantoan</title>
	<atom:link href="http://fernandomantoan.com/feed/" rel="self" type="application/rss+xml" />
	<link>http://fernandomantoan.com</link>
	<description>Desenvolvimento e tecnologia da informação no geral</description>
	<lastBuildDate>Wed, 25 Aug 2010 23:45:48 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.1</generator>
		<item>
		<title>Autorização com Zend Framework</title>
		<link>http://fernandomantoan.com/frameworks/zend-framework/autorizacao-com-zend-framework/</link>
		<comments>http://fernandomantoan.com/frameworks/zend-framework/autorizacao-com-zend-framework/#comments</comments>
		<pubDate>Wed, 25 Aug 2010 23:44:52 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[zend_acl]]></category>
		<category><![CDATA[zend_auth]]></category>
		<category><![CDATA[zend_form]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=613</guid>
		<description><![CDATA[Veremos aqui uma explicação detalhada dos componentes de Autorização do Zend Framework, demonstrando como restringir acesso a recursos de um sistema, baseando-se nos privilégios que um usuário autenticado possui. Para este artigo, é essencial o estudo do artigo sobre Autenticação com Zend Framework.]]></description>
			<content:encoded><![CDATA[<p>Veremos aqui uma explicação detalhada dos componentes de Autorização do Zend Framework, demonstrando como restringir acesso a recursos de um sistema, baseando-se nos privilégios que um usuário autenticado possui. Para este artigo, é essencial o estudo do artigo sobre <a title="Autenticação com Zend Framework" href="http://fernandomantoan.com/frameworks/zend-framework/autenticacao-com-zend-framework/" target="_blank">Autenticação com Zend Framework</a>.</p>
<h2>Conceitos</h2>
<p>Autorização  é o ato de verificar as permissões de um usuário já autenticado no  sistema e, baseando-se nessas permissões, permitir ou bloquear o acesso  deste usuário a determinados recursos da aplicação. Se, por exemplo, em  um Sistema de Gestão de Conteúdo (CMS), o usuário logado é um escritor, ele  poderia ter acesso à escrita de artigos, porém não poderia ter acesso ao  cadastro de novos usuários, pode-se obter este tipo de funcionalidade por meio de um componente de autorização. No Zend  Framework este componente é o <strong>Zend_Acl</strong>,  que fornece a funcionalidade de Lista de Controle de Acesso (ACL) e  gestão de privilégios. Em geral, uma aplicação pode usar esta  funcionalidade para controlar o acesso a certos objetos protegidos,  requeridos por outros objetos.</p>
<p>Existem alguns termos  utilizados para melhor explanar as entidades envolvidas no controle de  acesso, cada um deles é detalhado a seguir.</p>
<h4>Papel (role)</h4>
<p>Um  papel corresponde a uma responsabilidade de um usuário dentro de um sistema  como, por exemplo, o papel de &#8220;colunista&#8221; ou de &#8220;membro&#8221;. Isto é  encapsulado através da classe <strong>Zend_Acl_Role</strong>, que é uma classe  simples que apenas armazena o nome do papel. Existe também herança  de papéis, onde ao se herdar de um papel, é possível fazer tudo que o  papel pai faz, além das ações específicas do papel filho. Para se criar um papel e adicioná-lo  na lista de controle de acesso, o seguinte código é necessário:</p>
<pre class="brush: php;">
$papelMembro = new Zend_Acl_Role('membro');
$acl = new Zend_Acl();
$acl-&gt;addRole($papelMembro);
</pre>
<p>Para utilizar a herança de papéis basta passar o nome do papel pai como segundo parâmetro do método <strong>addRole()</strong>. Para exemplificar isso o papel &#8220;colunista&#8221; irá herdar de &#8220;membro&#8221;, pois um colunista pode fazer tudo o que um membro pode, além de possuir permissões especiais para criar colunas. O código deste exemplo é apresentado abaixo:</p>
<pre class="brush: php;">
$papelMembro = new Zend_Acl_Role('membro');
$papelColunista = new Zend_Acl_Role('colunista');
$acl = new Zend_Acl();
$acl-&gt;addRole($papelMembro);
$acl-&gt;addRole($papelColunista, 'membro');
</pre>
<h4>Recurso  (resource)</h4>
<p>Um recurso é algo a ser protegido, o que pode ser um  controlador ou uma ação. Um recurso é encapsulado pela classe <strong>Zend_Acl_Resource</strong>,  que simplesmente armazena  o nome do recurso que será protegido. Assim como no caso do <strong>Zend_Acl_Role</strong>, a classe <strong>Zend_Acl_Resource</strong> oferece suporte a herança, esta sendo definida no segundo parâmetro do método <strong>add()</strong> de <strong>Zend_Acl</strong>. Um  exemplo de utilização de recursos é o caso de um sistema de ERP onde usuários do papel &#8220;administrador&#8221; podem ter acesso ao controlador <strong>manutencao</strong>, já usuários do papel &#8220;operador&#8221; podem ter acesso ao controlador <strong>produto</strong>. Para criar estes recursos o seguinte código é necessário:</p>
<pre class="brush: php;">
$acl = new Zend_Acl();
$acl-&gt;addResource(new Zend_Acl_Resource('manutencao'));
$acl-&gt;addResource(new Zend_Acl_Resource('produto'));
</pre>
<h3>Privilégio (privilege)</h3>
<p>Um dado recurso pode ter diversas permissões a um determinado papel, estas permissões são, tipicamente, baseadas nas operações que serão executadas. Exemplos destas operações podem ser ações de um controlador, como, por exemplo: &#8220;adicionar&#8221; e &#8220;visualizar&#8221;. Este tipo de acesso exigido é facilmente configurado com dois métodos do Zend_Acl: <strong>allow()</strong> e <strong>deny()</strong>. Um exemplo permitindo e negando ações do controlador <strong>artigos</strong> ao papel <strong>membro</strong> é exibido a seguir:</p>
<pre class="brush: php;">
$acl-&gt;allow('membro', 'artigos', 'visualizar');
$acl-&gt;deny('membro', 'artigos', 'adicionar');
</pre>
<p>Após permitir ou negar privilégios é possível verificar se um determinado papel tem acesso a um privilégio com o seguinte código:</p>
<pre class="brush: php;">
if ($acl-&gt;isAllowed('member', 'artigos', 'visualizar') {
	echo &quot;acesso permitido&quot;;
}
</pre>
<p>Estes são os principais conceitos e métodos relacionados aos componentes de autorização do Zend Framework, agora é hora de implementar um sistema de autorização integrado com o MVC do framework. Existem diversas formas de se implementar esta funcionalidade, a maneira demonstrada neste artigo é apenas uma delas.</p>
<h2>Codificando a Autorização</h2>
<p>Após uma introdução sobre os componentes de autorização do Zend Framework é hora de integrar as funcionalidades para aplicar a autorização ao MVC do framework. Antes de mais nada estou partindo do pressuposto de que o leitor possui todos os fontes do artigo <a title="Autenticação com Zend Framework" href="../frameworks/zend-framework/autenticacao-com-zend-framework/" target="_blank">Autenticação com Zend Framework</a>, para reaproveitar o código desenvolvido neste artigo.</p>
<h3>Banco de Dados e configurações iniciais</h3>
<p>O banco de dados do artigo anterior sofreu algumas modificações, agora foi criada uma tabela para armazenar os perfis (papéis) suportados por essa aplicação. Dois perfis de exemplo são criados, o primeiro corresponde ao perfil de administrador, que pode ter acesso a todos os recursos protegidos e o segundo ao perfil de escritor, que pode apenas acessar o controlador de notícias. Um usuário para cada perfil também foi criado. O SQL do banco de dados é apresentado abaixo:</p>
<pre class="brush: sql;">
CREATE TABLE `perfil`(
 id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
 nome VARCHAR(30)
)ENGINE=InnoDB;
CREATE TABLE `usuario`(
 id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
 login VARCHAR(30) NOT NULL UNIQUE,
 senha VARCHAR(60) NOT NULL,
 nome_completo VARCHAR(100) NOT NULL,
 perfil_id INT UNSIGNED NOT NULL,
 FOREIGN KEY(`perfil_id`) REFERENCES `perfil`(`id`)
 ON UPDATE CASCADE
 ON DELETE CASCADE
)ENGINE=InnoDB;
INSERT INTO `perfil`(nome) VALUES ('admin'), ('writer');
INSERT INTO `usuario`(login, senha, nome_completo, perfil_id) VALUES ('admin', SHA1('admin'), 'Administrador', 1), ('escritor', SHA1('escritor'), 'Escritor', 2);
</pre>
<p>O arquivo de configurações <strong>application/configs/application.ini</strong> desenvolvido no artigo anterior não sofrerá alterações impactantes, algumas linhas são adicionadas para configurar as namespaces do <strong>autoloader</strong> do framework e incluir o plugin de autenticação, que cuidará da parte de verificar o usuário logado e suas permissões, implementado mais adiante. Estas linhas podem ser adicionadas logo acima da seção <strong>[staging : production]</strong>:</p>
<pre class="brush: plain;">
autoloaderNamespaces[] = &quot;Aplicacao&quot;
resources.frontController.plugins.auth = &quot;Aplicacao_Plugin_Auth&quot;
</pre>
<p>A próxima etapa é adicionar ao <strong>Bootstrap</strong> a inicialização da classe de ACL que irá popular todas as regras de autorização suportadas pela aplicação. Dentro do arquivo <strong>application/Bootstrap.php</strong> basta adicionar o seguinte método à classe <strong>Bootstrap</strong>:</p>
<pre class="brush: php;">
protected function _initAcl()
{
	$aclSetup = new Aplicacao_Acl_Setup();
}
</pre>
<p>No artigo anterior foram criados os controladores: <strong>noticias</strong> e <strong>auth</strong>. Agora basta criar o controlador <strong>usuarios</strong>, que será acessível pelo papel <strong>admin</strong>, adicionar novas ações a este novo controlador e ao controlador noticias e, por último, adicionar uma nova ação ao controlador <strong>error</strong>.</p>
<pre class="brush: bash;">
zf create controller usuarios
zf create action adicionar noticias
zf create action adicionar usuarios
zf create action forbidden error
</pre>
<p>A ação <strong>forbidden</strong> ficará responsável por informar ao usuário que um determinado acesso não foi autorizado pela aplicação. Para exibir esta mensagem ao usuário basta adicionar o seguinte conteúdo ao arquivo <strong>views/scripts/error/forbidden.phtml</strong>:</p>
<pre class="brush: php;">
&lt;div style=&quot;color: #f00;&quot;&gt;Voc&amp;ecirc; n&amp;atilde;o est&amp;aacute; autorizado a ver esta p&amp;aacute;gina&lt;/div&gt;
</pre>
<p>Com isso a parte inicial da aplicação está pronta, agora é hora de implementar a classe responsável por popular o componente Zend_Acl.</p>
<h3>Populando a ACL</h3>
<p>A classe <strong>Bootstrap</strong> irá inicializar uma classe chamada <strong>Aplicacao_Acl_Setup</strong>, que ficará responsável por popular todos os dados relacionados a papéis, recursos e privilégios do componente <strong>Zend_Acl</strong>. Esta classe é apresentada abaixo e deve ser gravada no arquivo <strong>library/Aplicacao/Acl/Setup.php</strong>.</p>
<pre class="brush: php;">
&lt;?php
class Aplicacao_Acl_Setup
{
	/**
	 * @var Zend_Acl
	 */
	protected $_acl;

	public function __construct()
	{
		$this-&gt;_acl = new Zend_Acl();
		$this-&gt;_initialize();
	}

	protected function _initialize()
	{
		$this-&gt;_setupRoles();
		$this-&gt;_setupResources();
		$this-&gt;_setupPrivileges();
		$this-&gt;_saveAcl();
	}

	protected function _setupRoles()
	{
		$this-&gt;_acl-&gt;addRole( new Zend_Acl_Role('guest') );
		$this-&gt;_acl-&gt;addRole( new Zend_Acl_Role('writer'), 'guest' );
		$this-&gt;_acl-&gt;addRole( new Zend_Acl_Role('admin'), 'writer' );
	}

	protected function _setupResources()
	{
		$this-&gt;_acl-&gt;addResource( new Zend_Acl_Resource('auth') );
		$this-&gt;_acl-&gt;addResource( new Zend_Acl_Resource('error') );
		$this-&gt;_acl-&gt;addResource( new Zend_Acl_Resource('noticias') );
		$this-&gt;_acl-&gt;addResource( new Zend_Acl_Resource('usuarios') );
	}

	protected function _setupPrivileges()
	{
		$this-&gt;_acl-&gt;allow( 'guest', 'auth', array('index', 'login') )
				   -&gt;allow( 'guest', 'error', array('error', 'forbidden') );
		$this-&gt;_acl-&gt;allow( 'writer', 'noticias', array('index', 'adicionar') )
				   -&gt;allow( 'writer', 'auth', 'logout' );
		$this-&gt;_acl-&gt;allow( 'admin', 'usuarios', array('index', 'adicionar') );
	}

	protected function _saveAcl()
	{
		$registry = Zend_Registry::getInstance();
		$registry-&gt;set('acl', $this-&gt;_acl);
	}
}
</pre>
<p>A primeira etapa desta classe é configurar os papéis. Neste caso foram criados os papéis <strong>guest</strong>, <strong>writer</strong> e <strong>admin</strong>. O papel <strong>guest</strong> foi criado como um facilitador, já que não será utilizado. Pode ocorrer de a aplicação liberar determinados acessos a usuários não-logados, aí que entra este papel. O papel <strong>writer</strong> terá os mesmos acessos de <strong>guest</strong>, além de acessos específicos, assim como o papel <strong>admin</strong> terá os mesmos acessos que <strong>guest</strong> e <strong>writer</strong>, além de outras permissões.</p>
<p>Após ter os papéis definidos, são adicionados os recursos protegidos. Neste caso os recursos são os controladores <strong>auth</strong>, <strong>error</strong>, <strong>noticias</strong> e <strong>usuarios</strong>. A próxima etapa, é definir os privilégios de um determinado papel a um determinado recurso. O papel <strong>guest</strong> pode acessar ações de erro e a página de login, já o papel <strong>writer</strong> pode acessar as ações de <strong>guest</strong>, as ações do controlador de notícias e a ação de logout do controlador auth. Já o papel <strong>admin</strong> pode acessar o mesmo que os outros dois papéis, além das ações do controlador de usuários.</p>
<p>Por último esta ACL é adicionada ao <strong>Zend_Registry</strong>, para que em outras partes da aplicação ela esteja acessível e devidamente populada.</p>
<h3>Verificação de permissões</h3>
<p>Tendo a ACL devidamente configurada, agora será possível verificar as permissões do usuário. Para isso foi criado um plugin que é adicionado ao <strong>Zend_Controller_Front</strong> no arquivo de configuração definido na primeira etapa das implementações. Este plugin terá como pai a classe <strong>Zend_Controller_Plugin_Abstract</strong> que possui diversos métodos referentes a cada etapa do processo de despacho das classes do Zend Framework. O método utilizado no plugin é o <strong>preDispatch()</strong> que é chamado antes de uma ação de controlador ser despachada, o que permite re-configurar a rota caso o usuário não possa ter acesso à página em questão. Este plugin é exibido abaixo e deve estar gravado em <strong>library/Aplicacao/Plugin/Auth.php</strong>:</p>
<pre class="brush: php;">
&lt;?php
class Aplicacao_Plugin_Auth extends Zend_Controller_Plugin_Abstract
{
	/**
	 * @var Zend_Auth
	 */
	protected $_auth = null;
	/**
	 * @var Zend_Acl
	 */
	protected $_acl = null;
	/**
	 * @var array
	 */
	protected $_notLoggedRoute = array(
		'controller' =&gt; 'auth',
		'action'     =&gt; 'login',
		'module'     =&gt; 'default'
	);
	/**
	 * @var array
	 */
	protected $_forbiddenRoute = array(
		'controller' =&gt; 'error',
		'action'     =&gt; 'forbidden',
		'module'     =&gt; 'default'
	);

	public function __construct()
	{
		$this-&gt;_auth = Zend_Auth::getInstance();
		$this-&gt;_acl = Zend_Registry::get('acl');
	}

	public function preDispatch(Zend_Controller_Request_Abstract $request)
	{
		$controller = &quot;&quot;;
		$action     = &quot;&quot;;
		$module     = &quot;&quot;;
		if ( !$this-&gt;_auth-&gt;hasIdentity() ) {
			$controller = $this-&gt;_notLoggedRoute['controller'];
			$action     = $this-&gt;_notLoggedRoute['action'];
			$module     = $this-&gt;_notLoggedRoute['module'];
		} else if ( !$this-&gt;_isAuthorized($request-&gt;getControllerName(),
					$request-&gt;getActionName()) ) {
			$controller = $this-&gt;_forbiddenRoute['controller'];
			$action     = $this-&gt;_forbiddenRoute['action'];
			$module     = $this-&gt;_forbiddenRoute['module'];
		} else {
			$controller = $request-&gt;getControllerName();
			$action     = $request-&gt;getActionName();
			$module     = $request-&gt;getModuleName();
		}
		$request-&gt;setControllerName($controller);
		$request-&gt;setActionName($action);
		$request-&gt;setModuleName($module);
	}

	protected function _isAuthorized($controller, $action)
	{
		$this-&gt;_acl = Zend_Registry::get('acl');
		$user = $this-&gt;_auth-&gt;getIdentity();
		if ( !$this-&gt;_acl-&gt;has( $controller ) || !$this-&gt;_acl-&gt;isAllowed( $user, $controller, $action ) )
			return false;
		return true;
	}
}
</pre>
<p>Primeiramente são definidas as rotas padrão para o caso do usuário não estar logado ou não estar autorizado a ver uma determinada página. Estas rotas são, consecutivamente: <strong>auth/login</strong> e <strong>error/forbidden</strong>. No construtor é recuperada a instância atual de <strong>Zend_Auth </strong>e <strong>Zend_Acl</strong>, ambas usadas no processo de verificação do usuário logado.</p>
<p>A primeira etapa do método preDispatch() é verificar se o usuário está logado e, caso não esteja, os parâmetros da requisição são configurados para a rota de login. A segunda etapa é o caso do usuário estar logado, nesta etapa o objeto que representa o usuário logado é recuperado e é feita uma verificação se este usuário possui o privilégio correspondente à ação do controlador requisitado. Caso não possua, ou o recurso que representa o controlador não exista, ele é redirecionado para a rota de acesso proibido. Se nenhuma destas verificações negar o acesso ao usuário significa que ele está apto a acessar a requisição em questão, portanto os parâmetros dessa requisição são mantidos e o fluxo prossegue.</p>
<h3>Models</h3>
<p>Tendo todo o processo de verificação pronto a próxima etapa é criar as classes com regras de negócio da parte de autenticação. Já que, diferente do artigo anterior, este artigo envolve o MVC do Zend Framework, toda a parte de regra de negócio é implementada na camada referente ao <strong>Model</strong>. A primeira classe criada é a classe que representa um usuário da aplicação. Ela implementará a interface <strong>Zend_Acl_Role_Interface</strong>, que permite que ela seja tratada como um papel do componente <strong>Zend_Acl</strong>. Esta classe exige que o método <strong>getRoleId()</strong> seja implementado e retorne o identificador correspondente ao papel em questão. Esta classe é bem simples e possui apenas métodos <strong>getters</strong> e <strong>setters</strong>. Ela deverá estar no arquivo <strong>models/Usuario.php</strong>.</p>
<pre class="brush: php;">
&lt;?php
class Model_Usuario implements Zend_Acl_Role_Interface
{
	private $_userName;
	private $_roleId;
	private $_fullName;

	public function getUserName()
	{
		return $this-&gt;_userName;
	}

	public function setUserName($userName)
	{
		$this-&gt;_userName = (string) $userName;
	}

	public function getFullName()
	{
		return $this-&gt;_fullName;
	}

	public function setFullName($fullName)
	{
		$this-&gt;_fullName = (string) $fullName;
	}
	/**
	 *
	 */
	public function getRoleId()
	{
		return $this-&gt;_roleId;
	}

	public function setRoleId($roleId)
	{
		$this-&gt;_roleId = (string) $roleId;
	}
}
</pre>
<p>A próxima etapa é implementar a classe que cuidará da regra de negócio de login. Esta classe terá apenas um método estático, responsável por fazer o login do usuário na aplicação. A principal diferença deste método de login com o apresentado no artigo anterior é a modificação da consulta ao banco de dados, para adicionar a tabela <strong>perfil</strong> aos dados retornados pelo <strong>Zend_Auth_Adapter_DbTable</strong>. O método <strong>join()</strong> de <strong>Zend_Db_Select</strong>, adicionará a tabela <strong>perfil</strong> com o alias &#8220;p&#8221;, onde a coluna <strong>perfil_id</strong> da tabela <strong>usuario</strong> seja igual a coluna <strong>id</strong> da tabela <strong>perfil</strong>, retornando a coluna  &#8220;nome&#8221; da tabela &#8220;perfil&#8221; com o alias &#8220;nome_perfil&#8221;. Após validar o login, o objeto retornado pelo adapter é mapeado para um objeto do tipo <strong>Model_Usuario</strong> e, por último, este é armazenado à sessão do Zend Framework. Este model ficará no arquivo <strong>models/Auth.php</strong> e deve possuir o seguinte conteúdo:</p>
<pre class="brush: php;">
&lt;?php
class Model_Auth
{
	public static function login($login, $senha)
	{
		$dbAdapter = Zend_Db_Table::getDefaultAdapter();
		//Inicia o adaptador Zend_Auth para banco de dados
		$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
		$authAdapter-&gt;setTableName('usuario')
					-&gt;setIdentityColumn('login')
					-&gt;setCredentialColumn('senha')
					-&gt;setCredentialTreatment('SHA1(?)');
		//Define os dados para processar o login
		$authAdapter-&gt;setIdentity($login)
					-&gt;setCredential($senha);
		//Faz inner join dos dados do perfil no SELECT do Auth_Adapter
		$select = $authAdapter-&gt;getDbSelect();
		$select-&gt;join( array('p' =&gt; 'perfil'), 'p.id = usuario.perfil_id', array('nome_perfil' =&gt; 'nome') );
		//Efetua o login
		$auth = Zend_Auth::getInstance();
		$result = $auth-&gt;authenticate($authAdapter);
		//Verifica se o login foi efetuado com sucesso
		if ( $result-&gt;isValid() ) {
			//Recupera o objeto do usuário, sem a senha
			$info = $authAdapter-&gt;getResultRowObject(null, 'senha');

			$usuario = new Model_Usuario();
			$usuario-&gt;setFullName( $info-&gt;nome_completo );
			$usuario-&gt;setUserName( $info-&gt;login );
			$usuario-&gt;setRoleId( $info-&gt;nome_perfil );

			$storage = $auth-&gt;getStorage();
			$storage-&gt;write($usuario);

			return true;
		}
		throw new Exception('Nome de usuário ou senha inválida');
	}
}
</pre>
<h3>Controller de Autenticação e demais Views</h3>
<p>Agora que toda a regra de negócio foi delegada à camada Model, o controller de autenticação sofre algumas modificações para utilizar esta classe. Neste caso ele chamará o método estático <strong>Model_Auth::login()</strong>, e, caso este lance alguma exceção, irá armazenar a mensagem ao helper <strong>FlashMessenger</strong> e exibí-la em cima do formulário de login. A classe modificada é apresentada abaixo e, logo em seguida, a <strong>view</strong> correspondente a esta ação de login é apresentada. O formulário de login é o mesmo implementado no antigo anterior.</p>
<pre class="brush: php;">
&lt;?php
class AuthController extends Zend_Controller_Action
{

	public function init()
	{
	}

	public function indexAction()
	{
		return $this-&gt;_helper-&gt;redirector('login');
	}

	public function loginAction()
	{
		$this-&gt;_flashMessenger = $this-&gt;_helper-&gt;getHelper('FlashMessenger');
		$this-&gt;view-&gt;messages = $this-&gt;_flashMessenger-&gt;getMessages();
		$form = new Form_Login();
		$this-&gt;view-&gt;form = $form;
		//Verifica se existem dados de POST
		if ( $this-&gt;getRequest()-&gt;isPost() ) {
			$data = $this-&gt;getRequest()-&gt;getPost();
			//Formulário corretamente preenchido?
			if ( $form-&gt;isValid($data) ) {
				$login = $form-&gt;getValue('login');
				$senha = $form-&gt;getValue('senha');

				try {
					Model_Auth::login($login, $senha);
					//Redireciona para o Controller protegido
					return $this-&gt;_helper-&gt;redirector-&gt;goToRoute( array('controller' =&gt; 'noticias'), null, true);
				} catch (Exception $e) {
					//Dados inválidos
					$this-&gt;_helper-&gt;FlashMessenger($e-&gt;getMessage());
					$this-&gt;_redirect('/auth/login');
				}
			} else {
				//Formulário preenchido de forma incorreta
				$form-&gt;populate($data);
			}
		}
	}

	public function logoutAction()
	{
		$auth = Zend_Auth::getInstance();
		$auth-&gt;clearIdentity();
		return $this-&gt;_helper-&gt;redirector('index');
	}
}
</pre>
<pre class="brush: php;">
&lt;h2&gt;Login&lt;/h2&gt;
&lt;?php echo ( sizeof( $this-&gt;messages ) &gt; 0 ) ? '&lt;div style=&quot;color: #f00;&quot;&gt;' . $this-&gt;messages[0] . '&lt;/div&gt;' : &quot;&quot;; ?&gt;
&lt;?php echo $this-&gt;form; ?&gt;
</pre>
<p>A última etapa é modificar as views dos controladores <strong>noticias</strong> e <strong>usuarios</strong>. Estas views são extremamente simples e irão conter apenas uma mensagem de boas-vindas e um link para logout. O arquivo <strong>views/scripts/noticias/index.phtml</strong> deve conter o seguinte conteúdo:</p>
<pre class="brush: php;">
&lt;h2&gt;Bem-vindo Escritor&lt;/h2&gt;
&lt;a href=&quot;&lt;?php echo $this-&gt;url(array('controller' =&gt; 'auth', 'action' =&gt; 'logout', 'module' =&gt; 'default'), '', true); ?&gt;&quot;&gt;
	Logout
&lt;/a&gt;
</pre>
<p>E, por último, o arquivo <strong>views/scripts/usuarios/index.phtml</strong> possui o seguinte conteúdo:</p>
<pre><strong>
<pre class="brush: php;">
&lt;h2&gt;Bem-vindo Admin&lt;/h2&gt;
&lt;a href=&quot;&lt;?php echo $this-&gt;url(array('controller' =&gt; 'auth', 'action' =&gt; 'logout', 'module' =&gt; 'default'), '', true); ?&gt;&quot;&gt;
	Logout
&lt;/a&gt;
</pre>
<p> </strong></pre>
<h2>Funcionamento</h2>
<p>Após todas as etapas estarem concluídas a aplicação está devidamente protegida, tanto na questão de permitir apenas usuários logados, como em autorizar aos usuários apenas alguns privilégios baseados em seu perfil. Para o meu caso a URL da aplicação ficou apontada para: <strong>http://localhost/zend_acl</strong>, e qualquer tentativa de acessar controllers internos são redirecionadas à pagina de login. Após o login,  a aplicação permite ou proíbe o acesso, de acordo com o perfil logado.  Abaixo são apresentadas algumas screenshots de cada parte funcional desta aplicação:</p>
<div id="attachment_677" class="wp-caption aligncenter" style="width: 310px"><a href="http://fernandomantoan.com/wp-content/uploads/2010/08/erro_login.png"><img class="size-medium wp-image-677" title="erro_login" src="http://fernandomantoan.com/wp-content/uploads/2010/08/erro_login-300x227.png" alt="" width="300" height="227" /></a><p class="wp-caption-text">Erro ao efetuar login</p></div>
<div id="attachment_678" class="wp-caption aligncenter" style="width: 296px"><a href="http://fernandomantoan.com/wp-content/uploads/2010/08/escritor_bemvindo.png"><img class="size-full wp-image-678" title="escritor_bemvindo" src="http://fernandomantoan.com/wp-content/uploads/2010/08/escritor_bemvindo.png" alt="" width="286" height="146" /></a><p class="wp-caption-text">Escritor logado com sucesso, acessando o controlador noticias</p></div>
<div id="attachment_679" class="wp-caption aligncenter" style="width: 310px"><a href="http://fernandomantoan.com/wp-content/uploads/2010/08/erro_forbidden.png"><img class="size-medium wp-image-679" title="erro_forbidden" src="http://fernandomantoan.com/wp-content/uploads/2010/08/erro_forbidden-300x125.png" alt="" width="300" height="125" /></a><p class="wp-caption-text">Tentativa de acesso ao controlador usuarios, utilizando o perfil escritor</p></div>
<div id="attachment_680" class="wp-caption aligncenter" style="width: 287px"><a href="http://fernandomantoan.com/wp-content/uploads/2010/08/admin_bemvindo.png"><img class="size-full wp-image-680" title="admin_bemvindo" src="http://fernandomantoan.com/wp-content/uploads/2010/08/admin_bemvindo.png" alt="" width="277" height="110" /></a><p class="wp-caption-text">Acesso ao controlador usuarios, usando o perfil admin</p></div>
<h2><strong>Conclusão</strong></h2>
<p>Os componentes do Zend Framework relacionados à autorização apresentam uma API consistente e intuitiva de se utilizar e configurar, o que garante uma baixa curva de aprendizagem para se utilizar as funcionalidades básicas do mesmo. Estes componentes podem ser integrados a todo o processo de despacho da parte MVC do framework através de plugins, o que permite manipular as requisições livremente e, baseado em determinados critérios, redirecionar o usuário para outros pontos da aplicação para informar mensagens de erro ou exigir algum formulário para entrada de dados. O objetivo deste artigo foi demonstrar de forma prática uma maneira de implementar autorização e integrá-la ao MVC, porém, vale ressaltar, que existem diversas formas de se chegar a esta funcionalidade, para maiores informações a seção de referências logo abaixo pode ser de grande valia. No próximo artigo os componentes de Internacionalização e Localização serão abordados, até a próxima pessoal!</p>
<h2><strong>Referências</strong></h2>
<ul>
<li><a id="yjqa" title="Zend_Acl no guia de referência do Zend Framework" href="http://framework.zend.com/manual/en/zend.acl.html">Zend_Acl no guia de referência do Zend Framework</a>;</li>
<li><a href="http://framework.zend.com/manual/en/zend.controller.plugins.html" target="_blank">Plugins no guia de referência do Zend Framework</a>;</li>
<li><a id="swfv" title="Livro Zend Framework em Ação" href="http://altabooks.tempsite.ws/product_info.php?products_id=350&amp;osCsid=dfh1koampc9vmmbtmkt0br4hl0">Livro Zend Framework em Ação</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/frameworks/zend-framework/autorizacao-com-zend-framework/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Problemas com o WordPress</title>
		<link>http://fernandomantoan.com/sem-categoria/problemas-com-o-wordpress/</link>
		<comments>http://fernandomantoan.com/sem-categoria/problemas-com-o-wordpress/#comments</comments>
		<pubDate>Wed, 11 Aug 2010 01:09:32 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Sem categoria]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=658</guid>
		<description><![CDATA[Olá pessoal, como vão? Tive problemas devido a uma atualização do WordPress, e precisei reinstalá-lo, o que fez com que eu perdesse os artigos já escritos. Não se preocupem, tenho um backup do banco de dados, só preciso arranjar tempo para restaurar o conteúdo, acredito que até amanhã tudo estará normalizado. Até logo.]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal, como vão? Tive problemas devido a uma <a href="http://wp-brasil.org/novidades/correcao-da-versao-3-0-1-pt_br" target="_blank">atualização do WordPress</a>,  e precisei reinstalá-lo, o que fez com que eu perdesse os artigos já  escritos. Não se preocupem, tenho um backup do banco de dados, só  preciso arranjar tempo para restaurar o conteúdo, acredito que até  amanhã tudo estará normalizado.</p>
<p>Até logo.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/sem-categoria/problemas-com-o-wordpress/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Autenticação com Zend Framework</title>
		<link>http://fernandomantoan.com/frameworks/zend-framework/autenticacao-com-zend-framework/</link>
		<comments>http://fernandomantoan.com/frameworks/zend-framework/autenticacao-com-zend-framework/#comments</comments>
		<pubDate>Mon, 17 May 2010 20:02:46 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[zend_auth]]></category>
		<category><![CDATA[zend_form]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=562</guid>
		<description><![CDATA[Neste artigo explico detalhadamente os componentes de Autenticação do Zend Framework demonstrando como restringir acesso a uma aplicação, e como, baseado nas credenciais de um usuário, verificar se ele está apto ou não a acessar os recursos protegidos da aplicação.]]></description>
			<content:encoded><![CDATA[<p>Neste artigo explico detalhadamente os componentes de Autenticação do Zend Framework demonstrando como restringir acesso a uma  aplicação, e como, baseado nas credenciais de um usuário, verificar se ele está apto ou não a acessar os recursos protegidos da aplicação.</p>
<h2>Conceitos</h2>
<p>Autenticação  é o ato de determinar se uma entidade é aquilo que ela diz ser, baseado  em suas credenciais. Explicando de uma forma mais clara, é o ato de  verificar determinados dados de um usuário e, caso ele realmente seja um  usuário válido da aplicação, identificá-lo para que a aplicação saiba quem ele é. No Zend Framework esta funcionalidade é fornecida pelo  componente <strong>Zend_Auth</strong>, que além de prover uma API para  autenticação, também inclui adaptadores concretos de autenticação para  cenários comumente encontrados.</p>
<p>Um adaptador Zend_Auth é utilizado para fazer a autenticação em um serviço de autenticação  específico como, por exemplo, LDAP, banco de dados e arquivos físicos. Cada adaptador terá certas particularidades de comportamentos e opções,  porém algumas características básicas serão encontradas em todos os  adaptadores, por exemplo aceitar credenciais de acesso, efetuar  consultas no serviço de autenticação e retornar resultados. Os adaptadores implementam a interface <strong>Zend_Auth_Adapter_Interface</strong>, esta definindo o método <strong>authenticate()</strong>, que cuida da consulta utilizada na autenticação, que deverá ser implementado em cada um dos adaptadores. Para a utilização deste método, cada adaptador deverá estar devidamente configurado com os dados necessários na autenticação, como  as opções específicas do adaptador e o usuário e senha que deverão ser  utilizados.</p>
<p>Uma tentativa de autenticação utilizando o método <strong>authenticate()</strong> de um adaptador Zend_Auth irá retornar como resultado uma instância da classe <strong>Zend_Auth_Result</strong> devidamente  populada com informações para validar o retorno da autenticação. Esta  classe possui os seguintes métodos:</p>
<ul>
<li><strong>isValid()</strong> &#8211;  Retorna <strong>true</strong> se e somente se o resultado representa uma tentativa  de autenticação bem-sucedida;</li>
<li><strong>getCode()</strong> &#8211; Retorna uma  constante da classe <strong>Zend_Auth_Result</strong> para determinar que tipo de  falha de autenticação ou sucesso que ocorreu. Pode ser usado em  situações onde o desenvolvedor necessita saber o tipo de resultado  ocorrido para proceder de alguma forma específica;</li>
<li><strong>getIdentity()</strong> &#8211; Retorna a identidade da tentativa de autenticação, pode ser o nome de  usuário ou alguma outra característica definida como identidade;</li>
<li><strong>getMessages()</strong> &#8211; Retorna um <strong>array</strong> de mensagens sobre uma tentativade  autenticação mal-sucedida.</li>
</ul>
<p>As constantes que podem ser retornadas no método <strong>getCode()</strong> são listadas abaixo:</p>
<p><span style="font-family: Courier New;">
<pre class="brush: php;">
Zend_Auth_Result::SUCCESS //Sucesso na  autenticação
Zend_Auth_Result::FAILURE //Falha na autenticação
Zend_Auth_Result::FAILURE_IDENTITY_NOT_FOUND  //Falha, a identidade é inválida
Zend_Auth_Result::FAILURE_IDENTITY_AMBIGUOUS  //Falha, a identidade é ambígua
Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID  //Falha, a senha é inválida
Zend_Auth_Result::FAILURE_UNCATEGORIZED  //Falha não categorizada
</pre>
<p></span></p>
<p>Efetuar corretamente  uma autenticação que inclui suas devidas credenciais é útil por si só,  mas também é importante manter a autenticação feita para não haver a  necessidade de solicitar as credenciais de autenticação a cada  requisição. O HTTP é um protocolo <em>stateless</em>, porém técnicas como <strong>cookies</strong> e <strong>sessões</strong> foram criadas para facilitar o mantimento de um  determinado estado durante diversas requisições às aplicações. Por  padrão o componente <strong>Zend_Auth</strong> armazena uma tentativa  bem-sucedida de autenticação na sessão do PHP.  Ele utiliza uma classe  de armazenamento chamada <strong>Zend_Auth_Storage_Session</strong> que utiliza a  classe <strong>Zend_Session</strong> para manipular as sessões. Também pode-se  utilizar para armazenamento uma classe customizada, para isso basta  prover um objeto que implemente a classe <strong>Zend_Auth_Storage_Interface</strong> para o método <strong>Zend_Auth::setStorage()</strong>.</p>
<h2>Codificando a Autenticação</h2>
<p>Após explicar detalhadamente os conceitos que envolvem autenticação é hora de codificar um exemplo simples que fará uso dos componentes do Zend Framework. Este exemplo precisará de uma tabela no banco de dados onde serão armazenados os usuários do sistema. Esta tabela está descrita a seguir:</p>
<pre class="brush: sql;">
CREATE TABLE `usuario`(
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	login VARCHAR(30) NOT NULL UNIQUE,
	senha VARCHAR(60) NOT NULL,
	nome_completo VARCHAR(100) NOT NULL
);
</pre>
<p>É inserido então um usuário de exemplo que estará apto a se autenticar no sistema:</p>
<pre class="brush: sql;">
INSERT INTO `usuario` VALUES ('', 'admin', SHA1('admin'), 'Administrador');
</pre>
<p>É possível notar que é uma tabela extremamente simples, porém essa estrutura já é o suficiente para utilizar no exemplo desenvolvido. Para este exemplo foi criado um projeto padrão do Zend Framework com o seguinte comando:</p>
<pre class="brush: bash;">zf create project zend_auth</pre>
<p>Este projeto conterá um controlador de notícias, que seria um recurso apenas disponível para usuários autenticados no sistema, e outro controlador de autenticação, utilizado para fazer login e logout da aplicação. Para criar estes controladores e  as ações de autenticação os seguintes comandos são utilizados:</p>
<pre class="brush: bash;">
cd zend_auth
zf create controller noticias
zf create controller auth
zf create action login Auth
zf create action logout Auth
</pre>
<p>O próximo passo é configurar o adaptador do banco de dados MySQL, e configurar o controlador de notícias como o controlador padrão da aplicação. No arquivo <strong>application.ini</strong> localizado na pasta <strong>application/configs</strong> basta acrescentar o seguinte conteúdo:</p>
<pre class="brush: plain;">
; Faz com que o controlador de notícias seja o controlador padrão
resources.frontController.defaultControllerName = &quot;noticias&quot;
; Banco de dados
resources.db.adapter = &quot;PDO_MYSQL&quot;
resources.db.params.host = &quot;localhost&quot;
resources.db.params.username = &quot;root&quot;
resources.db.params.password = &quot;&quot;
resources.db.params.dbname = &quot;zend_auth&quot;
</pre>
<p>Agora o último passo é configurar o Autoload de classes do Zend Framework. Para isso basta abrir o arquivo <strong>application/Bootstrap.php</strong> e adicionar o seguinte método na classe:</p>
<pre class="brush: php;">
protected function _initAutoload()
{
	$autoloader = new Zend_Application_Module_Autoloader(array(
			'basePath' =&gt; APPLICATION_PATH,
			'namespace' =&gt; ''
	));
	return $autoloader;
}
</pre>
<h3>Formulário de Login</h3>
<p>Todo sistema que precisa de autenticação fornece um formulário onde o usuário pode informar suas credenciais para se identificar no sistema. Para criar o formulário de login pode-se utilizar o componente <strong>Zend_Form</strong>, colocando os campos de login e senha. Para isto, primeiramente basta executar o seguinte comando:</p>
<pre class="brush: bash;">zf create form login</pre>
<p>Com isso um arquivo nomeado <strong>Login.php</strong> poderá ser encontrado dentro de <strong>application/forms</strong>. Para criar o formulário basta colocar o seguinte conteúdo neste arquivo:</p>
<pre class="brush: php;">
&lt;?php

class Form_Login extends Zend_Form
{
	public function init()
	{
		$this-&gt;setName('login');

		$login = new Zend_Form_Element_Text('login');
		$login-&gt;setLabel('Login:')
			  -&gt;setRequired(true)
			  -&gt;addFilter('StripTags')
			  -&gt;addFilter('StringTrim')
			  -&gt;addValidator('NotEmpty');

		$senha = new Zend_Form_Element_Password('senha');
		$senha-&gt;setLabel('Senha:')
			  -&gt;setRequired(true)
			  -&gt;addFilter('StripTags')
			  -&gt;addFilter('StringTrim')
			  -&gt;addValidator('NotEmpty');

		$submit = new Zend_Form_Element_Submit('submit');
		$submit-&gt;setLabel('Logar')
			   -&gt;setAttrib('id', 'submitbutton');

		$this-&gt;addElements(array($login, $senha, $submit));
	}
}
</pre>
<p>Neste código são criados os campos <strong>login</strong> e <strong>senha</strong>, onde ambos possuirão filtros que farão uma limpeza nos dados fornecidos pelo usuário, tirando espaços vazios e tags HTML, e uma validação de campos obrigatórios. Após criar estes elementos é criado o botão de envio e, por último, todos os elementos são adicionados ao corpo do formulário. Estudar mais afundo o componente <strong>Zend_Form</strong> foge do escopo deste artigo, só este componente pode ser assunto de vários outros artigos.</p>
<h3>Ação de Login</h3>
<p>Após criar o formulário é hora de implementar a ação de login. O seguinte código ficará encarregado de efetuar o login na aplicação:</p>
<pre class="brush: php;">
public function loginAction()
{
	$this-&gt;_flashMessenger = $this-&gt;_helper-&gt;getHelper('FlashMessenger');
	$this-&gt;view-&gt;messages = $this-&gt;_flashMessenger-&gt;getMessages();
	$form = new Form_Login();
	$this-&gt;view-&gt;form = $form;
	//Verifica se existem dados de POST
	if ( $this-&gt;getRequest()-&gt;isPost() ) {
		$data = $this-&gt;getRequest()-&gt;getPost();
		//Formulário corretamente preenchido?
		if ( $form-&gt;isValid($data) ) {
			$login = $form-&gt;getValue('login');
			$senha = $form-&gt;getValue('senha');

			$dbAdapter = Zend_Db_Table::getDefaultAdapter();
			//Inicia o adaptador Zend_Auth para banco de dados
			$authAdapter = new Zend_Auth_Adapter_DbTable($dbAdapter);
			$authAdapter-&gt;setTableName('usuario')
						-&gt;setIdentityColumn('login')
						-&gt;setCredentialColumn('senha')
						-&gt;setCredentialTreatment('SHA1(?)');
			//Define os dados para processar o login
			$authAdapter-&gt;setIdentity($login)
						-&gt;setCredential($senha);
			//Efetua o login
			$auth = Zend_Auth::getInstance();
			$result = $auth-&gt;authenticate($authAdapter);
			//Verifica se o login foi efetuado com sucesso
			if ( $result-&gt;isValid() ) {
				//Armazena os dados do usuário em sessão, apenas desconsiderando
				//a senha do usuário
				$info = $authAdapter-&gt;getResultRowObject(null, 'senha');
				$storage = $auth-&gt;getStorage();
				$storage-&gt;write($info);
				//Redireciona para o Controller protegido
				return $this-&gt;_helper-&gt;redirector-&gt;goToRoute( array('controller' =&gt; 'noticias'), null, true);
			} else {
				//Dados inválidos
				$this-&gt;_helper-&gt;FlashMessenger('Usuário ou senha inválidos!');
				$this-&gt;_redirect('/auth/login');
			}
		} else {
			//Formulário preenchido de forma incorreta
			$form-&gt;populate($data);
		}
	}
}
</pre>
<p>Inicialmente é necessário instanciar o formulário de login e passá-lo para a camada View, para exibí-lo ao usuário. Caso este formulário seja enviado para processamento o método <strong>$this-&gt;getRequest()-&gt;isPost()</strong> irá retornar <strong>true</strong>, e então toda a lógica para efetuar o login será executada. Primeiramente os dados do formulário são recuperados através do método <strong>$this-&gt;getRequest()-&gt;getPost()</strong>, então é feita uma verificação se os dados foram preenchidos corretamente, caso eles não foram preenchidos, ele não entrará na lógica de login e executará o trecho:</p>
<pre class="brush: php;">
} else {
	//Formulário preenchido de forma incorreta
	$form-&gt;populate($data);
}
</pre>
<p>Que basicamente irá preencher o formulário com os dados já enviados, para o usuário não precisar reinformá-los, permitindo exibí-los na View. No caso do formulário ser preenchido corretamente a lógica de autenticação é executada, onde são recuperados os valores preenchidos do formulário através do método <strong>getValue(atributo)</strong>, e finalmente os componentes do Zend Framework entram em ação, primeiramente é recuperado o adaptador de banco de dados sendo executado pela aplicação e, então ele é passado para a classe <strong>Zend_Auth_Adapter_DbTable</strong>, que, após ser instanciada, é configurada para utilizar a tabela <strong>usuario</strong> do banco de dados, utilizando como <strong>Identidade</strong> a coluna <strong>login</strong>, e como <strong>Credencial</strong> a coluna <strong>senha</strong>, e como <strong>Tratamento de senha</strong> o formato de criptografia <strong>SHA1</strong>.</p>
<p>Após configurar o adaptador os dados informados pelo usuário são passados para o mesmo, em seguida o componente <strong>Zend_Auth</strong> é iniciado, e é efetuada uma tentativa de autenticação. Caso o resultado seja válido, é armazenado um objeto com os dados do usuário em sessão, excluindo apenas sua senha por questões de segurança, e o usuário é redirecionado para o controlador de notícias.  Caso o resultado seja inválido, é criada uma mensagem de erro através do componente <strong>FlashMessenger</strong>, que é instanciado no início desta action passando as possíveis mensagens armazenadas para a camada View, e então o usuário é redirecionado para o formulário de login, que conterá uma mensagem informando sobre o erro encontrado.</p>
<p>Agora a última etapa é codificar a View <strong>login.phtml</strong>, localizada na pasta <strong>application/views/scripts/auth</strong>, para exibir o formulário e as possíveis mensagens de erro. O código deste arquivo é apresentado a seguir:</p>
<pre class="brush: php;">
&lt;h2&gt;Login&lt;/h2&gt;
&lt;?php echo ( sizeof( $this-&gt;messages ) &gt; 0 ) ? $this-&gt;messages[0] : &quot;&quot;; ?&gt;
&lt;?php echo $this-&gt;form; ?&gt;
</pre>
<p>Este arquivo é extremamente simples, ele terá uma verificação se existem mensagens de erro para exibir ao usuário, caso existam ele irá imprimí-las, e irá exibir o formulário de login. Como o componente <strong>Zend_Form</strong>, encapsula toda a validação, não é necessário mais nenhum código. Agora para testar basta apontar o browser para o projeto, no meu caso estou utilizando a seguinte url: http://zend_auth/auth/login. A seguinte imagem deverá ser exibida:</p>
<div id="attachment_621" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/05/form_login.png"><img class="size-medium wp-image-621" title="form_login" src="http://fernandomantoan.com/wp-content/uploads/2010/05/form_login-300x223.png" alt="" width="300" height="223" /></a><p class="wp-caption-text">Formulário de Login</p></div>
<p>Agora a última etapa é configurar a ação <strong>indexAction</strong> para redirecionar para a ação de login. Para isso basta deixá-la da seguinte forma:</p>
<pre class="brush: php;">
public function indexAction()
{
	return $this-&gt;_helper-&gt;redirector('login');
}
</pre>
<h3>Logout</h3>
<p>Efetuar logout com os componentes do Zend Framework é uma etapa extremamente simples. Na classe <strong>AuthController</strong> foi criada a ação <strong>logoutAction</strong>, basta alterá-la para que ela fique da seguinte forma:</p>
<pre class="brush: php;">
public function logoutAction()
{
	$auth = Zend_Auth::getInstance();
	$auth-&gt;clearIdentity();
	return $this-&gt;_helper-&gt;redirector('index');
}
</pre>
<p>Basicamente é recuperada a instância do <strong>Zend_Auth</strong> e é feita uma limpeza dos dados do usuário logado, após isso o usuário é redirecionado ao formulário de login, para que ele realmente saiba que agora ele não está mais autenticado no sistema.</p>
<h3>Controlador de notícias</h3>
<p>O Controlador de notícias será o ponto de verificação de todo o processo de login. Neste exemplo ele é uma área restrita, portanto é necessário protegê-lo do acesso de usuários não-autenticados. O método <strong>init()</strong> é acessado antes de qualquer ação de um controlador, portanto ele é o ponto ideal para fazer a proteção do controlador. Para obter esta proteção basta modificar este método, no arquivo <strong>NoticiasController.php</strong>, deixando-o com o seguinte conteúdo:</p>
<pre class="brush: php;">
public function init()
{
	if ( !Zend_Auth::getInstance()-&gt;hasIdentity() ) {
		return $this-&gt;_helper-&gt;redirector-&gt;goToRoute( array('controller' =&gt; 'auth'), null, true);
	}
}
</pre>
<p>Mais um código extremamente simples, ele irá verificar se existe alguma identidade autenticada no sistema, e, caso não exista, o usuário será redirecionado para o formulário de login.</p>
<p>Agora no método <strong>indexAction()</strong> será feita uma breve codificação para que a sua View possa informar os dados do usuário, junto com um link para efetuar o logout da aplicação. Este código fica da seguinte forma:</p>
<pre class="brush: php;">
public function indexAction()
{
	$usuario = Zend_Auth::getInstance()-&gt;getIdentity();
	$this-&gt;view-&gt;usuario = $usuario;
}
</pre>
<p>Ele recupera a identidade armazenada na instância do <strong>Zend_Auth</strong> e passa-a para a camada de apresentação. A View desta ação está localizada em <strong>application/views/scripts/noticias/index.phtml</strong> e o seguinte conteúdo deve ser colocado nela:</p>
<pre class="brush: php;">
&lt;h2&gt;Usu&amp;aacute;rio logado: &lt;?php echo $this-&gt;usuario-&gt;nome_completo; ?&gt;&lt;/h2&gt;
&lt;p&gt;&lt;a href=&quot;&lt;?php echo $this-&gt;url(array('controller' =&gt; 'auth', 'action' =&gt; 'logout'), null, true); ?&gt;&quot;&gt;Efetuar logout&lt;/a&gt;&lt;/p&gt;
</pre>
<p>Esse código irá mostrar o nome do usuário logado e logo abaixo um link para efetuar logout do sistema. Após clicar neste link, pode-se verificar se o logout foi feito com sucesso tentando acessar novamente o controlador de notícias. O resultado será um redirecionamento para o formulário de login, o que garante que a aplicação está devidamente protegida.</p>
<h2>Conclusão</h2>
<p>Os componentes do  Zend Framework são extremamente simples de se utilizar além de  fornecerem uma enorme flexibilidade de extensão. Pode-se criar  adaptadores customizados para o Zend_Auth, o que permite estender suas funcionalidades de acordo com cada cenário, tudo isso com um código reaproveitável e bem refinado. Neste artigo procurei abordar os conceitos que envolvem os componentes de autenticação, com um exemplo simples utilizando eles, de acordo com cada situação este exemplo precisará de uma boa refatoração para melhorar o fluxo e o reaproveitamento de código. Para isso recomendo a leitura do manual do Zend Framework, encontrado logo abaixo nas referências do artigo.</p>
<h2>Referências</h2>
<ul>
<li><a id="yjqa" title="Zend_Auth no guia de referência do Zend Framework" href="http://framework.zend.com/manual/en/zend.auth.html">Zend_Auth no  guia de referência do Zend Framework</a>;</li>
<li><a id="swfv" title="Livro Zend Framework em Ação" href="http://altabooks.tempsite.ws/product_info.php?products_id=350&amp;osCsid=dfh1koampc9vmmbtmkt0br4hl0">Livro Zend Framework em  Ação</a>.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/frameworks/zend-framework/autenticacao-com-zend-framework/feed/</wfw:commentRss>
		<slash:comments>13</slash:comments>
		</item>
		<item>
		<title>Adicionando dual-boot no Ubuntu 10.04</title>
		<link>http://fernandomantoan.com/ubuntu/adicionando-dual-boot-no-ubuntu-10-04/</link>
		<comments>http://fernandomantoan.com/ubuntu/adicionando-dual-boot-no-ubuntu-10-04/#comments</comments>
		<pubDate>Sun, 02 May 2010 22:30:10 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[grub2]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[lucid lynx]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=585</guid>
		<description><![CDATA[No post anterior falei sobre como ficou bom o novo Ubuntu 10.04. O único problema que encontrei após instalá-lo foi que ele não adicionou no dual-boot uma instalação do Windows que possuo para trabalhar com Adobe Flex. Em alguns minutos resolvi isso, e criei este artigo para demonstrar as etapas necessárias para isso!]]></description>
			<content:encoded><![CDATA[<p>No <a href="http://fernandomantoan.com/ubuntu/ubuntu-10-04-lancado/">post anterior</a> falei sobre como ficou bom o novo <a title="Site Oficial do Ubuntu" href="http://www.ubuntu.com/" target="_blank">Ubuntu 10.04</a>. O único problema que encontrei após instalá-lo foi que ele não adicionou no dual-boot uma instalação do Windows que possuo para trabalhar com Adobe Flex. Em alguns minutos resolvi isso, e criei este artigo para demonstrar as etapas necessárias para isso!</p>
<h2>Verificando a partição</h2>
<p>No meu caso eu possuo apenas um hd, com uma partição NTFS para o Windows e outra EXT4 para o Ubuntu, então verifiquei rapidamente a partição de cada sistema operacional, com o seguinte comando:</p>
<pre class="brush: bash;">sudo fdisk -l</pre>
<p>Ele então me retornou a seguinte saída:</p>
<pre class="brush: bash;">Disco /dev/sda: 160.0 GB, 160041885696 bytes
255 heads, 63 sectors/track, 19457 cylinders
Unidades = cilindros de 16065 * 512 = 8225280 bytes
Sector size (logical/physical): 512 bytes / 512 bytes
I/O size (minimum/optimal): 512 bytes / 512 bytes
Identificador do disco: 0xb0f220b8

Dispositivo Boot Início Fim Blocos Id Sistema
/dev/sda1   *           1       11090    89079401    7  HPFS ou NTFS
/dev/sda2           11091       19457    67207897    5  Estendida
/dev/sda5           11091       19110    64420618+  83  Linux
/dev/sda6           19111       19457     2787246   82  Linux swap / Solaris</pre>
<p>Pode-se perceber então, que o Windows está na partição <strong>sda1</strong>, e o Ubuntu na partição <strong>sda5</strong>. Sendo o <strong>sda1</strong> a primeira partição lógica do meu HD, pode-se concluir que para inicializar o Windows, a raíz no Grub estaria na partição <strong>hd(0,1)</strong>. Se, por exemplo, o Windows estivesse em <strong>sda5</strong> a partição seria <strong>hd(0, 5)</strong>, se fosse <strong>sdb1</strong> seria <strong>hd(1, 1)</strong>, e assim vai&#8230;</p>
<h2>Identificando o Windows</h2>
<p>Após saber a raíz da partição Windows, é necessário criar um arquivo para que ele entre na lista de sistemas operacionais do Grub. Para isso, basta abrir um terminal e digitar o seguinte comando:</p>
<pre class="brush: bash;">sudo gedit /etc/grub.d/11_Windows</pre>
<p>Após abrir  o editor de textos, basta então colocar o seguinte conteúdo nele:</p>
<pre class="brush: bash;">#! /bin/sh -e
echo &quot;Adding Windows&quot; &gt;&amp;2
cat &lt;&lt; EOF
menuentry &quot;Windows Vista&quot; {
set root=(hd0,1)
chainloader +1
}
EOF</pre>
<p>Dar permissão de execução ao arquivo com o seguinte comando:</p>
<pre class="brush: bash;">sudo chmod a+x /etc/grub.d/11_Windows</pre>
<p>E, por último, atualizar o Grub2 para que ele adicione a entrada do Windows na tela de boot, para isso basta executar o seguinte comando:</p>
<pre class="brush: bash;">sudo update-grub2</pre>
<p>A saída do programa será algo similar a:</p>
<pre class="brush: bash;">
Generating grub.cfg ...
Found linux image: /boot/vmlinuz-2.6.32-21-generic
Found initrd image: /boot/initrd.img-2.6.32-21-generic
Adding Windows
Found memtest86+ image: /boot/memtest86+.bin
done
</pre>
<h2>Fim</h2>
<p>Após isso basta então reiniciar seu computador e deverá aparecer a entrada para o seu Windows na tela de inicialização do Grub2. Não é tão difícil quanto parece, apesar de o antigo Grub ter um processo muito mais simples. Até a próxima pessoal!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/ubuntu/adicionando-dual-boot-no-ubuntu-10-04/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>Ubuntu 10.04 Lançado</title>
		<link>http://fernandomantoan.com/ubuntu/ubuntu-10-04-lancado/</link>
		<comments>http://fernandomantoan.com/ubuntu/ubuntu-10-04-lancado/#comments</comments>
		<pubDate>Sun, 02 May 2010 22:06:38 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[linux]]></category>
		<category><![CDATA[lucid lynx]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=581</guid>
		<description><![CDATA[Olá pessoal, como vão? Nesta quinta-feira foi lançada a nova versão do Ubuntu, entitulada Lucid Lynx. Acabei de instalá-la no meu notebook e confesso que gostei muito do que vi. Dentre as principais mudanças, destacam-se: Novo visual, totalmente reformulado, com nova logotipo do Ubuntu; Boot extremamente rápido; Central de programas, que centraliza e simplifica a [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal, como vão? Nesta quinta-feira foi lançada a nova versão do <a title="Site Oficial do Ubuntu" href="http://www.ubuntu.com/" target="_blank">Ubuntu</a>, entitulada Lucid Lynx. Acabei de instalá-la no meu notebook e confesso que gostei muito do que vi. Dentre as principais mudanças, destacam-se:</p>
<ul>
<li>Novo visual, totalmente reformulado, com nova logotipo do Ubuntu;</li>
<li>Boot extremamente rápido;</li>
<li>Central de programas, que centraliza e simplifica a instalação de programas;</li>
<li>Armazenamento online com Ubuntu One (2gb Grátis);</li>
<li>Última versão de softwares como: Gnome, Firefox, Empathy;</li>
<li>Nova Music store, para comprar músicas online;</li>
<li>Cliente social <a title="Site Oficial do Gwibber" href="http://gwibber.com/" target="_blank">Gwibber</a> que agrega Twitter, Facebook, Orkut e diversas outras redes sociais;</li>
<li>Utilização do F-Spot no lugar do Gimp, com o intúito de deixar muito mais prática a edição e organização de imagens;</li>
<li>Editor de Vídeos Pitivi.</li>
</ul>
<p>Existem muitas outras novidades, mas acredito que estas sejam umas das principais. Eu fiquei surpreendido com a consistência e elegância da parte visual desta nova versão, além do aplicativo Gwibber e alguns outros pequenos detalhes. Não é a toa que esta á uma versão LTS (Long Term Support), a robustez é impressionante! Abaixo vocês podem conferir uma screenshot, que demonstra como ficou bonito o Ubuntu 10.04:</p>
<div id="attachment_582" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/05/screen_ubuntu.png"><img class="size-medium wp-image-582" title="screen_ubuntu" src="http://fernandomantoan.com/wp-content/uploads/2010/05/screen_ubuntu-300x187.png" alt="Imagem com o Desktop do Ubuntu 10.04" width="300" height="187" /></a><p class="wp-caption-text">Desktop do Ubuntu 10.04</p></div>
<p>Além destas novidades ele continua com o excelente suporte às placas Wireless, no meu notebook (um Semp Toshiba extremamente problemático com distros Linux) tudo já veio funcionando &#8220;de fábrica&#8221;, tanto a Wireless quanto a placa de vídeo. Pois é, mais uma versão LTS muito boa lançada pela Canonical, não perca tempo e <a title="Download do Ubuntu" href="http://www.ubuntu.com/getubuntu/download" target="_blank">pegue já a sua</a>!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/ubuntu/ubuntu-10-04-lancado/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Integrando o Doctrine com o Zend Framework</title>
		<link>http://fernandomantoan.com/php/integrando-o-doctrine-com-o-zend-framework/</link>
		<comments>http://fernandomantoan.com/php/integrando-o-doctrine-com-o-zend-framework/#comments</comments>
		<pubDate>Sun, 28 Mar 2010 19:10:36 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[doctrine]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=513</guid>
		<description><![CDATA[Neste artigo demonstro uma maneira de integrar o framework de mapeamento objeto relacional Doctrine com o Zend Framework. Esta integração pode ser útil em projetos que necessitam de uma ferramento mais consistente mara fazer o mapeamento objeto relacional, tendo em vista que o Zend_Db ainda não possui boas funcionalidades para este objetivo. O Doctrine também [...]]]></description>
			<content:encoded><![CDATA[<p>Neste artigo demonstro uma maneira de integrar o <em>framework</em> de mapeamento objeto relacional Doctrine com o Zend Framework. Esta integração pode ser útil em projetos que necessitam de uma ferramento mais consistente mara fazer o mapeamento objeto relacional, tendo em vista que o Zend_Db ainda não possui boas funcionalidades para este objetivo. O Doctrine também se mostra consistente na gestão de memória, liberando recursos conforme eles não são mais necessários, além de outros recursos interessantes para as aplicações.</p>
<h2>Introdução ao Doctrine</h2>
<p>O Doctrine é uma ferramenta de mapeamento objeto-relacional (ORM) para PHP 5.2.3+. Um de seus principais recursos é a opção de se escrever consultas de bancos de dados em um dialeto SQL proprietário orientado a objetos chamado Doctrine <em>Query Language</em> (DQL), que foi inspirada na Hibernate <em>Query Language</em> (HQL) do <em>framework</em> Hibernate para Java. Isso fornece aos desenvolvedores uma alternativa poderosa ao SQL que mantém a flexibilidade sem duplicações desnecessárias de código.</p>
<p>Os <em>Models</em> gerados pelo Doctrine extendem da classe Doctrine Record, onde todos eles herdam métodos típicos de um <em>Active Record</em>, como os métodos <em>save</em>, <em>delete</em>, etc, além de permitir que o Doctrine participe e monitore o ciclo de vida dos registros. Outros componentes do Doctrine fazem os trabalhos mais pesados, como por exemplo a classe Doctrine_Table. Esta classe possui os métodos típicos de um <em>Data Mapper</em>, como, por exemplo, <em>createQuery</em>, <em>find</em>, <em>findAll</em>, <em>findBy*</em>, etc.</p>
<p>No Doctrine as consultas são baseadas em <strong>classes</strong> ao invés de <strong>tabelas</strong>, para demonstrar um exemplo, considere a seguinte consulta:</p>
<pre class="brush: sql;">FROM Usuario
LEFT JOIN u.Enderecos WHERE u.id = 1</pre>
<p>Com ela pode-se notar o seguinte:</p>
<ul>
<li>É feita uma seleção do <strong><em>Model</em> Usuario</strong> e não da tabela;</li>
<li>É possível referenciar os campos do <em>Model</em>;</li>
<li>São feitos <em>joins</em> com associações;</li>
<li>Não existe condição de <em>join</em>, as associações entre as classes e como elas estão no banco de dados são conhecidas pelo Doctrine.</li>
</ul>
<p>Estas informações foram traduzidas do <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/introduction" target="_blank">Manual Oficial do Doctrine</a>, com algumas modificações para clarear o entendimento.</p>
<h2>Definição do Projeto com o Zend Framework</h2>
<p>Agora que já foi feita uma breve explicação sobre o Doctrine é hora de gerar um projeto de exemplo com o Zend Framework. O projeto criado será bem simples, apenas para exemplificar algumas operações básicas com o Doctrine. Neste ponto presumo que você leitor tenha o Zend Framework e sua ferramenta de linha de comando configurados em seu sistema operacional. Caso não tenha feito isso, recomendo o <a href="http://blog.adlermedrado.com.br/zend-framework-tutorial-series-capitulo-1" target="_blank">tutorial do Adler Medrado</a>, onde ele ensina como fazer estas configurações.</p>
<p>O primeiro passo é criar a estrutura do projeto com o comando:</p>
<pre class="brush: bash;">zf create project zf_doctrine</pre>
<p>Caso nenhum erro ocorra este comando gerará a seguinte estrutura:</p>
<div id="attachment_521" class="wp-caption aligncenter" style="width: 192px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_zf.png"><img class="size-full wp-image-521" title="estrutura_zf" src="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_zf.png" alt="" width="182" height="217" /></a><p class="wp-caption-text">Estrutura básica de um projeto Zend Framework</p></div>
<p>A pasta <strong>application</strong> será onde o código específico da aplicação será armazenado. Este código inclui as configurações da aplicação para ambiente de desenvolvimento, produção ou demais ambientes configurados; os <em>Controllers</em> responsáveis por intermediar o fluxo entre as <em>Views</em>, que cuidam da apresentação ao usuário, e os <em>Models</em> responsáveis pela lógica de negócio da aplicação.</p>
<p>A pasta <strong>docs</strong> é utilizada para armazenar as documentações da aplicação e dos componentes. <strong>library</strong> é onde ficam armazenados os <em>plugins</em>, componentes e demais bibliotecas de terceiros. Ela é utilizada para armazenar o Doctrine e toda estrutura de classes do Zend Framework. A pasta <strong>public</strong> é a pasta acessível pelo servidor <em>web</em>, onde é feita toda a chamada para inicializar a aplicação, seguindo o padrão <em>Front Controller</em>. E a pasta <strong>testes</strong> é onde são armazenados os testes unitários.</p>
<h2>Integração</h2>
<p>A primeira coisa a se fazer é o <em>download</em> do <em>framework</em> Doctrine. Na data em que este artigo foi escrito a última versão estável do <em>framework</em> é a 1.2.1. Você pode baixá-la <a href="http://www.doctrine-project.org/download" target="_blank">neste link</a>. Após ter efetuado o <em>download</em> e extraído o pacote, é necessário copiar todo o conteúdo da pasta <strong>lib</strong> para a pasta <strong>library</strong> do projeto Zend Framework criado, resultando na seguinte estrutura:</p>
<div id="attachment_522" class="wp-caption aligncenter" style="width: 197px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_com_doctrine.png"><img class="size-full wp-image-522" title="estrutura_com_doctrine" src="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_com_doctrine.png" alt="" width="187" height="272" /></a><p class="wp-caption-text">Estrutura com o Doctrine extraído</p></div>
<p>Após isso é necessário criar a pasta <strong>db</strong> e dentro dela as seguintes pastas:</p>
<ul>
<li><strong>fixtures</strong> &#8211; Pasta onde armazenará arquivos de definição de dados para popular o banco de dados;</li>
<li><strong>migrations</strong> &#8211; Arquivos de migração entre diferentes versões de banco de dados;</li>
<li><strong>schema</strong> &#8211; Definição de toda estrutura do banco de dados, seguindo o formato YAML;</li>
<li><strong>sql</strong> &#8211; Armazena a estrutura SQL que define o banco de dados.</li>
</ul>
<p>Depois de criar estas pastas, também pode ser criada a pasta para armazenar os <em>scripts</em> de linha de comando do Doctrine. Dentro de <strong>application</strong> é criada uma pasta com o nome de <strong>scripts</strong>. Após criar todas estas pastas a estrutura será a seguinte:</p>
<div id="attachment_523" class="wp-caption aligncenter" style="width: 168px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_final.png"><img class="size-medium wp-image-523" title="estrutura_final" src="http://fernandomantoan.com/wp-content/uploads/2010/03/estrutura_final-158x300.png" alt="" width="158" height="300" /></a><p class="wp-caption-text">Estrutura final de diretórios</p></div>
<p>Após toda a estrutura estar definida é hora de começar a configurar o projeto. A primeira coisa a se fazer é, abrir o arquivo <strong>application/configs/application.ini</strong>, e acrescentar o seguinte conteúdo nele, na seção <strong>[production]</strong>:</p>
<pre class="brush: plain;">autoloaderNamespaces[] = &quot;Doctrine&quot;
doctrine.dsn = &quot;mysql://usuario:senha@host/banco&quot;
doctrine.models_path = APPLICATION_PATH &quot;/models&quot;
doctrine.data_fixtures_path = APPLICATION_PATH &quot;/../db/fixtures&quot;
doctrine.migrations_path = APPLICATION_PATH &quot;/../db/migrations&quot;
doctrine.sql_path = APPLICATION_PATH &quot;/../db/sql&quot;
doctrine.yaml_schema_path = APPLICATION_PATH &quot;/../db/schema&quot;
; Conservative Model Loading
doctrine.model_autoloading = 2</pre>
<p>Nestas linhas é definido o <em>Namespace</em> utilizado pelo Doctrine para o <strong>autoLoader</strong> carregar as classes automaticamente, logo em seguida é definido um Nome de Fonte de Dados (<em>Data Source Name</em> &#8211; DSN) para a localização do banco de dados, em seguida são definidas as pastas onde são armazenados os <strong>models</strong>, as <strong>fixtures</strong>, a <strong>sql</strong>, e o <strong>schema</strong>, e, por último é definida a forma como o Doctrine carregará os <em>Models</em>, neste caso é utilizado o <em><strong>Conservative</strong></em>, que carrega os <em>Models</em> conforme eles sejam necessários.</p>
<p>Logo abaixo da linha <strong>doctrine.model_autoloading</strong> é necessário definir algumas configurações para a ferramenta de linha de comando do Doctrine (Doctrine Cli), basta colocar o seguinte conteúdo:</p>
<pre class="brush: plain;">[doctrineCLI : production]
doctrine.generate_models_options.pearStyle = true
doctrine.generate_models_options.generateTableClasses = false
doctrine.generate_models_options.generateBaseClasses = true
doctrine.generate_models_options.baseClassPrefix = &quot;Base_&quot;
doctrine.generate_models_options.baseClassesDirectory =
doctrine.generate_models_options.classPrefixFiles = false
doctrine.generate_models_options.classPrefix = &quot;Model_&quot;
; Agressive Model Loading
doctrine.model_autoloading = 1</pre>
<p>Neste ambiente é necessário configurar as formas como os <em>Models</em> serão gerados. A primeira linha configura a nomenclatura no formato PEAR, onde o nome da classe contém como prefixos a estrutura de diretório onde ela está localizada, por exemplo, Model_Produto, estará na pasta <strong>model/Produto.php</strong>, no caso da nomenclatura do Zend Framework, a pasta <strong>models</strong> terá como prefixo <strong>Model_</strong>, seguindo o padrão do <em>Autoloader</em> do <em>framework</em>. A segunda linha indica ao Doctrine CLI para não gerar as classes <em>Table</em> automaticamente. A terceira linha configura o Doctrine CLI para que gere classes base, onde a quarta linha configura o prefixo das classes Base e a linha seguinte define um diretório vazio, fazendo com que as classes geradas sejam armazenadas no diretório <strong>models/base</strong> ao invés de <strong>models/Model/Base</strong>. A próxima linha indica que os nomes de arquivos não devem conter prefixos, a linha seguinte indica ao prefixo das classes geradas, que deverá ser <strong>Model_</strong>, como explicado. E a última linha define que a forma de carregar os <em>Models</em> será <em><strong>Agressive</strong></em>, ou seja, eles são carregados na inicialização do Doctrine.</p>
<p>Após definir toda essa estrutura é  hora de configurar a inicialização do Zend Framework para que ele carregue e configure corretamente o Doctrine e demais classes necessárias pela aplicação. Para isso, basta abrir o arquivo <strong>application/Bootstrap.php</strong>, e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">
&lt;?php
class Bootstrap extends Zend_Application_Bootstrap_Bootstrap
{
	protected function _initAutoload()
	{
		$autoloader = new Zend_Application_Module_Autoloader(array(
			'basePath' =&gt; APPLICATION_PATH,
			'namespace' =&gt; ''
		));
		return $autoloader;
	}
	protected function _initDoctrine()
	{
		$this-&gt;getApplication()-&gt;getAutoloader()
								-&gt;pushAutoloader(array('Doctrine', 'autoload'));
		spl_autoload_register(array('Doctrine', 'modelsAutoload'));

		$doctrineConfig = $this-&gt;getOption('doctrine');
		$manager = Doctrine_Manager::getInstance();
		$manager-&gt;setAttribute(Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);
		$manager-&gt;setAttribute(
			Doctrine::ATTR_MODEL_LOADING,
			$doctrineConfig['model_autoloading']
		);
		Doctrine::loadModels($doctrineConfig['models_path']);

		$conn = Doctrine_Manager::connection($doctrineConfig['dsn'], 'doctrine');
		$conn-&gt;setAttribute(Doctrine::ATTR_USE_NATIVE_ENUM, true);
		return $conn;
	}
}
</pre>
<p>O primeiro método configura o <em>Autoloader</em> do Zend Framework, para que ele cuide do carregamento das classes necessárias na aplicação. O segundo método configura o Doctrine. Primeiramente ele adiciona o <em>Autoloader</em> do Doctrine ao <em>Autoloader</em> do Zend Framework, permitindo ao Doctrine carregar as classes específicas de seus componentes. A próxima linha configura o <em>Autoloader</em> de <em>Models</em> do Doctrine, para que o Doctrine também cuide do carregamento de seus <em>Models</em>, conforme for necessário na aplicação. As linhas seguintes cuidam de:</p>
<ul>
<li>Pegar as configurações definidas no arquivo <strong>application.ini</strong>;</li>
<li>Definir os atributos do Doctrine, onde o primeiro atributo definido é a sobrescrita de acessores e o segundo é a forma como os <em>Models</em> são carregados;</li>
<li>Carregar os <em>Models</em>, conforme a forma definida na linha anterior;</li>
<li>Gerar uma conexão ao banco de dados, baseada na <strong>dsn</strong> definida no arquivo de configuração;</li>
<li>Utilizar a forma nativa de ENUM.</li>
</ul>
<p>Com isso o arquivo de inicialização do Zend Framework está devidamente configurado. A última etapa é criar a ferramenta de linha de comando do Doctrine. Para fazer isso basta criar o arquivo <strong>application/scripts/doctrine.php</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">
&lt;?php
//Caminho para a pasta da aplicação
defined('APPLICATION_PATH')
    || define('APPLICATION_PATH', realpath(dirname(__FILE__) . '/..'));
//Ambiente em que a aplicação será executada
defined('APPLICATION_ENV')
    || define('APPLICATION_ENV', (getenv('APPLICATION_ENV') ? getenv('APPLICATION_ENV') : 'doctrineCLI'));

//Adiciona a &quot;library&quot; no include_path
set_include_path(implode(PATH_SEPARATOR, array(
    realpath(APPLICATION_PATH . '/../library'),
    get_include_path()
)));

require_once 'Zend/Application.php';
//Cria a aplicação, faz o bootstrap e a executa
$application = new Zend_Application(
    APPLICATION_ENV,
    APPLICATION_PATH . '/configs/application.ini'
);

$application-&gt;getBootstrap()-&gt;bootstrap('autoload');
$application-&gt;getBootstrap()-&gt;bootstrap('doctrine');

$config = $application-&gt;getOption('doctrine');

$cli = new Doctrine_Cli($config);
$cli-&gt;run($_SERVER['argv']);
</pre>
<p>Este arquivo irá definir a pasta da aplicação, o ambiente <strong>doctrineCLI</strong>, para pegar as configurações específicas da ferramenta de linha de comando, conforme definido no arquivo <strong>application.ini</strong>, adicionar a biblioteca de componentes no <strong>include_path</strong>, inicializar a aplicação, assim como o <em>Autoload</em> do Zend Framework e o Doctrine, pegar as configurações definidas em <strong>application.ini</strong>, e, finalmente chamar o Doctrine CLI para cuidar de todo o resto. Por último é necessário criar o arquivo executável responsável por chamar esta ferramenta definida. Para isso basta criar o arquivo <strong>application/scripts/doctrine</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: bash;">#!/usr/bin/env /usr/bin/php
&lt;?php
chdir(dirname(__FILE__));
include('doctrine.php');</pre>
<p>O próximo passo é dar permissão de execução a esse arquivo:</p>
<pre class="brush: bash;">$ chmod a+x zf_doctrine/application/scripts/doctrine</pre>
<h2>Testando</h2>
<p>Antes de mais nada, a primeira coisa a se fazer é testar o cliente de linha de comando. Para isso, em um terminal, execute o seguinte comando:</p>
<pre class="brush: bash;">$ zf_doctrine/application/scripts/doctrine</pre>
<p>A saída deste comando deverá ser a seguinte:</p>
<pre class="brush: bash;">Doctrine Command Line Interface

doctrine.php build-all
doctrine.php build-all-load
doctrine.php build-all-reload
doctrine.php compile
doctrine.php create-db
doctrine.php create-tables
doctrine.php dql
doctrine.php drop-db
doctrine.php dump-data
doctrine.php generate-migration
doctrine.php generate-migrations-db
doctrine.php generate-migrations-diff
doctrine.php generate-migrations-models
doctrine.php generate-models-db
doctrine.php generate-models-yaml
doctrine.php generate-sql
doctrine.php generate-yaml-db
doctrine.php generate-yaml-models
doctrine.php load-data
doctrine.php migrate
doctrine.php rebuild-db</pre>
<p>Se preferir, adicione esta ferramenta no <strong>include_path</strong> de sua aplicação, seguindo a mesma idéia explanada pelo Adler Medrado. Caso o comando retorne a saída demonstrada acima, a ferramenta da linha de comando deverá estar funcionando corretamente. Agora é hora de criar um banco de dados chamado <strong>carros_doctrine</strong>. Após criá-lo, crie o arquivo <strong>db/schema/schema.yml</strong>, e coloque o seguinte conteúdo nele:</p>
<pre class="brush: plain;">
Carro:
  connection: 0
  tableName: carro
  columns:
    id:
      type: integer(4)
      fixed: false
      unsigned: true
      primary: true
      autoincrement: true
    nome:
      type: string(150)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false
    cor:
      type: string(150)
      fixed: false
      unsigned: false
      primary: false
      notnull: true
      autoincrement: false</pre>
<p>Neste arquivo é feita a definição de uma tabela chamada &#8220;Carro&#8221; para o banco de dados, onde esta tabela terá as colunas:</p>
<ul>
<li><strong>id</strong> &#8211; Que será um campo do tipo Inteiro, chave primária, não aceitará valores nulos e nem valores negativos (<em>unsigned</em>)  e será um campo auto-incremental;</li>
<li><strong>nome</strong> &#8211; Será um campo do tipo String, com o tamanho de 150 caracteres e  que não pode ser nulo;</li>
<li><strong>cor</strong> &#8211; Será um campo do tipo String, com o tamanho de 150 caracteres e  que  não pode ser nulo.</li>
</ul>
<p>Após criar o banco e definir este arquivo, basta executar a ferramenta de linha de comando para que ela gere o banco de dados e os <em>Models</em>. Para isso basta executar o seguinte comando:</p>
<pre class="brush: bash;">
$ zf_doctrine/application/scripts/doctrine build-all-reload
build-all-reload - Are you sure you wish to drop your databases? (y/n)
y
build-all-reload - Successfully dropped database for connection named 'doctrine'

build-all-reload - Generated models successfully from YAML schema
build-all-reload - Successfully created database for connection named 'doctrine'

build-all-reload - Created tables successfully
build-all-reload - Data was successfully loaded
</pre>
<p>Após executar este comando basta verificar se a pasta <strong>models</strong> está devidamente preenchida com o arquivo<strong> Carro.php</strong> e <strong>Base/Carro.php</strong>.</p>
<p>Agora, caro queira gerar o SQL da aplicação, basta executar o seguinte comando:</p>
<pre class="brush: bash;">
$ zf_doctrine/application/scripts/doctrine generate-sql
generate-sql - Generated SQL successfully for models
</pre>
<p>Após isso, o arquivo <strong>db/sql/schema.sql</strong> será criado e conterá a SQL do banco de dados, como o trecho a seguir:</p>
<pre class="brush: sql;">
CREATE TABLE carro (
	id INT UNSIGNED AUTO_INCREMENT,
	nome VARCHAR(150) NOT NULL,
	cor VARCHAR(150) NOT NULL,
	PRIMARY KEY(id)
) ENGINE = INNODB;
</pre>
<p>Agora, o último teste para verificar se tudo está corretamente integrado é fazer algumas chamadas no <em>Controller</em> e verificar se tudo é executado corretamente. Dentro do arquivo <strong>application/controllers/IndexController.php</strong>, existe o método <strong>indexAction()</strong>, basta definí-lo como a seguir:</p>
<pre class="brush: php;">
public function indexAction()
{
	$carro = new Model_Carro();
	$carro-&gt;nome = &quot;Ferrari&quot;;
	$carro-&gt;cor = &quot;Vermelha&quot;;
	$carro-&gt;save();

	$query = new Doctrine_Query();
	$query-&gt;from('Model_Carro c');
	$query-&gt;orderBy('c.id DESC');
	$this-&gt;view-&gt;carros = $query-&gt;execute();
}
</pre>
<p>Neste método é criado um novo carro com o nome &#8220;Ferrari&#8221; e a cor &#8220;Vermelha&#8221;, e então é inserido este carro no banco de dados. Após isso uma consulta de todos os carros do banco de dados é executada e, então, esta consulta é passada para a <em>View</em>, onde é feita uma listagem destes carros e apresentado ao usuário.</p>
<p>Para fazer esta listagem altere o arquivo <strong>application/views/scripts/index/index.phtml</strong> e deixe-o com o seguinte conteúdo:</p>
<pre class="brush: php;">
&lt;?php foreach ( $this-&gt;carros as $carro ): ?&gt;
&lt;h1&gt;Carro #&lt;?php echo $carro-&gt;id; ?&gt;&lt;/h1&gt;
&lt;p&gt;Nome: &lt;?php echo $carro-&gt;nome; ?&gt;&lt;/p&gt;
&lt;p&gt;Cor: &lt;?php echo $carro-&gt;cor; ?&gt;&lt;/p&gt;
&lt;hr /&gt;
&lt;?php endforeach; ?&gt;
</pre>
<p>Nele é feito um laço para percorrer todos os carros imprimindo os dados de cada um ao usuário. Agora basta ir no <em>browser</em> e acessar o projeto, que o seguinte conteúdo será exibido:</p>
<div id="attachment_531" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/03/resultado_browser.png"><img class="size-medium wp-image-531" title="resultado_browser" src="http://fernandomantoan.com/wp-content/uploads/2010/03/resultado_browser-300x204.png" alt="" width="300" height="204" /></a><p class="wp-caption-text">Listagem dos Carros</p></div>
<p>Caso todo este processo ocorra sem erros o Doctrine está devidamente integrado ao Zend Framework.</p>
<h2>Conclusão</h2>
<p>O Doctrine é uma ferramenta robusta e consistente para mapeamento objeto relacional, e unindo todas as suas funcionalidades com os componentes do Zend Framework é possível obter uma arquitetura altamente consistente e com ferramentas de alto nível. Apesar de ser uma solução minimalista, a integração se mostra devidamente eficaz, provendo todas as funcionalidades das ferramentas de linha de comando e dos componentes de ambos os <em>frameworks</em>. Existem diversas formas de se integrar o Doctrine com o Zend Framework, esta pode não ser a melhor, porém funciona sem maiores problemas. Logo abaixo coloco alguns <em>links</em> com outras formas de integração assim como o <em>screencast</em> que utilizei como base para elaborar este artigo. Até a próxima.</p>
<h2>Código-Fonte</h2>
<p>O <em>link</em> abaixo é o pacote com todo o código-fonte do projeto desenvolvido neste artigo, junto com a biblioteca Doctrine.</p>
<p><a href="http://fernandomantoan.com/wp-content/uploads/2010/03/zf_doctrine.tar.gz">zf_doctrine.tar</a></p>
<h2>Links Úteis</h2>
<ul>
<li><a href="http://zendcasts.com/deep-integration-between-zend-and-doctrine-1-2/2010/01/">Deep Integration between Zend and Doctrine 1.2</a></li>
<li><a href="http://dev.juokaz.com/php/zend-framework-and-doctrine-part-1">Zend Framework and Doctrine &#8211; Part 1</a></li>
<li><a href="http://weierophinney.net/matthew/archives/220-Autoloading-Doctrine-and-Doctrine-entities-from-Zend-Framework.html">Autoloading Doctrine and Doctrine entities from Zend Framework</a></li>
<li><a href="http://framework.zend.com">Zend Framework</a></li>
<li><a href="http://doctrine-project.org/">Doctrine</a></li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/integrando-o-doctrine-com-o-zend-framework/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
		<item>
		<title>Frameworks para Rich Internet Applications</title>
		<link>http://fernandomantoan.com/ria/rich-internet-applications/</link>
		<comments>http://fernandomantoan.com/ria/rich-internet-applications/#comments</comments>
		<pubDate>Mon, 22 Mar 2010 15:46:49 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[RIA]]></category>
		<category><![CDATA[extjs]]></category>
		<category><![CDATA[flex]]></category>
		<category><![CDATA[jquery]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=471</guid>
		<description><![CDATA[Olá a todos. Neste artigo gostaria de compartilhar minha experiência com frameworks Rich Internet Application (RIA), o que pode ajudar quem está querendo melhorar a User Interface (UI) de suas aplicações web mas não sabe muito bem qual framework escolher dentre a grande variade disponível. Todo conteúdo deste artigo é uma opinião pessoal, não quero que achem que sou o [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos. Neste artigo gostaria de compartilhar minha experiência com <em>frameworks Rich Internet Application</em> (RIA), o que pode ajudar quem está querendo melhorar a <em>User Interface</em> (UI) de suas aplicações <em>web</em> mas não sabe muito bem qual <em>framework</em> escolher dentre a grande variade disponível. Todo conteúdo deste artigo é uma opinião pessoal, não quero que achem que sou o dono da verdade, apesar de defender a minha escolha com relação a <em>frameworks</em> RIA, cabe a cada um pesquisar bem as alternativas e escolher o que mais se adapta à sua realidade.</p>
<h2>JQuery</h2>
<p>Uma das minhas primeiras experiências com RIA foi utilizando <a href="http://jquery.com" target="_blank">Jquery</a> e sua extensão <a href="http://jqueryui.com" target="_blank">Jquery UI</a> que fornece diversos componentes RIA para as aplicações. Jquery é conhecida por ser simples, altamente extensível e por ter diversos recursos e <em>plugins</em>, além de uma comunidade forte e ativa. A Jquery UI possui bons componentes para deixar as aplicações mais bonitas e amigáveis, ela também possui um <em>framework</em> CSS muito consistente, o que facilita a criação de temas para seus componentes, porém ela não tem uma boa abrangência das necessidades de sistemas, como, por exemplo, a falta de uma <em>Grid</em> e de uma <em>Toolbar</em>, além de outros componentes é claro. Isso mostra que o <em>framework</em> ainda tem muito o que crescer, apesar disso ele está num ótimo caminho e tem se mostrado muito <strong>promissor</strong>.</p>
<p>Com a falta destes componentes é necessário procurar componentes fornecidos via <em>plugins</em>, o problema disso é que nem sempre é uma solução consistente, de fácil extensibilidade e customização, um exemplo disso é com relação a <em>Grid</em>, existem opções disponíveis, porém boa parte está em beta ou alpha, e para customizar o componente é necessário um belo estudo em toda estrutura que o desenvolvedor definiu. Existem <em>proposals</em> para que próximas <em>releases</em> da Jquery UI agreguem estes componentes, porém será que seu projeto pode esperar até estas <em>releases</em>?</p>
<p>A Jquery pode ser uma boa opção se a equipe possui tempo disponível para customizar os componentes ou se sua aplicação não necessita de grandes alterações no visual do tema e dos componentes externos adotados. O <em>framework</em> é de fácil aprendizado, portanto isso seria um bom diferencial quanto a outros <em>frameworks</em> Javascript.</p>
<h2>ExtJS</h2>
<p><a href="http://extjs.com" target="_blank">ExtJS</a> é um <em>framework</em> Javascript com uma gama enorme de <em>widgets</em> para aplicações <em>web</em>. Existem diversos temas prontos, alguns fornecidos pelo próprio site da ExtJS e outros facilmente encontrados pela internet, além da flexibilidade fornecida pelo <em>framework</em>, para a extensão dos <em>widgets</em> já prontos. Segundo o site da ExtJS, os <em>widgets</em> seguem estritamente os padrões <em>web</em> e os temas prontos fornecem um bom suporte a diversos <em>browsers</em>, como IE, Firefox e Opera, dentre outros. Acredito que a principal vantagem deste <em>framework</em> é a quantidade de componentes que ele possui, é extremamente raro existir a necessidade de se implementar um novo componente do zero.</p>
<p>Além desta gama de componentes, as funcionalidades da ExtJS também são bem completas. O <em>framework</em> fornece funcionalidades para utilização de AJAX, para manipulação de DOM, para extensão de componentes, para armazenar fontes de dados (<em>datasources</em>), <em>templates</em> para apresentação de dados, etc. É um <em>framework </em>realmente completo, o que é possível de se perceber no tamanho do pacote de <em>download</em> fornecido no site oficial.</p>
<p>Uma das principais desvantagens é a &#8220;burocracia&#8221; necessária para utilizar ou extender os componentes. A sintaxe da ExtJS é mais extensa do que a da Jquery, por exemplo, mas com um pouco de tempo utilizando o <em>framework</em> isso acaba não sendo mais uma barreira. Outra desvantagem é a comunidade. Apesar de ser possível obter respostas rápidas nos fóruns nacionais/internacionais, os <em>experts</em> tendem a parecer um pouco rudes com os novatos, mas com um pouco de insistência eles acabam dando uma boa ajuda na solução de <em>bugs</em> e dúvidas.</p>
<p>Acredito que a utilização da ExtJS depende muito do prazo definido para o projeto e do aprendizado da equipe. No começo o <em>framework</em> tende a ser um pouco complexo, principalmente para quem está acostumado com Jquery ou algum outro <em>framework</em> Javascript fácil de se trabalhar, mas após uma boa vivência com o <em>framework</em> ele torna-se um aliado poderoso para a UI.</p>
<h2>Adobe Flex</h2>
<p><a href="http://flex.org" target="_blank">Adobe Flex</a>, odiado por uns, amado por outros. Para mim é o <em>framework</em> RIA mais robusto e de fácil aprendizagem com que já trabalhei. No início pode parecer um bicho de sete cabeças, mas com pouco tempo de estudo é possível já codificar as UIs e comunicar com a aplicação remota muito facilmente. Uma de suas principais características é a independência do <em>backend</em>, você pode ter PHP e com muita facilidade mudar para outra linguagem como Java ou Rails. Ele possui muitos componentes, todas as necessidades de um sistema RIA podem ser supridas com este <em>framework</em>. Outra vantagem é que por rodar no Flash Player o visual é consistente por todos os <em>browsers</em>, inclusive o IE.</p>
<p>Inicialmente eu não tive uma boa experiência com ele, talvez pela falta de vontade de aprender (sempre odiei Flash), ou pela forma com que estava trabalhando, mas posteriormente vi que ele dava conta do recado e que só precisava ser utilizado da forma correta. Você pode definir uma <em>skin</em> para a sua aplicação, utilizar algum <em>framework</em> como Swiz ou Cairgorn para melhorar a estrutura e facilitar em alguns pontos da UI, além de existir a possibilidade de, além de fazer uma versão para rodar no <em>browser</em>, fazer uma versão com Adobe AIR para rodar no computador, semelhantemente a uma aplicação <em>desktop</em>, como Delphi ou Java com Swing.</p>
<p>É a tecnologia que estou prefirindo para RIA, utilizando PHP como <em>backend</em>. Algumas barreiras sempre aparecem, porém o <a href="http://www.adobe.com/support/documentation/en/flex/" target="_blank"><em>Live Docs</em> da Adobe</a> quase sempre soluciona os problemas, quando não soluciona, existem diversos grupos de discussão e fóruns.</p>
<h2>Conclusão</h2>
<p>As alternativas são muitas, além destes citados no artigo, ainda existe o OpenLaszlo, o JavaFX, fora os diversos <em>frameworks</em> Javascript, como o do Yahoo e etc. No meu caso o Adobe Flex supre as necessidades que encontro com relação a UI, além de me dar interoperabilidade, tanto na <em>web</em> como no <em>desktop</em> (com o Adobe AIR), flexibilidade na escolha do <em>backend</em> e uma boa comunidade para ajudar quando surge alguma dificuldade. Como disse no início do artigo, isso pode variar de pessoa para pessoa, cabe a cada um pesquisar e ver o que mais se adequa a sua realidade. E você leitor, tem alguma experiência com <em>frameworks</em> RIA? Deixe no campo de comentários sua opinião, todas opiniões são bem-vindas e pode auxiliar quem está a procura de um bom <em>framework</em> RIA.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/ria/rich-internet-applications/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Voucher Zend Framework Certified Engineer</title>
		<link>http://fernandomantoan.com/certificacoes/voucher-zend-framework-certified-engineer/</link>
		<comments>http://fernandomantoan.com/certificacoes/voucher-zend-framework-certified-engineer/#comments</comments>
		<pubDate>Thu, 18 Mar 2010 14:02:34 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Certificações]]></category>
		<category><![CDATA[Zend Framework]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=483</guid>
		<description><![CDATA[Olá pessoal. Como havia falado em outro post, se conseguisse a certificação PHP5 eu iria me candidatar à certificação de Zend Framework, e é isso que fiz. Comprei o voucher no final do ano passado, e, agora inicei os estudos para fazer a prova até Junho deste ano. A preparação para esta prova é um [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal. Como havia falado em <a href="http://fernandomantoan.com/sem-categoria/voucher-zend-certified-engineer-comprado/">outro post</a>, se conseguisse a certificação PHP5 eu iria me candidatar à certificação de <a href="http://framework.zend.com/">Zend Framework</a>, e é isso que fiz. Comprei o <em><a href="http://shop.zend.com/en/zend-framework-certification-voucher.html">voucher</a></em> no final do ano passado, e, agora inicei os estudos para fazer a prova até Junho deste ano. A preparação para esta prova é um pouco diferente já que ainda não existem simulados do mesmo estilo da de PHP5, porém verifiquei que o <em><a href="http://www.zend.com/community/downloads">Study Guide</a></em> fornecido pela Zend possui algumas questões que devem ajudar no teste dos conhecimentos. O conteúdo da prova aborda <strong>TUDO</strong> existente no Zend Framework versão 1.5. Eu desenvolvo com o Zend Framework a aproximadamente uns 5 meses, porém é difícil existir requisitos que exijam aplicação de todos os componentes do <em>framework</em>, apesar de já ter uma noção geral da estrutura e da forma como os componentes são desenvolvidos. Este estudo árduo tira todo o tempo livre que sobrava para escrever no blog, mas acredito que conforme for me aprofundando no <em>framework</em> posso postar aqui algum conteúdo interessante sobre os componentes. Então é isso pessoal, até a próxima!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/certificacoes/voucher-zend-framework-certified-engineer/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Ubuntu 9.10 e arquivos .7z</title>
		<link>http://fernandomantoan.com/ubuntu/ubuntu-9-10-e-arquivos-7z/</link>
		<comments>http://fernandomantoan.com/ubuntu/ubuntu-9-10-e-arquivos-7z/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 23:22:06 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[7zip]]></category>
		<category><![CDATA[synaptic]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=463</guid>
		<description><![CDATA[Neste artigo demonstro o processo necessário para adicionar suporte a arquivos do 7z no Ubuntu 9.10. É um processo bem simples e fácil, e em poucas linhas é possível explaná-lo.]]></description>
			<content:encoded><![CDATA[<p>Gostaria de compartilhar com vocês como adicionar suporte a arquivos .7z no Ubuntu 9.10. É um processo bem simples, basta instalar o pacote <strong>p7zip-full</strong> com o comando:</p>
<pre class="brush: bash;">sudo apt-get install p7zip-full</pre>
<p>Assim o compactador de arquivos já poderá extrair os arquivos .7z. Para extraí-los via terminal:</p>
<pre class="brush: bash;">7z x nomedoarquivo.7z</pre>
<p>E para ver todas as opções:</p>
<pre class="brush: bash;">7z -h</pre>
<p>É isso pessoal, até a próxima.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/ubuntu/ubuntu-9-10-e-arquivos-7z/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Revisão dos artigos da Arquitetura de Software com CI</title>
		<link>http://fernandomantoan.com/offtopic/revisao-dos-artigos-da-arquitetura-de-software-com-ci/</link>
		<comments>http://fernandomantoan.com/offtopic/revisao-dos-artigos-da-arquitetura-de-software-com-ci/#comments</comments>
		<pubDate>Tue, 23 Feb 2010 23:11:32 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Offtopic]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=460</guid>
		<description><![CDATA[Olá pessoal, como vão? Bom, percebi que uma das fontes de visitas do meu site são os artigos onde defino uma arquitetura de software com CodeIgniter, integrando Smarty, Doctrine e alguns Design Patterns. Conforme vou estudando os patterns vou descobrindo e revendo conceitos e a melhor forma de aplicá-los, por isso resolvi dar uma revisada [...]]]></description>
			<content:encoded><![CDATA[<p>Olá pessoal, como vão? Bom, percebi que uma das fontes de visitas do meu site são os artigos onde defino uma <a href="http://fernandomantoan.com/category/frameworks/codeigniter/">arquitetura de <em>software</em> com CodeIgniter</a>, integrando Smarty, Doctrine e alguns <em>Design Patterns</em>. Conforme vou estudando os <em>patterns</em> vou descobrindo e revendo conceitos e a melhor forma de aplicá-los, por isso resolvi dar uma revisada nos artigos e redefinir algumas coisas da arquitetura, para deixá-la mais consistente e sem a aplicação errônea de conceitos de <em>pattern</em>. Só gostaria então de notificá-los que todos os artigos foram revisados e atualizados, com correções de erros de gramática e de conceitos equivocados. Portanto aproveitem <a href="http://fernandomantoan.com/category/frameworks/codeigniter/">os artigos</a>, esta arquitetura é muito útil para aplicações <em>web</em> de pequeno e médio porte. Estou reunindo todos estes artigos em um PDF e em breve disponibilizo aqui no site para <em>download</em>. Até a próxima.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/offtopic/revisao-dos-artigos-da-arquitetura-de-software-com-ci/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
