<?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 &#187; PHP</title>
	<atom:link href="http://fernandomantoan.com/category/php/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>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>Debug de Aplicações PHP com XDebug e Eclipse PDT</title>
		<link>http://fernandomantoan.com/php/debug-de-aplicacoes-php-com-xdebug-e-eclipse-pdt/</link>
		<comments>http://fernandomantoan.com/php/debug-de-aplicacoes-php-com-xdebug-e-eclipse-pdt/#comments</comments>
		<pubDate>Tue, 19 Jan 2010 00:03:12 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=353</guid>
		<description><![CDATA[Neste artigo é configurado um ambiente para debugging de aplicações PHP utilizando o XDebug e o Eclipse PDT.]]></description>
			<content:encoded><![CDATA[<p>No <a href="http://fernandomantoan.com/php/instalando-xdebug-no-ubuntu-9-10/">artigo anterior</a>, demonstrei passo a passo como instalar no Ubuntu 9.10 a extensão XDebug, utilizada no <em>debugging</em> e <em>profiling</em> de aplicações PHP. Neste artigo demonstro as configurações necessárias para integrar esta ferramenta com a IDE Eclipse PDT.</p>
<h2>Configurando o XDebug</h2>
<p>Antes de ir ao Eclipse, é necessário modificar algumas diretrizes de configuração do XDebug, para isto basta abrir o arquivo de configuração do PHP como root:</p>
<pre class="brush: bash;">sudo gedit /etc/php5/apache2/php.ini</pre>
<p>E na seção:</p>
<pre class="brush: plain;">[Zend]
zend_extension=&quot;/usr/lib/php5/20060613+lfs/xdebug.so&quot;</pre>
<p>Adicionar logo abaixo o seguinte conteúdo:</p>
<pre class="brush: plain;">[xdebug]
xdebug.remote_enable=On
xdebug.remote_host=&quot;localhost&quot;
xdebug.remote_port=9000</pre>
<p>Após fazer isso, basta verificar se o phpinfo() traz o seguinte resultado:</p>
<div id="attachment_355" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/phpinfo.png"><img class="size-medium wp-image-355" title="phpinfo()" src="http://fernandomantoan.com/wp-content/uploads/2010/01/phpinfo-300x137.png" alt="" width="300" height="137" /></a><p class="wp-caption-text">Resultado da função phpinfo()</p></div>
<p>Com isso o XDebug está devidamente configurado.</p>
<h2>Configurando o Eclipse</h2>
<p>A primeira coisa a se fazer no Eclipse é adicionar o executável do PHP. No menu <em>Window</em> -&gt; <em>Preferences</em> existe um menu lateral com o título PHP, ao expandí-lo aparecerá a opção PHP <em>Executables</em>, ao clicar nesta opção aparecerá a seguinte janela:</p>
<div id="attachment_360" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/php_executables.png"><img class="size-medium wp-image-360" title="php_executables" src="http://fernandomantoan.com/wp-content/uploads/2010/01/php_executables-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Janela de executáveis do PHP</p></div>
<p>Basta então clicar no botão <em>Add</em> e colocar um nome qualquer, informar o caminho do executável (por exemplo, /usr/bin/php) e escolher o tipo do <em>debugger</em>, que é <strong>XDebug</strong>. O próximo passo é configurar as informações do <em>debugger</em> no Eclipse, para isto basta ir em: PHP -&gt; <em>Debug</em> -&gt; <em>Installed Debuggers, </em>lá existirá uma entrada para o XDebug, basta verificar se a porta é a 9000, e caso não seja clicar em <em>Configure</em> e alterá-la. Após isto basta ir em PHP -&gt; <em>Debug</em> e modificar o PHP <em>Debugger</em> para o XDebug.</p>
<p>Após estas configurações o <em>Debugging</em> do Eclipse já deverá estar funcionando. Caso não esteja, é necessário verificar se o servidor padrão está apontando para a URL correta do <em>Web Server</em>, para isto basta ir em <em>Window</em> -&gt; <em>Preferences</em> -&gt; PHP -&gt; PHP <em>Servers</em> e editar as configurações do servidor padrão.</p>
<h2>Exemplo de <em>Debugging</em></h2>
<p>Agora a última etapa é fazer um teste para verificar se tudo está funcionando. Para isso basta criar um projeto PHP, e criar um arquivo chamado <strong>teste.php</strong>. Dentro deste arquivo é acrescentado o seguinte conteúdo:</p>
<pre class="brush: php;">&lt;?php
$teste = &quot;ola&quot;;
$muaha = array();
for ( $i = 0; $i &amp;lt; 3; $i++ ) {
	$muaha[] = $i;
}
array_shift($muaha);
echo &quot;fim&quot;;</pre>
<p>Ele é bastante simples, vai criar duas variáveis, fazer um laço para preencher o array, tirar o primeiro elemento do array e imprimir o texto <strong>fim</strong>. Para executar ele, basta clicar na pequena seta logo à direita do botão de <em>Debug</em>, como apresentado na imagem abaixo, e ir em <em>Debug as</em> -&gt; PHP <em>Web Page</em>.</p>
<div id="attachment_361" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_button.png"><img class="size-medium wp-image-361" title="debug_button" src="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_button-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Botão de Debug no Eclipse</p></div>
<p>Ele então avisará para abrir a perspectiva de <em>Debug</em>, basta confirmar clicando em <em>Yes</em> e a seguinte tela aparecerá:</p>
<div id="attachment_362" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_perspective.png"><img class="size-medium wp-image-362" title="debug_perspective" src="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_perspective-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Perspectiva de Debug</p></div>
<p>Pode-se notar que existe uma barra logo à esquerda da numeração das linhas, ao clicar nesta barra será adicionado um <em>breakpoint</em>, que é um ponto de parada na execução do <em>script</em>, o que permite verificar a situação do script até este ponto, como as variáveis alocadas, o conteúdo delas etc. A nível de teste, basta colocar 2 <em>breakpoints</em>, um na linha 4 e outro na linha 8. Após isto basta executar o <em>script</em>, clicando no botão com seta verde, localizado na aba <em>Debug</em>, ele é apresentado na imagem abaixo:</p>
<div id="attachment_363" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/seta_resume.png"><img class="size-medium wp-image-363" title="seta_resume" src="http://fernandomantoan.com/wp-content/uploads/2010/01/seta_resume-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Localização do botão para resumir a execução do script</p></div>
<p>Logo na primeira parada é possível verificar as variáveis, como o array vazio e a string devidamente preenchida, isto é apresentado na imagem abaixo:</p>
<div id="attachment_364" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_linha4.png"><img class="size-medium wp-image-364" title="debug_linha4" src="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_linha4-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Primeira execução do script</p></div>
<p>Ao clicar novamente no botão para resumir a execução do <em>script</em>, será feito um dos <em>loops</em> do <strong>for</strong> definido até que a condição especificada ($i &lt; 3) seja cumprida, ou seja, serão necessários 4 cliques no botão para sair do <strong>for</strong> <img src='http://fernandomantoan.com/wp-includes/images/smilies/icon_razz.gif' alt=':P' class='wp-smiley' /> . Neste laço é possível verificar que o array vai sendo preenchido, e após sair do <em>loop</em> e parar na linha 8 o array está com apenas 2 elementos devido à função <strong>array_shift</strong>. As imagens abaixo representam, respectivamente, o fim do <em>loop</em> e a parada na linha 8.</p>
<div id="attachment_367" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_array_full.png"><img class="size-medium wp-image-367" title="debug_array_full" src="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_array_full-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Fim do loop: Array com 3 elementos</p></div>
<p style="text-align: center;">
<div id="attachment_365" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_array_preenchida.png"><img class="size-medium wp-image-365 " title="debug_array_preenchida" src="http://fernandomantoan.com/wp-content/uploads/2010/01/debug_array_preenchida-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Parada na linha 8: Array com 2 elementos</p></div>
<p>E por último, é exibida a saída da página na tela, e a aba de variáveis é limpa, assim como apresentado na imagem abaixo:</p>
<div id="attachment_366" class="wp-caption aligncenter" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2010/01/fim_end.png"><img class="size-medium wp-image-366" title="fim_end" src="http://fernandomantoan.com/wp-content/uploads/2010/01/fim_end-300x175.png" alt="" width="300" height="175" /></a><p class="wp-caption-text">Fim do Debug</p></div>
<h2>Concluindo</h2>
<p>O XDebug é uma ferramenta bastante útil para programadores PHP, com ela é possível debugar cada trecho do código para garantir uma maior consistência a ele e (tentar) eliminar bugs. Além de <em>debug</em> ela também fornece a funcionalidade de <em>profiling</em>, que será abordada em um artigo futuro. Até a próxima.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/debug-de-aplicacoes-php-com-xdebug-e-eclipse-pdt/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Arquitetura de Software com CodeIgniter &#8211; Aplicação de Exemplo</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/#comments</comments>
		<pubDate>Sun, 20 Dec 2009 12:33:01 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[arquiteturas de software]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[doctrine]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[smarty]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=231</guid>
		<description><![CDATA[Olá a todos, como vão? Finalmente depois de algum tempo consegui implementar uma aplicação de exemplo utilizando a arquitetura de software proposta com o framework CodeIgniter. É essencial para você leitor, ter acompanhado os artigos anteriores onde a arquitetura é definida e explanada. Este artigo irá guiá-los no desenvolvimento desta aplicação. Aproveitem! A Aplicação A [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos, como vão? Finalmente depois de algum tempo consegui implementar uma aplicação de exemplo utilizando a arquitetura de <em>software</em> proposta com o <em>framework</em> CodeIgniter. É essencial para você leitor, ter acompanhado os <a href="http://fernandomantoan.com/category/frameworks/codeigniter/">artigos anteriores</a> onde a arquitetura é definida e explanada. Este artigo irá guiá-los no desenvolvimento desta aplicação. Aproveitem!</p>
<h2>A Aplicação</h2>
<p>A aplicação desenvolvida é uma <strong>lista de afazeres</strong> (<em>todo list</em>), altamente simples, porém tendo ela como base é possível desenvolver futuras aplicações, principalmente por ela possuir muitas das funcionalidades que os sistemas reais possuem. O banco de dados definido para a aplicação é mostrado abaixo.</p>
<pre class="brush: sql;">
CREATE DATABASE todo_ci;
USE todo_ci;
CREATE TABLE tasks(
	id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
	title VARCHAR(255) NOT NULL,
	completed BOOLEAN DEFAULT FALSE
)ENGINE=InnoDB;
</pre>
<p>O banco consiste apenas de uma tabela para armazenar as tarefas, contendo o título da tarefa e se ela foi completada (TRUE) ou não (FALSE). Em um sistema de controle de tarefas um pouco mais completo também existiria uma tabela de usuários, mas foge um pouco do escopo desta aplicação. Para configurar o acesso ao banco na arquitetura, é necessário modificar o arquivo <strong>database.php</strong> localizado em <strong>application/config</strong>, alterando os atributos: <strong>hostname</strong>, <strong>username</strong>, <strong>password</strong>, <strong>database</strong>. Como no seguinte trecho:</p>
<pre class="brush: php;">$db['default']['hostname'] = &quot;localhost&quot;;
$db['default']['username'] = &quot;root&quot;;
$db['default']['password'] = &quot;&quot;;
$db['default']['database'] = &quot;todo_ci&quot;;</pre>
<p>Outra coisa a se fazer é configurar no arquivo <strong>autoload.php</strong> dentro de <strong>application/config</strong> o carregamento automático dos <em>helpers</em> e bibliotecas utilizadas. Para fazer isso basta alterar as linhas:</p>
<pre class="brush: php;">$autoload['libraries'] = array();
$autoload['helper'] = array();</pre>
<p>para</p>
<pre class="brush: php;">$autoload['libraries'] = array('form_validation', 'session');
$autoload['helper'] = array('url');</pre>
<h2>Negócio</h2>
<p>Como a arquitetura está bem definida com camadas lógicas para negócio e apresentação, pode-se facilmente separar as duas dividindo o desenvolvimento em duas etapas. Na parte de negócio é necessário fazer toda codificação referente a <em><strong>Facade</strong></em>, <strong>DAO</strong> e <em><strong>Model</strong></em>.</p>
<h3>Camadas referentes ao banco de dados</h3>
<p>As camadas <strong><em>Model</em> </strong>e <strong>DAO</strong>, são as referentes ao banco de dados. O <em><strong>Model</strong></em> vai ser a representação de uma entidade do banco de dados como um objeto da aplicação e o <em><strong>Data Access Object</strong></em> (DAO) será o objeto que possuirá operações com o banco, como, por exemplo, operações de salvar e obter registros. Para gerar o <em>Model</em> diretamente pelo Doctrine, tendo o arquivo de configuração apresentado acima devidamente configurado, é necessário gerar o arquivo <strong>schema.yml</strong>, dentro da pasta <strong>application/schema</strong>, que define os atributos das entidades do banco, ele possui o seguinte conteúdo:</p>
<pre class="brush: plain;">Tasks:
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(10)
    title:
      type: string(255)
    completed:
      type: boolean</pre>
<p>Então, para gerar a classe basta ir a um terminal, e estando na pasta <strong>system/application</strong> executar o seguinte comando:</p>
<pre class="brush: bash;">$ php doctrine generate-models-yaml</pre>
<p>Ele então gerará os arquivos <strong>Tasks.php</strong> e <strong>BaseTasks.php</strong>, contidos, respectivamente, em: <strong>application/models</strong> e <strong>application/models/generated</strong>. Estes arquivos possuem os seguintes conteúdos:</p>
<pre class="brush: php;">
abstract class BaseTasks extends Doctrine_Record
{
	public function setTableDefinition()
	{
		$this-&gt;setTableName('tasks');
		$this-&gt;hasColumn('id', 'integer', 10, array('primary' =&gt; true, 'autoincrement' =&gt; true, 'type' =&gt; 'integer', 'length' =&gt; '10'));
		$this-&gt;hasColumn('title', 'string', 255, array('type' =&gt; 'string', 'length' =&gt; '255'));
		$this-&gt;hasColumn('completed', 'boolean', null, array('type' =&gt; 'boolean'));
	}
}
</pre>
<pre class="brush: php;">class Tasks extends BaseTasks
{
}</pre>
<p>Com isso o <em><strong>Model</strong></em> está gerado, porém ainda falta o arquivo <strong>DAO</strong>, basta criar então um arquivo chamado <strong>TasksDAO.php</strong> na pasta <strong>application/models</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">&lt;?php
class TasksDAO
{
}</pre>
<p>Bom, após ter tudo gerado é necessário criar os métodos referentes as operações básicas com o banco de dados, que são: <em><strong>Create</strong></em>, <em><strong>Retrieve</strong></em>, <em><strong>Update</strong></em> e <em><strong>Delete</strong></em>, ou o tão famoso CRUD. Todas estas operações estarão localizadas na classe <strong>TasksDAO</strong>. A operação para se criar uma nova tarefa ou atualizá-la é apresentada no código abaixo:</p>
<pre class="brush: php;">
public function save($data)
{
	if ( !isset($data['id']) || !$tasks = $this-&gt;fetch($data['id']) ) {
		$tasks = new Tasks();
	}
	$tasks-&gt;merge($data);
	$tasks-&gt;save();
}
</pre>
<p>Apesar do <em>Model</em> a nível de código possuir somente os atributos que o banco de dados possui, graças a ele extender da classe do Doctrine é possível se aproveitar de todos os métodos do <em>framework</em>, o que transforma o <em>Model</em> em um <em>Active Record</em>, possibilitando utilizar diretamente dele o método <strong>save</strong>. Se um id for passado, é feita uma verificação se este id existe e então, caso exista, a operação será uma atualização de um registro já populado. A parte referente ao procedimento de exclusão de um registro é o apresentado abaixo:</p>
<pre class="brush: php;">
public function delete($id)
{
	$tasks = $this-&gt;fetch($id);
	if ( $tasks ) {
		return $tasks-&gt;delete();
	}
	return false;
}
</pre>
<p>O método irá procurar por uma tarefa com o id passado e, caso encontre-a, irá excluí-la. O procedimento para se obter todas as tarefas é:</p>
<pre class="brush: php;">
public function fetchAll()
{
	$query = new Doctrine_Query();
	$query-&gt;from('Tasks t');
	$query-&gt;orderby('t.id DESC');
	return $query-&gt;execute();
}
</pre>
<p>A partir de uma Doctrine <em>Query</em> ele irá procurar todas as tarefas existentes no banco de dados e retorná-las para as camadas superiores. E, por fim, o procedimento para se obter uma determinada tarefa é:</p>
<pre class="brush: php;">
public function fetch($id)
{
	$task = Doctrine::getTable('Tasks')-&gt;find($id);
	if ( $task ) {
		return $task;
	}
	return false;
}
</pre>
<p>Ele irá obter uma tarefa baseado no <strong>id</strong> passado para o método e irá retorná-la. Com isso a camada de banco de dados está pronta.</p>
<h3>Regra de Negócio</h3>
<p>A regra de negócio da aplicação ficará na camada <em><strong>Facade</strong></em>, como explicado anteriormente. Ela conterá métodos que o <em><strong>Controller</strong></em> irá chamar. No caso desta aplicação de exemplo estes procedimentos são simplesmente os referentes a um CRUD, mas em uma aplicação real, regras como, por exemplo, de cálculo de juros, ou de fechamento de um pedido, ficariam nesta camada. Na <em>Facade</em> também será feita toda a validação dos dados vindos do formulário. A <em>Facade</em> criada é um arquivo chamado <strong>tasks_facade.php</strong> e está localizada na pasta <strong>application/facades</strong>, ele possui o seguinte conteúdo:</p>
<pre class="brush: php;">
&lt;?php
class TasksFacade extends Facade
{
	public function index()
	{
		$dao = new TasksDAO();
		$tasks = $dao-&gt;fetchAll();
		return $tasks;
	}
	public function save()
	{
		$this-&gt;form_validation-&gt;set_rules('title', 'Title', 'required|max_length[255]|htmlspecialchars');

		if ( $this-&gt;form_validation-&gt;run() == FALSE ) {
			return false;
		} else {
			$array_data = array();
			$array_data['title'] = $this-&gt;form_validation-&gt;set_value('title');
			$dao = new TasksDAO();
			$dao-&gt;save($array_data);
			return true;
		}
	}
	public function update()
	{
		$this-&gt;form_validation-&gt;set_rules('id', 'Código', 'required');
		$this-&gt;form_validation-&gt;set_rules('title', 'Título', 'required|max_length[255]|htmlspecialchars');

		if ( $this-&gt;form_validation-&gt;run() == FALSE ) {
			return false;
		} else {
			$array_data = array();
			$array_data['id'] = $this-&gt;form_validation-&gt;set_value('id');
			$array_data['title'] = $this-&gt;form_validation-&gt;set_value('title');
			$array_data['completed'] = ( isset($_POST['completed']) ) ? true : false;
			$dao = new TasksDAO();
			$dao-&gt;save($array_data);
			return true;
		}
	}
	public function get($id)
	{
		$dao = new TasksDAO();
		return $dao-&gt;fetch($id);
	}
	public function delete($id)
	{
		$dao = new TasksDAO();
		$dao-&gt;delete($id);
		return true;
	}
}
</pre>
<p>O primeiro método será acessado para fornecer todas as tarefas existentes no banco de dados, ele simplesmente chama a DAO para obter estes dados e retorna para a camada de mais alto nível. Os métodos <strong>save</strong> e <strong>update</strong>, serão referentes à inserção de um novo registro e à alteração de um registro já existente; onde eles irão validar os dados enviados pelo formulário e, caso tudo esteja corretamente preenchido, irão chamar a DAO para persistir estes dados em banco. O método <strong>get</strong> irá chamar a DAO para obter a tarefa em questão, passando-a para a camada de cima. O último método, o <strong>delete</strong> simplesmente irá excluir a tarefa.</p>
<p>Esta é toda a parte referente a negócio da aplicação, agora a última coisa a se fazer é implementar a camada de mais alto nível.</p>
<h3>Camada de mais alto nível</h3>
<p>Esta camada é composta pelo <em><strong>Controller</strong></em> e pela <em><strong>View</strong></em>, onde o primeiro é relacionado ao controle de fluxo da aplicação e o segundo à apresentação com o usuário. Primeiramente é necessário criar o controller para as tarefas, o nome do arquivo é <strong>tasks_controller.php</strong> localizado em <strong>application/controllers</strong>, ele deverá extender da classe <strong>Controller</strong> padrão do CodeIgniter, como demonstrado asseguir:</p>
<pre class="brush: php;">&lt;?php
class TasksController extends Controller
{
	public function TasksController()
	{
		parent::Controller();
		$this-&gt;load-&gt;library('smartyview');
		$this-&gt;load-&gt;facade('tasks_facade');
	}
}</pre>
<p>Este código declara a classe do <em>Controller</em> em questão e seu construtor já irá carregar a <em>Facade</em> utilizada para processar as regras de negócio. O primeiro método a ser implementado é o referente a listagem das tarefas, ele é demonstrado abaixo:</p>
<pre class="brush: php;">
public function index()
{
	if ( $this-&gt;session-&gt;flashdata('success') ) {
		$this-&gt;smartyview-&gt;assign('message', $this-&gt;session-&gt;flashdata('success'));
	}
	$tasks = $this-&gt;tasksfacade-&gt;index();
	$this-&gt;smartyview-&gt;assign_by_ref('tasks', $tasks);
	$this-&gt;smartyview-&gt;display('tasks/index.tpl');
}
</pre>
<p>Primeiramente ele verifica se existe alguma mensagem para exibir ao usuário, caso existe ele passa esta mensagem para a <em>View.</em> Posteriormente, ele irá chamar a camada <em>Facade</em> para obter os dados das tarefas e, então passará estas tarefas para a <em>View.</em> Agora que o <em>Controller</em> já está criado, junto com seu método index, é interessante configurar o CodeIgniter para que este <em>Controller</em> seja o principal da aplicação, para isso basta localizar a seguinte linha dentro de <strong>application/config/routes.php</strong>:</p>
<pre class="brush: php;">$route['default_controller'] = &quot;welcome&quot;;</pre>
<p>e mudá-la para:</p>
<pre class="brush: php;">$route['default_controller'] = &quot;tasks&quot;;</pre>
<p>Ao acessar a raíz do projeto ele então já chamará a ação <strong>index</strong> do Controller <strong>tasks</strong>. Agora é necessário desenvolver o <strong>layout</strong> da aplicação, dentro da pasta <strong>views</strong> é necessário criar a pasta <strong>geral</strong>, e criar os arquivos <strong>header.tpl</strong> e <strong>footer.tpl</strong> eles serão o cabeçalho e o rodapé da aplicação. O arquivo <strong>header.tpl</strong> possui o seguinte código:</p>
<pre class="brush: xml;">
&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; ?&gt;
&lt;!DOCTYPE html PUBLIC &quot;-//W3C//DTD XHTML 1.0 Strict//EN&quot; &quot;http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd&quot;&gt;
&lt;html xmlns=&quot;http://www.w3.org/1999/xhtml&quot;&gt;
	&lt;head&gt;
		&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=UTF-8&quot; /&gt;
		&lt;title&gt;Afazeres - Arquitetura CodeIgniter&lt;/title&gt;
		&lt;link rel=&quot;stylesheet&quot; type=&quot;text/css&quot; href=&quot;{php}echo base_url(){/php}css/style.css&quot; /&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;div id=&quot;wrapper&quot;&gt;
			&lt;div id=&quot;header&quot;&gt;
				&lt;h1&gt;Lista de Afazeres&lt;/h1&gt;
			&lt;/div&gt;
			&lt;div id=&quot;content&quot;&gt;
</pre>
<p>E o <strong>footer.tpl</strong>:</p>
<pre class="brush: xml;">
			&lt;/div&gt;
			&lt;div id=&quot;footer&quot;&gt;
				&lt;p&gt;Fernando Mantoan.&lt;/p&gt;
			&lt;/div&gt;
		&lt;/div&gt;
	&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Com o layout já definido, é hora de criar as <em>Views</em> referentes ao <em>Controller</em> <strong>tasks</strong>, estas <em>Views</em> deverão estar dentro da pasta <strong>application/views/tasks</strong>, o primeiro arquivo criado é referente a listagem das tarefas, ele é o arquivo <strong>index.tpl</strong> e possui o seguinte conteúdo:</p>
<pre class="brush: xml;">
{include file=&quot;geral/header.tpl&quot;}
{if $message}
&lt;p class=&quot;success&quot;&gt;{$message}&lt;/p&gt;
{/if}
&lt;p&gt;
	{php}
		echo anchor('tasks/add', 'Nova Tarefa');
	{/php}
&lt;/p&gt;
&lt;table&gt;
	&lt;thead&gt;
		&lt;tr&gt;
			&lt;th scope=&quot;col&quot;&gt;T&amp;iacute;tulo&lt;/th&gt;
			&lt;th scope=&quot;col&quot;&gt;Tarefa Completada?&lt;/th&gt;
			&lt;th scope=&quot;col&quot; colspan=&quot;2&quot;&gt;&lt;/th&gt;
		&lt;/tr&gt;
	&lt;/thead&gt;
	&lt;tbody&gt;
		{foreach from=$tasks item=task}
		&lt;tr&gt;
			&lt;td class=&quot;title&quot;&gt;{$task.title}&lt;/td&gt;
			&lt;td&gt;{if $task.completed}Completada{else}N&amp;atilde;o Completada{/if}&lt;/td&gt;
			&lt;td class=&quot;actions center&quot;&gt;
				{php}$task = $this-&gt;get_template_vars('task');{/php}
				{php}echo anchor('tasks/edit/' . $task-&gt;id, 'Editar');{/php}
				{php}echo anchor('tasks/delete/' . $task-&gt;id, 'Excluir', 'onclick=&quot;return window.confirm(\'Deseja excluir esta tarefa?\');&quot;');{/php}
			&lt;/td&gt;
		&lt;/tr&gt;
		{/foreach}
	&lt;/tbody&gt;
&lt;/table&gt;
{include file=&quot;geral/footer.tpl&quot;}
</pre>
<p>Para utilizar algumas das funções nativas do CodeIgniter, foi necessário utilizar a tag <strong>{php}</strong> do Smarty, que deixa para o PHP executar o código definido entre os delimitadores. Quem for levar mais para frente a arquitetura poderá integrar estas funções com o Smarty para utilizá-las como <em>Helpers</em> e não ter a necessidade de utilizar as funções como código PHP. Agora que a listagem está funcionando é hora de fazer o cadastro de novas tarefas, para isso é adicionado o seguinte método à classe <strong>TasksController</strong>:</p>
<pre class="brush: php;">
public function add()
{
	if ( !$this-&gt;tasksfacade-&gt;save() ) {
		$this-&gt;smartyview-&gt;display('tasks/add.tpl');
	} else {
		$this-&gt;session-&gt;set_flashdata('success', 'Tarefa cadastrada!');
		redirect('tasks/index');
	}
}
</pre>
<p>Ele simplesmente verificará se foi possível salvar um novo registro, caso não exibe o formulário de cadastro, e caso a tarefa tenha sido cadastrada redireciona para a listagem de tarefas passando também uma mensagem de sucess. A <em>View</em> referente a este método é o arquivo <strong>add.tpl</strong> apresentado abaixo:</p>
<pre class="brush: xml;">
{include file=&quot;geral/header.tpl&quot;}
&lt;h2&gt;Nova Tarefa&lt;/h2&gt;
{php}echo validation_errors('&lt;p class=&quot;error&quot;&gt;', '&lt;/p&gt;'){/php}
{php}echo form_open('tasks/add'){/php}
&lt;div&gt;
	&lt;label for=&quot;title&quot;&gt;T&amp;iacute;tulo:&lt;/label&gt;
	&lt;br /&gt;
	&lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;{php}set_value('title'){/php}&quot; /&gt;
&lt;/div&gt;
&lt;div&gt;&lt;input type=&quot;submit&quot; value=&quot;Salvar&quot; /&gt;&lt;/div&gt;
{php}echo form_close(){/php}
{include file=&quot;geral/footer.tpl&quot;}
</pre>
<p>Novamente é necessária a utilização da tag <strong>{php}</strong> do Smarty, para aproveitar ao máximo os <em>Helpers</em> do CodeIgniter. Esta tela exibirá erros, caso ocorram, e também, o formulário para cadastro de uma nova tarefa. O próximo método a ser implementado é o de atualização de tarefas, ele é apresentado a seguir:</p>
<pre class="brush: php;">
public function edit($id = null)
{
	if ( is_null($id) || !$task = $this-&gt;tasksfacade-&gt;get($id) ) {
		redirect('tasks/index');
	}
	if ( !$this-&gt;tasksfacade-&gt;update() ) {
		$this-&gt;smartyview-&gt;assign_by_ref('task', $task);
		$this-&gt;smartyview-&gt;display('tasks/edit.tpl');
	} else {
		$this-&gt;session-&gt;set_flashdata('success', 'Tarefa atualizada!');
		redirect('tasks/index');
	}
}
</pre>
<p>Ele basicamente verificará se um id foi ou não passado, e se foi informado um id existente no banco de dados, caso estes requisistos sejam atendidos ele irá mostrar pro usuário o formulário de alteração ou uma mensagem de sucesso na alteração. O formulário de alteração (arquivo <strong>edit.tpl</strong>) é exibido abaixo:</p>
<pre class="brush: xml;">
{include file=&quot;geral/header.tpl&quot;}
&lt;h2&gt;Editar Tarefa&lt;/h2&gt;
{php}echo validation_errors('&lt;p class=&quot;error&quot;&gt;', '&lt;/p&gt;'){/php}
{php}echo form_open('tasks/edit/' . basename($_SERVER['PHP_SELF'])){/php}
&lt;div&gt;
&lt;input type=&quot;hidden&quot; name=&quot;id&quot; value=&quot;{$task.id}&quot; /&gt;
	&lt;label for=&quot;title&quot;&gt;T&amp;iacute;tulo:&lt;/label&gt;
	&lt;br /&gt;
	&lt;input type=&quot;text&quot; name=&quot;title&quot; value=&quot;{$task.title}&quot; /&gt;
	&lt;br /&gt;
	&lt;label&gt;Completada? &lt;input type=&quot;checkbox&quot; {if $task.completed}checked=&quot;checked&quot;{/if} name=&quot;completed&quot; value=&quot;1&quot; /&gt;
&lt;/div&gt;
&lt;div&gt;&lt;input type=&quot;submit&quot; value=&quot;Salvar&quot; /&gt;&lt;/div&gt;
{php}echo form_close(){/php}
{include file=&quot;geral/footer.tpl&quot;}
</pre>
<p>Novamente para utilizar ao máximo os <em>Helpers</em> do CodeIgniter foram necessários alguns <em>workarounds</em>, este formulário segue a mesma idéia do formulário de cadastro, a diferença é que a URL dele precisa do id da tarefa, assim como um <strong>input</strong> hidden com este id no formulário, e ele apresenta um <em>checkbox</em> para o usuário informar se a tarefa já foi completada ou não. O último método do <em>Controller</em> necessário para esta aplicação é o referente a exclusão de registros. Este método é apresentado abaixo:</p>
<pre class="brush: php;">
public function delete($id = null)
{
	if ( is_null($id) ) {
		redirect('tasks/index');
	} else {
		$this-&gt;tasksfacade-&gt;delete($id);
		$this-&gt;session-&gt;set_flashdata('success', 'Tarefa excluída!');
		redirect('tasks/index');
	}
}
</pre>
<p>Neste caso não é necessário apresentar nenhuma <em>View</em>. A última coisa a se fazer para esta aplicação é definir alguns estilos CSS, para isto foi criada uma folha de estilos simples para tornar a aplicação um pouco mais bonita, esta folha de estilos deve ser armazenada na raíz do projeto em uma pasta com o nome de <strong>css</strong>, como, por exemplo em <strong>ci_todo/css</strong>, e o arquivo desta folha de estilos é <strong>style.css</strong>:</p>
<pre class="brush: css;">
BODY {
	font-family: Arial, Verdana, Helvetica, sans-serif;
}
A {
	color: #000;
	font-weight: bold;
}
DIV#wrapper {
	left: 50%;
	margin-left: -300px;
	position: relative;
	width: 600px;
}
DIV#header {
	margin: 20px 0 40px 0;
}
DIV#header H1 {
	color: #f60;
	font-size: 32px;
	letter-spacing: -2px;
	margin: 0;
}
DIV#content {
	font-size: 12px;
}
DIV#content TABLE {
	border-collapse: collapse;
	width: 100%;
}
DIV#content TABLE THEAD TR TH, DIV#content TABLE TBODY TR TD {
	text-align: left;
	padding: 9px;
}
DIV#content TABLE THEAD TR TH {
	background: #eee;
}
DIV#content TABLE TR TD.title {
	width: 40%;
}
DIV#content TABLE TR TD.actions {
	width: 18%;
}
DIV#content FORM LABEL {
	cursor: pointer;
}
DIV#content FORM INPUT[type=&quot;text&quot;] {
	background: #f6f6f6;
	border: 1px #eee solid;
	font-size: 12px;
	margin-top: 10px;
	padding: 3px;
	width: 99%;
}
DIV#content FORM INPUT[type=&quot;submit&quot;] {
	background: #f60;
	border: none;
	color: #fff;
	margin-top: 20px;
	padding: 4px;
}
UL, LI {
	margin: 0;
}
P.error, .errorExplanation LI {
	background-color: #603131;
	border: 1px solid #5c2d2d;
	color: #fff;
	font-weight: bold;
	padding: 10px;
	margin: 0 0 15px 0;
}
P.success {
	background-color: #317b17;
	border: 1px solid #317b17c;
	color: #fff;
	font-weight: bold;
	padding: 10px;
	margin-bottom: 15px;
}
DIV#footer {
	font-size: 9px;
	font-weight: bold;
	margin-top: 80px;
}
.center {
	text-align: center !important;
}
</pre>
<p>Algumas <em>screenshots</em> deste sistema são apresentadas abaixo:</p>

<a href='http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/attachment/afazeres-arquitetura-codeigniter/' title='Listagem de Dados'><img width="150" height="150" src="http://fernandomantoan.com/wp-content/uploads/2009/12/Afazeres-Arquitetura-CodeIgniter-150x150.png" class="attachment-thumbnail" alt="Listagem de Dados" title="Listagem de Dados" /></a>
<a href='http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/attachment/afazeres-arquitetura-codeigniter-add/' title='Validação do Formulário'><img width="150" height="150" src="http://fernandomantoan.com/wp-content/uploads/2009/12/Afazeres-Arquitetura-CodeIgniter-Add-150x150.png" class="attachment-thumbnail" alt="Validação do Formulário" title="Validação do Formulário" /></a>
<a href='http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/attachment/afazeres-arquitetura-codeigniter-deleted/' title='Exclusão de Tarefa'><img width="150" height="150" src="http://fernandomantoan.com/wp-content/uploads/2009/12/Afazeres-Arquitetura-CodeIgniter-deleted-150x150.png" class="attachment-thumbnail" alt="Exclusão de Tarefa" title="Exclusão de Tarefa" /></a>

<h3>Fim</h3>
<p>Bom, assim concluo toda esta série de artigos referentes a uma <strong>Arquitetura de Desenvolvimento de Aplicações com o CodeIgniter</strong>, eu sinceramente achava esta solução muito boa na época que a criei, porém após terminar a arquitetura proposta no meu trabalho de conclusão de curso eu fiquei muito mais animado com o <strong>Zend Framework</strong> e este artigo é o último referente a esta arquitetura com CI, o que pode acontecer é de haver <strong>atualizações</strong> dos artigos sobre esta arquitetura para melhorar o entendimento e revisar os conceitos apresentados caso necessário. Como já havia dito antes, para quem procura uma solução simples e rápida esta arquitetura com o CI pode ser aplicável, mas <strong>existem diversas melhorias</strong> a serem feitas, seu uso pode então depender muito da disponibilidade de melhorá-la e do gosto por este <em>framework</em>. Bom, por hoje é só, até mais!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-aplicacao-de-exemplo/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Trabalho de Conclusão de Curso: Proposta de Arquitetura para Desenvolvimento Web Baseada em PHP utilizando Design Patterns, Um Estudo de Caso</title>
		<link>http://fernandomantoan.com/php/trabalho-de-conclusao-de-curso-proposta-de-arquitetura-para-desenvolvimento-web-baseada-em-php-utilizando-design-patterns-um-estudo-de-caso/</link>
		<comments>http://fernandomantoan.com/php/trabalho-de-conclusao-de-curso-proposta-de-arquitetura-para-desenvolvimento-web-baseada-em-php-utilizando-design-patterns-um-estudo-de-caso/#comments</comments>
		<pubDate>Tue, 15 Dec 2009 18:51:09 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[arquiteturas de software]]></category>
		<category><![CDATA[cesufoz]]></category>
		<category><![CDATA[design patterns]]></category>
		<category><![CDATA[Frameworks]]></category>
		<category><![CDATA[monografia]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=222</guid>
		<description><![CDATA[Olá a todos, como vão? Algum tempo parado com o blog, apesar de ter dito que agora eu teria mais tempo para me dedicar a ele, não é o que está acontecendo . Bom hoje trago para vocês o meu tema de trabalho de conclusão de curso, com o qual conclui minha graduação no Centro [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos, como vão? Algum tempo parado com o blog, apesar de ter dito que agora eu teria mais tempo para me dedicar a ele, não é o que está acontecendo <img src='http://fernandomantoan.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> . Bom hoje trago para vocês o meu tema de trabalho de conclusão de curso, com o qual conclui minha graduação no <strong>Centro de Ensino Superior de Foz do Iguaçu</strong>, me tornando <strong>Bacharel em Ciência da Computação</strong>. Na segunda-feira dia 7 de Dezembro de 2009, apresentei a banca final, defendendo o tema, explanando toda a parte prática (a parte teórica foi apresentada na banca parcial) e ganhando a aprovação dos avaliadores da banca.</p>
<h2>Objetivo Geral</h2>
<p>Propor uma arquitetura de desenvolvimento de aplicações em PHP contendo <em>design patterns</em> que forneça uma maior estrutura organizacional, padronização de programação, facilidade de manutenção, menos repetição de código e que evite <em>bad smell</em> (algo errado no código que necessita ser refatorado).</p>
<h2>Arquitetura Definida</h2>
<p style="text-align: center;">
<div id="attachment_223" class="wp-caption aligncenter" style="width: 409px"><a href="http://fernandomantoan.com/wp-content/uploads/2009/12/implementacao_diagrama_arquitetura.png" class="thickbox"><img class="size-full wp-image-223 " title="implementacao_diagrama_arquitetura" src="http://fernandomantoan.com/wp-content/uploads/2009/12/implementacao_diagrama_arquitetura.png" alt="Diagrama da arquitetura definida" width="399" height="336" /></a><p class="wp-caption-text">Diagrama da arquitetura definida</p></div>
<p>O fluxo definido por esta arquitetura segue o padrão definido pelo Zend <em>Framework</em> e, também, possui algumas customizações para a comunicação entre cada camada. A estrutura base do <em>framework</em> é baseada no <em>pattern</em> <em>Model-View-Controller</em> (MVC), o que divide a aplicação em <em>Model</em>, <em>View</em> e <em>Controller</em>. Na arquitetura, conforme apresentado na Figura acima ainda existem as camadas: <em>Facade</em>, <em>Data Mapper</em> e <em>Table Data Gateway</em>.</p>
<p>Todo o fluxo inicia-se por uma requisição feita por um usuário, o <em>framework</em> definirá qual o <em>Controller</em> requerido, este então será responsável por tratar a requisição e, utilizando o <em>pattern</em> <em>Factory Method</em>, o <em>Controller</em> obtém a <em>Facade</em> ligada ao caso de uso a que ele corresponde e então delega para esta camada o processamento da lógica referente a regra de negócio.</p>
<p>A <em>Facade</em> poderá utilizar um <em>Data Mapper</em> para obter dados do banco de dados, ou para fazer operações a registros do banco. O <em>Data Mapper</em> irá utilizar o <em>Table Data Gateway</em> para efetuar as operações SQL, que é a linguagem compreendida pelo banco de dados. Ele também poderá mapear os dados vindos do <em>Table Data Gateway</em> para objetos <em>Model</em>, que representam em forma de objetos as entidades do banco de dados.</p>
<p>Existe ainda a implementação do <em>Observer</em> e <em>Observable</em>, que fazem parte do <em>design pattern</em> <em>Observer</em>. Uma classe <em>Observable</em> possuirá métodos para se conectar a <em>Observers</em> e para notificar cada um deles. A classe <em>Observer</em> irá fazer um <em>log</em> das operações notificadas pela <em>Observable</em>, gravando este <em>log</em> em banco de dados, no formato JSON, para permitir uma consulta posterior.</p>
<p>Após todo o processamento das camadas inferiores ser concluído, o <em>Controller</em> irá continuar o fluxo da aplicação, exibindo a <em>View</em> para o usuário, que pode conter os dados pegos pelo <em>Data Mapper</em>, ou os formulários definidos pelos componentes Zend_Form para obter dados para algum registro, ou mensagens relevantes para informar ao usuário.</p>
<p>O <em>design pattern</em> <em>Singleton</em> é implementado por diversos componentes do Zend <em>Framework</em>, como, por exemplo, o Zend_Auth que é utilizado na autenticação de usuários. Com este <em>pattern</em> é possível manter os objetos durante a aplicação e por apenas um ponto de entrada. Isto garante a consistência deste objeto, sabendo sempre o que esperar dele.</p>
<h2>Aplicação de Exemplo</h2>
<p>Para fazer o estudo de caso foi necessário a elaboração de uma aplicação, esta sendo um sistema simples de controle de bibliotecas. Como não era necessário especificar um cliente real, foram criadas algumas regras de negócio que o sistema devia atender e então construí todo o sistema utilizando a arquitetura. A observação que deixo para quem for analisar a aplicação é que <strong>a regra de negócio é sim extremamente simples</strong>, e acredito que se fosse aplicar a aplicação a uma biblioteca real existiria muita coisa a se trabalhar, porém com ela foi possível demonstrar o uso da arquitetura e o resultado foi bem satisfatório. Os casos de uso criados são demonstrados no diagrama de casos de uso apresentado na Figura abaixo:</p>
<div id="attachment_224" class="wp-caption aligncenter" style="width: 310px"><a href="http://fernandomantoan.com/wp-content/uploads/2009/12/implementacao_casos_uso.png"  class="thickbox"><img class="size-medium wp-image-224" title="implementacao_casos_uso" src="http://fernandomantoan.com/wp-content/uploads/2009/12/implementacao_casos_uso-300x215.png" alt="Diagrama de Casos de Uso" width="300" height="215" /></a><p class="wp-caption-text">Diagrama de Casos de Uso</p></div>
<h2>Conclusões</h2>
<p>A principal conclusão apresentada na minha monografia é com relação a manutenibilidade dos sistemas e ciclo de vida. Com uma arquitetura padronizada e altamente reutilizável graças a um ótimo <em>framework</em> e a utilização de <em>design patterns</em> pode-se aumentar bastante o ciclo de vida, principalmente porque desenvolvedores que forem alterar as aplicações já prontas, deverão apenas se familiarizar com os <em>patterns</em> já especificados e reconhecidos mundialmente, e, também, ler a documentação da arquitetura, para saberem onde exatamente alterar as partes necessárias. Os trabalhos futuros são:</p>
<ul>
<li>Tornar a arquitetura independente de <em>framework</em>;</li>
<li>Basear a arquitetura em <em>plugins</em> para facilitar a criação e atualização de funcionalidades de sistemas;</li>
<li>Escolher entre os <em>design patterns</em> existentes para adicionar ou remover <em>patterns</em> de acordo com a necessidade das aplicações que forem desenvolvidas.</li>
</ul>
<h2>Código-Fonte</h2>
<p>O código-fonte com a arquitetura e a aplicação de exemplo poderão ser baixados no link abaixo. Se você tiver melhorias e dicas por favor envie um comentário que ficarei bem agradecido, principalmente se forem coisas construtivas. Bom, é isso, gostaria só de anunciar as boas novas e, também, divulgar esta arquitetura, que ao meu ver ficou muito boa para se trabalhar, e que já estou utilizando em um sistema real&#8230; <img src='http://fernandomantoan.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p><a href="http://fernandomantoan.com/wp-content/uploads/2009/12/monografia_biblioteca.zip">Código-Fonte da Arquitetura</a></p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/trabalho-de-conclusao-de-curso-proposta-de-arquitetura-para-desenvolvimento-web-baseada-em-php-utilizando-design-patterns-um-estudo-de-caso/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Instalando XDebug no Ubuntu 9.10</title>
		<link>http://fernandomantoan.com/php/instalando-xdebug-no-ubuntu-9-10/</link>
		<comments>http://fernandomantoan.com/php/instalando-xdebug-no-ubuntu-9-10/#comments</comments>
		<pubDate>Fri, 27 Nov 2009 16:06:22 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[Ubuntu]]></category>
		<category><![CDATA[pear]]></category>
		<category><![CDATA[pecl]]></category>
		<category><![CDATA[xdebug]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=197</guid>
		<description><![CDATA[Olá a todos! Hoje demonstrarei os passos necessários para se instalar a ferramenta de debug e profiling para PHP chamada XDebug. Esta ferramenta é relativamente nova para mim, e pode ser uma grande aliada para garantir a performance e qualidade de seu código. O primeiro passo é instalar os pacotes necessários para poder instalar o [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos! Hoje demonstrarei os passos necessários para se instalar a ferramenta de <em>debug</em> e <em>profiling</em> para PHP chamada <strong>XDebug</strong>. Esta ferramenta é relativamente nova para mim, e pode ser uma grande aliada para garantir a <em>performance</em> e qualidade de seu código.</p>
<p>O primeiro passo é instalar os pacotes necessários para poder instalar o XDebug a partir do repositório de extensões PHP:</p>
<pre class="brush: bash;">sudo apt-get install php5-dev php-pear</pre>
<p>Com o PECL pode-se instalar novos pacotes no estilo do apt-get, utilizado para instalar pacotes no sistema operacional. Neste repositório é possível instalar o XDebug, para isso basta o seguinte comando:</p>
<pre class="brush: bash;">sudo pecl install xdebug</pre>
<p>Após a extensão ser instalada, é necessário verificar o caminho completo onde ela se encontra, para isso basta digitar o seguinte comando:</p>
<pre class="brush: bash;">find / -name 'xdebug.so' 2&gt; /dev/null</pre>
<p>No meu caso o caminho retornado foi:</p>
<pre class="brush: bash;">/usr/lib/php5/20060613+lfs/xdebug.so</pre>
<p>Agora, a última etapa é configurar o <strong>php.ini</strong>:</p>
<pre class="brush: bash;">sudo gedit /etc/php5/apache2/php.ini</pre>
<p>E adicionar o seguinte conteúdo no fim do arquivo:</p>
<pre class="brush: plain;">[Zend]
zend_extension=&quot;/usr/lib/php5/20060613+lfs/xdebug.so&quot;</pre>
<p>Onde o caminho utilizado para o atributo <strong>zend_extension</strong> deve ser o retornado pelo comando de pesquisa. Após isso basta reiniciar o serviço Apache:</p>
<pre class="brush: bash;">sudo service apache2 restart</pre>
<p>E então verificar a saída do phpinfo(), que deverá ter um trecho como este:</p>
<div id="attachment_201" class="wp-caption alignnone" style="width: 310px"><a class="thickbox" href="http://fernandomantoan.com/wp-content/uploads/2009/11/xdebuginfo.png"><img class="size-medium wp-image-201" title="Screen com informações do XDebug" src="http://fernandomantoan.com/wp-content/uploads/2009/11/xdebuginfo-300x137.png" alt="phpinfo() com dados do XDebug" width="300" height="137" /></a><p class="wp-caption-text">phpinfo() com dados do XDebug</p></div>
<p>Bom, com isto a instalação do XDebug foi um sucesso, para quem quer mais informações sobre o XDebug e os repositórios oficiais do PHP:</p>
<ul>
<li><a href="http://www.xdebug.org/" target="_blank">Site oficial do XDebug</a>;</li>
<li><a href="http://pear.php.net/" target="_blank">Site oficial do PEAR</a>;</li>
<li><a href="http://pecl.php.net/" target="_blank">Site oficial do PECL</a>.</li>
</ul>
<p>Como o objetivo deste artigo era só abordar a instalação da extensão acredito que a missão esteja cumprida, em um artigo futuro farei um breve tutorial sobre como debugar os scripts PHP e, também, sobre como funciona a ferramenta de <em>profiling</em> desta extensão.<br />
Para quem acompanhou os artigos sobre a arquitetura de software com CodeIgniter, também falo que em breve colocarei aqui o artigo para desenvolvimento de um sistema visando demonstrar o uso desta arquitetura. Agora o tempo está um pouco menos apertado, poderei me dedicar mais ao blog. Até mais.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/instalando-xdebug-no-ubuntu-9-10/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>Reapresentação da palestra Webservices REST com Zend Framework</title>
		<link>http://fernandomantoan.com/php/reapresentacao-da-palestra-webservices-rest-com-zend-framework/</link>
		<comments>http://fernandomantoan.com/php/reapresentacao-da-palestra-webservices-rest-com-zend-framework/#comments</comments>
		<pubDate>Sat, 14 Nov 2009 02:49:50 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Eventos]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[cesufoz]]></category>
		<category><![CDATA[palestra]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[semana academica]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=165</guid>
		<description><![CDATA[Ontem eu e o Jurmir apresentamos na Semana Acadêmica Integrada 2009 do CESUFOZ a palestra Webservices REST com Zend Framework. Quem ainda não viu os slides, confira-os no post original, escrito após a apresentação na Latinoware. Agradeço a todos que nos prestigiaram e espero que tenham gostado da palestra. Esta foi uma reapresentação da palestra [...]]]></description>
			<content:encoded><![CDATA[<p>Ontem eu e o <a href="http://jcanalneto.wordpress.com/" target="_blank">Jurmir</a> apresentamos na Semana Acadêmica Integrada 2009 do CESUFOZ a palestra Webservices REST com Zend Framework. Quem ainda não viu os slides, confira-os no <a href="http://fernandomantoan.com/php/palestra-webservices-rest-com-zend-framework/">post original</a>, escrito após a apresentação na Latinoware. Agradeço a todos que nos prestigiaram e espero que tenham gostado da palestra. Esta foi uma reapresentação da palestra da Latinoware, o bom desta palestra é que tínhamos internet, então foi possível demonstrar o cliente Twitter, apesar de não ter sido possível inserir novos status, mas tudo bem, já foi muito mais completa do que a da Latinoware.</p>
<p>Estou em processo de término da monografia, além de estar atuando em alguns projetos, em breve espero colocar mais artigos aqui no blog. Até mais.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/reapresentacao-da-palestra-webservices-rest-com-zend-framework/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Palestra &#8211; PHP, Mercado e Certificações</title>
		<link>http://fernandomantoan.com/php/palestra-php-mercado-e-certificacoes/</link>
		<comments>http://fernandomantoan.com/php/palestra-php-mercado-e-certificacoes/#comments</comments>
		<pubDate>Fri, 13 Nov 2009 02:38:31 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Eventos]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[cesufoz]]></category>
		<category><![CDATA[semana academica]]></category>
		<category><![CDATA[zce]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=159</guid>
		<description><![CDATA[Apresentei ontem na Semana Acadêmica Integrada 2009 do Centro de Ensino Superior de Foz do Iguaçu a palestra entitulada PHP, Mercado e Certificações. Nela, procurei abordar um pouco da evolução da linguagem, mostrar que seu futuro é promissor, empresas que a utilizam (grandes companhias e empresas da cidade), perfis de profissionais, dicas para se tornar [...]]]></description>
			<content:encoded><![CDATA[<p>Apresentei ontem na Semana Acadêmica Integrada 2009 do Centro de Ensino Superior de Foz do Iguaçu a palestra entitulada <strong>PHP, Mercado e Certificações</strong>. Nela, procurei abordar um pouco da evolução da linguagem, mostrar que seu futuro é promissor, empresas que a utilizam (grandes companhias e empresas da cidade), perfis de profissionais, dicas para se tornar um profissional melhor e uma abordagem geral sobre as certificações da Zend, me focando mais na de PHP5 que eu já possuo alguma experiência. Espero que todos tenham gostado da palestra, segue os slides:</p>
<div style="width:425px;text-align:left" id="__ss_2488851"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" href="http://www.slideshare.net/fernandouhu/php-mercado-e-certificaes-2488851" title="PHP, Mercado e Certificações">PHP, Mercado e Certificações</a><object style="margin:0px" width="425" height="355"><param name="movie" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-091112201114-phpapp01&#038;stripped_title=php-mercado-e-certificaes-2488851" /><param name="allowFullScreen" value="true"/><param name="allowScriptAccess" value="always"/><embed src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=slides-091112201114-phpapp01&#038;stripped_title=php-mercado-e-certificaes-2488851" type="application/x-shockwave-flash" allowscriptaccess="always" allowfullscreen="true" width="425" height="355"></embed></object>
<div style="font-size:11px;font-family:tahoma,arial;height:26px;padding-top:2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">documents</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/fernandouhu">Fernando Geraldo Mantoan</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/palestra-php-mercado-e-certificacoes/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Sites de Clientes Finalizados</title>
		<link>http://fernandomantoan.com/php/sites-de-clientes-finalizados/</link>
		<comments>http://fernandomantoan.com/php/sites-de-clientes-finalizados/#comments</comments>
		<pubDate>Sat, 07 Nov 2009 16:22:45 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Clientes]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[drupal]]></category>
		<category><![CDATA[lumine]]></category>
		<category><![CDATA[smarty]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=151</guid>
		<description><![CDATA[Olá a todos. Depois de algum tempo deixando o blog parado venho anunciar a conclusão de dois projetos que já estavam pendentes a um bom tempo. Estes projetos foram desenvolvidos por mim e pelo meu amigo e sócio Anderson Rodrigo Davi. Ambos os sites dei uma de webdesigner e fiz o layout, acredito que ficaram [...]]]></description>
			<content:encoded><![CDATA[<p>Olá a todos. Depois de algum tempo deixando o blog parado venho anunciar a conclusão de dois projetos que já estavam pendentes a um bom tempo. Estes projetos foram desenvolvidos por mim e pelo meu amigo e sócio <a href="http://andersonrodrigo.com/" target="_blank">Anderson Rodrigo Davi</a>. Ambos os sites dei uma de <em>webdesigner</em> e fiz o layout, acredito que ficaram legais&#8230; <img src='http://fernandomantoan.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>O primeiro deles é o site da <a href="http://academiaplanetacorpo.com" target="_blank">Academia Planeta Corpo</a>. Este site foi marcado por, principalmente, ter sido o primeiro site desenvolvido utilizando um &#8220;framework&#8221; próprio, seguindo a dica dada por <a href="http://www.brandonsavage.net/why-every-developer-should-write-their-own-framework/" target="_blank">este post</a>. Nele construimos um CMS onde o cliente pode gerenciar as páginas, comentários, notícias e multimídia. A arquitetura foi elaborada no ano passado e não tínhamos conhecimento ainda de front controller, urls amigáveis e etc, e, devido a conclusão do projeto ser urgente, a arquitetura não foi melhorada. Provavelmente se o CMS for ter continuidade ele será re-escrito utilizando frameworks como <a href="http://codeigniter.com" target="_blank">CodeIgniter</a> ou <a href="http://framework.zend.com" target="_blank">Zend Framework</a> e será publicado como um CMS open-source, para ver se o projeto tem futuro ou não. Neste CMS utilizamos o framework de persistência <a href="http://hufersil.com.br/lumine" target="_blank">Lumine</a>, escrito pelo ZCE <a href="http://hufersil.com.br/" target="_blank">Hugo Ferreira da Silva</a>, conterrâneo de Foz do Iguaçu. Utilizamos também o <a href="http://www.smarty.net/" target="_blank">Smarty</a>, template engine muito robusta escrita em PHP e que ajudou a evitar o <a href="http://www.baguete.com.br/colunasDetalhes.php?id=2376" target="_blank">espagueti</a>, principalmente pela camada de visão não ter uma linha de código php, apenas template tags do smarty. O cliente deu um feedback muito legal sobre o site e sobre o sistema, e agradecemos a paciência tida pelo mesmo, afinal foi uma longa jornada até aqui.</p>
<p>O segundo site é o site da empresa <a href="http://ogarasa.com" target="_blank">OGA RÃ SA</a>. Uma multinacional que produz diversos produtos de madeira, utilizando apenas matéria-prima reflorestada, garantindo a continuidade do negócio florestal. Este site foi marcado por ter sido o <strong>primeiro</strong> site real que criamos utilizando <a href="http://drupal.org" target="_blank">Drupal</a>. Nele foram utilizados módulos como: Views, CCK, i18n, ImageCache, Panels e alguns outros. O resultado final do site foi muito bom e acredito que se não fosse coisas como faculdade, monografia e outros projetos, teríamos concluído-o rapidamente. Agradecemos também a este cliente pela paciência e confiança depositada em nós.</p>
<p>Bom, por enquanto é só, esta semana novamente deixarei o blog parado, tenho que finalizar a monografia e me preparar para outras 2 palestras, em breve volto à ativa com algum artigo novo. Até a próxima!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/sites-de-clientes-finalizados/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Cliente Twitter com Zend Framework</title>
		<link>http://fernandomantoan.com/php/cliente-twitter-com-zend-framework/</link>
		<comments>http://fernandomantoan.com/php/cliente-twitter-com-zend-framework/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 13:12:42 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Latinoware]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[rest]]></category>
		<category><![CDATA[twitter]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=141</guid>
		<description><![CDATA[Bom, como disse no outro post fiz um cliente com o Zend Framework para consumir o serviço REST disponibilizado pelo Twitter. Este cliente era para ser apresentado na palestra da Latinoware, infelizmente não foi possível o acesso à internet, o que faria com que o cliente não funcionasse, então acabei nem mostrando ele. Disponibilizo aqui [...]]]></description>
			<content:encoded><![CDATA[<p>Bom, como disse no <a href="http://fernandomantoan.com/php/palestra-webservices-rest-com-zend-framework/">outro post</a> fiz um cliente com o Zend Framework para consumir o serviço REST disponibilizado pelo <a href="http://twitter.com">Twitter</a>. Este cliente era para ser apresentado na palestra da Latinoware, infelizmente não foi possível o acesso à internet, o que faria com que o cliente não funcionasse, então acabei nem mostrando ele. Disponibilizo aqui então este cliente, para utilizá-lo é necessário ativar o mod_rewrite no Apache e, provavelmente, ativar a extensão curl do PHP. Tendo estes requisitos, descompacte o zip na pasta acessível pelo Apache, altere o arquivo application/configs/application.ini para que ele contenha o usuário e senha utilizados no seu banco de dados MySQL, como no exemplo abaixo:<br />
<code>resources.db.params.username = "root"<br />
resources.db.params.password = ""<br />
</code></p>
<p>Então, crie o banco de dados utilizando o arquivo encontrado em db/banco.sql. Após certificar-se de tudo estar pronto basta ir no browser e acessar o cliente na sua URL local, para quem não conhece o Zend Framework é necessário acessar a pasta public para que ele funcione&#8230; por exemplo: http://localhost/zf_twitter/public. Então é só cadastrar seu usuário e senha do twitter, logar-se e postar seus twitts, visualizar os últimos twitts de seus amigos, seu perfil e fazer buscas por twitts. Espero que gostem e lembro que é um aplicativo simples, mas quem estiver afim pode extendê-lo sem nenhum problema.</p>
<p>Para baixar o cliente, <a href="http://fernandomantoan.com/wp-content/uploads/2009/10/zf_twitter.zip">clique aqui</a></p>
<p>Até o próximo post.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/cliente-twitter-com-zend-framework/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Palestra Webservices REST com Zend Framework</title>
		<link>http://fernandomantoan.com/php/palestra-webservices-rest-com-zend-framework/</link>
		<comments>http://fernandomantoan.com/php/palestra-webservices-rest-com-zend-framework/#comments</comments>
		<pubDate>Sat, 24 Oct 2009 12:21:26 +0000</pubDate>
		<dc:creator>Fernando Mantoan</dc:creator>
				<category><![CDATA[Latinoware]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Zend Framework]]></category>
		<category><![CDATA[palestra]]></category>
		<category><![CDATA[rest]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=128</guid>
		<description><![CDATA[Ontem foi um dia bem diferente para mim, apresentei na Latinoware uma palestra sobre Webservices REST com Zend Framework, junto com meu amigo Jurmir. Fiquei bem nervoso, mas depois que comecei a falar consegui me acalmar e apresentar tranquilamente. Agradeço a todos que estiveram lá e espero que tenham gostado da palestra. Infelizmente graças a [...]]]></description>
			<content:encoded><![CDATA[<p>Ontem foi um dia bem diferente para mim, apresentei na <a href="http://latinoware.org/">Latinoware</a> uma palestra sobre Webservices REST com Zend Framework, junto com meu amigo <a href="http://jcanalneto.wordpress.com">Jurmir</a>. Fiquei bem nervoso, mas depois que comecei a falar consegui me acalmar e apresentar tranquilamente. Agradeço a todos que estiveram lá e espero que tenham gostado da palestra. Infelizmente graças a ótima rede wireless disponibilizada lá, não pude mostrar o aplicativo que fiz para consumir o webservice do Twitter, mas daqui a pouco disponibilizarei ele aqui no site. Bom, segue abaixo os slides da palestra (via <a href="http://www.slideshare.net/fernandouhu/webservices-rest-com-zend-framework">slideshare</a>).</p>
<div id="__ss_2335178" style="width: 425px; text-align: left;"><a style="font:14px Helvetica,Arial,Sans-serif;display:block;margin:12px 0 3px 0;text-decoration:underline;" title="Webservices REST com Zend Framework" href="http://www.slideshare.net/fernandouhu/webservices-rest-com-zend-framework">Webservices REST com Zend Framework</a><object style="margin:0px" classid="clsid:d27cdb6e-ae6d-11cf-96b8-444553540000" width="425" height="355" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=6,0,40,0"><param name="allowFullScreen" value="true" /><param name="allowScriptAccess" value="always" /><param name="src" value="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=apresminha-091024071009-phpapp02&amp;rel=0&amp;stripped_title=webservices-rest-com-zend-framework" /><param name="allowfullscreen" value="true" /><embed style="margin:0px" type="application/x-shockwave-flash" width="425" height="355" src="http://static.slidesharecdn.com/swf/ssplayer2.swf?doc=apresminha-091024071009-phpapp02&amp;rel=0&amp;stripped_title=webservices-rest-com-zend-framework" allowscriptaccess="always" allowfullscreen="true"></embed></object></p>
<div style="font-size: 11px; font-family: tahoma,arial; height: 26px; padding-top: 2px;">View more <a style="text-decoration:underline;" href="http://www.slideshare.net/">presentations</a> from <a style="text-decoration:underline;" href="http://www.slideshare.net/fernandouhu">fernandouhu</a>.</div>
</div>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/palestra-webservices-rest-com-zend-framework/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
	</channel>
</rss>
