<?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; arquiteturas de software</title>
	<atom:link href="http://fernandomantoan.com/tag/arquiteturas-de-software/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>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>Arquitetura de Software com CodeIgniter – Camada Facade e Padronização de Nomenclaturas</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-%e2%80%93-camada-facade-e-padronizacao-de-nomenclaturas/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-%e2%80%93-camada-facade-e-padronizacao-de-nomenclaturas/#comments</comments>
		<pubDate>Wed, 16 Sep 2009 21:35:05 +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[Frameworks]]></category>

		<guid isPermaLink="false">http://fernandomantoan.com/?p=53</guid>
		<description><![CDATA[Continuando com a série de artigos sobre uma proposta de arquitetura de software com o framework CodeIgniter, desta vez abordarei a criação da camada Facade na arquitetura e algumas mudanças na nomenclatura dos Controllers, fornecendo uma maior padronização. Obs: Para acompanhar este artigo é muito interessante que você já tenha feito as outras etapas citadas [...]]]></description>
			<content:encoded><![CDATA[<p>Continuando com a série de artigos sobre uma proposta de arquitetura de <em>software</em> com o <em>framework</em> CodeIgniter, desta vez abordarei a criação da camada <em>Facade</em> na arquitetura e algumas mudanças na nomenclatura dos <em>Controllers</em>, fornecendo uma maior padronização.</p>
<p><strong>Obs:</strong> Para acompanhar este artigo é muito interessante que você já tenha feito as outras etapas citadas nos <a href="http://fernandomantoan.com/category/frameworks/codeigniter/">artigos anteriores</a>.</p>
<h2><em>Facade Design Pattern</em></h2>
<p>O <em>pattern</em> arquitetural MVC traz uma forma muito mais consistente de se desenvolver aplicações, dando aos desenvolvedores camadas lógicas destinadas a cada parte que compõe uma aplicação, estas sendo lógica de negócio, apresentação e classes de representação de dados. Porém, existem alguns conceitos no mesmo que podem confundir muitos desenvolvedores, um deles é o de onde colocar regras de negócio? Algumas pessoas fazem isso no <em>Controller</em>, deixando o <em>Model</em> apenas como representação do negócio (objetos com get e set) e outros fazem com que o <em>Model</em> seja representação do negócio unido com as regras da aplicação também (por exemplo, uma lógica de venda), e o <em>Controller</em> fica encarregado apenas de controlar o fluxo entre as camadas. Eu particularmente uso o último conceito, por já ter lido ele em vários livros e também por seguir o conceito <em><a href="http://blog.astrumfutura.com/archives/353-An-Example-Zend-Framework-Blog-Application-Part-2-The-MVC-Application-Architecture.html">thin controller and fat model</a></em>.</p>
<p>Em uma arquitetura de <em>software</em> não pode existir mal-entendimento de conceitos, senão cada programador faria da maneira que acha mais sensata, fugindo da padronização. Para que isso possa ser evitado, essa arquitetura utiliza um <em>design pattern</em> chamado <em>Facade</em>. O conceito de um <em>Facade</em> é simples, esconder várias linhas de códigos em seus métodos, fornecendo métodos comuns a outras partes da aplicação. Ele será utilizado para conter as regras de negócio, fazendo com que o <em>Controller</em> cuide de controle de fluxo e com que o <em>Model</em> fique apenas encarregado da representação do domínio da aplicação. Mesmo que nessa arquitetura o <em>Model</em> represente os dados do banco de dados e o DAO cuide das operações com o banco, poderia existir problemas de padronização com relação a escolha da camada na hora de se codificar a regra de negócio, este problema pode, então, ser resolvido com a <em>Facade</em> conceituada acima. Com isso a arquitetura teria um conceito de &#8220;<em>thin controller</em>, <em>thin model and fat Facade</em>&#8220;.</p>
<h3>Modificando o <em>Core</em></h3>
<p>A camada <em>Facade</em> é criada diretamente no <em>core</em> do CodeIgniter, esta foi uma abordagem simplificada para se criar esta camada, a melhor abordagem seria utilizar os <em>hooks</em> para que não seja necessário um retrabalho ao atualizar o <em>core</em> do <em>framework</em>, pois tendo codificado direto no <em>core</em> alguns arquivos podem acabar sendo substítuidos necessitando a recodificação da camada. Este aviso é necessário pelo simples fato de ser importante saber que existem <strong>melhores alternativas</strong>.</p>
<p>Tendo tudo explanado, é hora de criar um arquivo chamado <strong>Facade.php</strong>, dentro de <strong>/system/libraries</strong>/, e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">
&lt;?php
abstract class Facade
{
	public $_parent_name = '';
	public function Facade()
	{
		$this-&gt;_parent_name = ucfirst(get_class($this));
		log_message('debug', &quot;Facade Class Initialized&quot;);
	}
	public function _assign_libraries($use_reference = TRUE)
	{
		$CI =&amp; get_instance();
		foreach (array_keys(get_object_vars($CI)) as $key)
		{
			if ( ! isset($this-&gt;$key) AND $key != $this-&gt;_parent_name)
			{
				// In some cases using references can cause
				// problems so we'll conditionally use them
				if ($use_reference == TRUE)
				{
					$this-&gt;$key = NULL; // Needed to prevent reference errors with some configurations
					$this-&gt;$key =&amp; $CI-&gt;$key;
				}
				else
				{
					$this-&gt;$key = $CI-&gt;$key;
				}
			}
		}
	}
}
</pre>
<p>Este código utiliza como base o código do <strong>Model.php</strong>, classe nativa do CodeIgniter, onde no caso da <em>Facade</em> serão configuradas e carregadas as bibliotecas que existem no <em>Controller</em> para deixá-las disponíveis nesta camada, já que isso será útil, por exemplo, na hora de validar formulários. Como o <em>Model</em> já foi implementado para obter estas bibliotecas, utilizar sua implementação era a melhor abordagem para a <em>Facade</em>, mas outra forma seria herdar da classe <em>Model</em>.</p>
<p>Agora, já existe uma camada <em>Facade</em> como base para extender as <em>Facades</em> específicas, só que ainda é necessário implementar um <em>loader</em> para a <em>Facade</em>. O CodeIgniter fornece métodos para carregar o <em>Model</em>, <em>View</em> e as <em>Libraries</em>. Esse loader funciona da seguinte maneira, pelo comando <strong>$this-&gt;load-&gt;model(&#8216;nomedomodel&#8217;)</strong>, de dentro de um <em>Controller</em>, o <em>Model</em> fica disponível para o <em>Controller</em>. O responsável por esta funcionalidade é o <em><strong>Loader</strong></em>, que pode ser encontrado na pasta <strong>/system/libraries/Loader.php</strong>. Primeiramente é necessário setar um atributo que conterá as <em>Facades</em> carregadas pelo <em>Loader</em>. A definição dos atributos da classe é a seguinte:</p>
<pre class="brush: php;">var $_ci_ob_level;
var $_ci_view_path        = '';
var $_ci_is_php5        = FALSE;
var $_ci_is_instance     = FALSE; // Whether we should use $this or $CI =&amp; get_instance()
var $_ci_cached_vars    = array();
var $_ci_classes        = array();
var $_ci_loaded_files    = array();
var $_ci_models            = array();
var $_ci_helpers        = array();
var $_ci_plugins        = array();
var $_ci_varmap            = array('unit_test' =&gt; 'unit', 'user_agent' =&gt; 'agent');
</pre>
<p>Adicionando a variável <strong>$_ci_facades</strong>, que será um array contendo as <em>Facades</em> carregadas, a definição então fica:</p>
<pre class="brush: php;">
var $_ci_ob_level;
var $_ci_view_path		= '';
var $_ci_is_php5		= FALSE;
var $_ci_is_instance 	= FALSE; // Whether we should use $this or $CI =&amp; get_instance()
var $_ci_cached_vars	= array();
var $_ci_classes		= array();
var $_ci_loaded_files	= array();
var $_ci_facades		= array(); // Facade pattern added to the CI
var $_ci_models		= array();
var $_ci_helpers		= array();
var $_ci_plugins		= array();
var $_ci_varmap		= array('unit_test' =&gt; 'unit', 'user_agent' =&gt; 'agent');
</pre>
<p>Agora, para implementar a funcionalidade de carregar as <em>Facades</em>, é necessário adicionar, neste mesmo arquivo <strong>Loader.php</strong>, o seguinte método, que pode ser colocado acima do método <strong>database()</strong>:</p>
<pre class="brush: php;">
function facade($facade, $name = '')
{
	if (is_array($facade))
	{
		foreach($facade as $babe)
		{
			$this-&gt;facade($babe);
		}
		return;
	}

	if ($facade == '')
	{
		return;
	}

	// Is the facade in a sub-folder? If so, parse out the filename and path.
	if (strpos($facade, '/') === FALSE)
	{
		$path = '';
	}
	else
	{
		$x = explode('/', $facade);
		$facade = end($x);
		unset($x[count($x)-1]);
		$path = implode('/', $x).'/';
	}

	if ($name == '')
	{
		$name = strtolower(str_replace('_', '', $facade));
	}

	if (in_array($name, $this-&gt;_ci_facades, TRUE))
	{
		return;
	}

	$CI =&amp; get_instance();
	if (isset($CI-&gt;$name))
	{
		show_error('The facade name you are loading is the name of a resource that is already being used: '.$name);
	}

	$facade = strtolower($facade);

	if ( ! file_exists(APPPATH . 'facades/'. $path . $facade . EXT))
	{
		show_error('Unable to locate the facade you have specified: '.$facade);
	}

	if ( ! class_exists('Facade'))
	{
		load_class('Facade', FALSE);
	}

	require_once(APPPATH . 'facades/'.$path.$facade.EXT);

	$facade = ucfirst(str_replace('_', '', $facade));

	$CI-&gt;$name = new $facade();
	$CI-&gt;$name-&gt;_assign_libraries();

	$this-&gt;_ci_facades[] = $name;
}
</pre>
<p>Este código, basicamente, irá incluir o arquivo da <em>Facade</em> e irá deixá-la disponível através de um atributo do <em>Controller</em> em questão, permitindo desta forma que o <em>Controller</em> acesse os métodos desta <em>Facade</em>.</p>
<h3>Testando</h3>
<p>Agora, é necessário testar se a camada criada está funcionando corretamente. Primeiramente é necessária a criação da pasta <strong>facades</strong> dentro de <strong>/system/application/</strong>. Esta pasta armazenará as <em>Facades</em> que a aplicação necessitará. Apenas para testar a camada basta criar o arquivo <strong>/system/application/facades/index_facade.php</strong>, e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">
&lt;?php
class IndexFacade extends Facade
{
	public function index() { echo 'camada facade acionada'; }
}
?&gt;
</pre>
<p>Dentro do <em>Controller</em> <strong>welcome.php</strong>, criado no artigo anterior, basta mudar o construtor e o método <strong>index()</strong>, para que fique assim:</p>
<pre class="brush: php;">
public function Welcome()
{
	parent::Controller();
	$this-&gt;load-&gt;library('smartyview');
	$this-&gt;load-&gt;facade('index_facade');
}
public function index()
{
	$this-&gt;indexfacade-&gt;index();
	$dao = new TarefasDAO();
	$tarefas = $dao-&gt;allData();
	$this-&gt;smartyview-&gt;assign_by_ref('tarefas', $tarefas);
	$this-&gt;smartyview-&gt;display('index.tpl');
}</pre>
<p>Ao chamar no navegador, deverá exibir a mensagem &#8220;<strong>camada facade acionada</strong>&#8220;. Com isso, a camada <em>Facade</em> está corretamente integrada ao CodeIgniter, de uma forma que pode ser considerada nativa, pois ela pode ser carregada e acionada da mesma forma que os <em>Models</em> padrão do framework.</p>
<h2>Nomenclatura dos <em>Controllers</em></h2>
<p>Agora, para finalizar a definição da arquitetura, é necessária uma modificação na nomenclatura dos <em>Controllers</em>. Isso é necessário pois o CodeIgniter não obriga o desenvolvedor a seguir uma forma de nomear seus <em>Controllers</em> e isso pode dar brechas para ocorrer erros, como o de definir o mesmo nome para o <em>Controller</em> e para o <em>Model</em>, ou ao se criar um nome próprio para os <em>Controllers</em>, ele ser necessário na URL do browser (por exemplo, se seu <em>Controller</em> é Pessoas_controller, a url ficaria: seuhost.com/index.php/pessoas_controller).</p>
<p>A nomenclatura escolhida para esta arquitetura é a mesma do <em>framework</em> CakePHP, onde os arquivos devem ter o sufixo <strong>_controller.php</strong>, por exemplo <strong>pessoas_controller.php</strong>, e o nome das classes deve conter o sufixo <strong>Controller</strong>, por exemplo <strong>PessoasController</strong>.</p>
<p>Iniciando as modificações necessárias para se estabelecer esta nomenclatura, é necessário modificar a biblioteca do CodeIgniter <strong>Router.php</strong>, localizada em <strong>/system/libraries/</strong>, a função <strong>_set_request</strong>, possui a seguinte linha:</p>
<pre class="brush: php;">$this-&gt;set_class($segments[0]);</pre>
<p>Ela seta a classe para o que vier dos segmentos da URL. É necessário adicionar o sufixo &#8220;_controller&#8221;, ficando esta linha assim:</p>
<pre class="brush: php;">$this-&gt;set_class($segments[0] . '_controller');</pre>
<p>A próxima alteração a ser feita é no método <strong>_validate_request</strong>, a função completa é a seguinte:</p>
<pre class="brush: php;">
function _validate_request($segments)
{
	// Does the requested controller exist in the root folder?
	if (file_exists(APPPATH.'controllers/'.$segments[0].EXT))
	{
		return $segments;
	}
	// Is the controller in a sub-folder?
	if (is_dir(APPPATH.'controllers/'.$segments[0]))
	{
		// Set the directory and remove it from the segment array
		$this-&gt;set_directory($segments[0]);
		$segments = array_slice($segments, 1);
		if (count($segments) &gt; 0)
		{
			// Does the requested controller exist in the sub-folder?
			if ( ! file_exists(APPPATH . 'controllers/' . $this-&gt;fetch_directory() . $segments[0] . EXT))
			{
				show_404($this-&gt;fetch_directory().$segments[0]);
			}
		}
		else
		{
			$this-&gt;set_class($this-&gt;default_controller);
			$this-&gt;set_method('index');
			// Does the default controller exist in the sub-folder?
			if ( ! file_exists( APPPATH . 'controllers/' . $this-&gt;fetch_directory() . $this-&gt;default_controller . EXT))
			{
				$this-&gt;directory = '';
				return array();
			}
		}
		return $segments;
	}
	// Can't find the requested controller...
	show_404($segments[0]);
}
</pre>
<p>Alterando-a, ela fica:</p>
<pre class="brush: php;">
function _validate_request($segments)
{
	// Does the requested controller exist in the root folder?
	if (file_exists(APPPATH.'controllers/'.$segments[0] . '_controller' .EXT))
	{
		return $segments;
	}
	// Is the controller in a sub-folder?
	if (is_dir(APPPATH.'controllers/'.$segments[0]))
	{
		// Set the directory and remove it from the segment array
		$this-&gt;set_directory($segments[0]);
		$segments = array_slice($segments, 1);
		if (count($segments) &gt; 0)
		{
			// Does the requested controller exist in the sub-folder?
			if ( ! file_exists( APPPATH . 'controllers/' . $this-&gt;fetch_directory() . $segments[0] . '_controller' . EXT ))
			{
				show_404($this-&gt;fetch_directory().$segments[0]);
			}
		}
		else
		{
			$this-&gt;set_class($this-&gt;default_controller);
			$this-&gt;set_method('index');
			// Does the default controller exist in the sub-folder?
			if ( ! file_exists( APPPATH . 'controllers/' . $this-&gt;fetch_directory() . $this-&gt;default_controller . EXT ))
			{
				$this-&gt;directory = '';
				return array();
			}
		}
		return $segments;
	}
	// Can't find the requested controller...
	show_404($segments[0]);
}
</pre>
<p>O que é feito, é alterar a forma padrão de se adicionar os <em>Controllers</em>, para que eles contenham o sufixo &#8220;_controller&#8221; em seus nomes. Agora basta mudar a forma de instanciar os <em>Controllers</em>. No arquivo <strong>CodeIgniter.php</strong>, localizado em <strong>/system/codeigniter/</strong>, basta alterar a seguinte linha:</p>
<pre class="brush: php;">$class  = $RTR-&gt;fetch_class();</pre>
<p>Para:</p>
<pre class="brush: php;">$class  = str_replace('_', '', $RTR-&gt;fetch_class());</pre>
<p>Pronto, agora a nomenclatura dos <em>Controllers</em> está padronizada.</p>
<p>Para testar se as alterações estão funcionando, basta renomear o arquivo <strong>welcome.php</strong> dentro de <strong>/system/application/controllers/</strong>, para <strong>welcome_controller.php</strong>, e dentro dele, modificar a declaração da classe e seu construtor, de:</p>
<pre class="brush: php;">
class Welcome extends Controller
{
	public function Welcome
	{
</pre>
<p>Para:</p>
<pre class="brush: php;">
class WelcomeController extends Controller
{
	public function WelcomeController
	{
</pre>
<p>Ao acessar o projeto, se tudo aparecer corretamente, significa que a padronização da nomenclatura foi setada com sucesso. Agora, os controllers requisitados por uma URL, como por exemplo <strong>index.php/carros</strong>, serão referenciados no arquivo com o sufixo <strong>_controller</strong> e numa classe com o sufixo <strong>Controller</strong>, por exemplo <strong>carros_controller.php</strong> e <strong>CarrosController</strong>.</p>
<h2>Concluindo</h2>
<p>Assim concluí-se a definição da arquitetura utilizando o <em>Framework</em> CodeIgniter e alguns <em>Design Patterns</em>. Com isso, já é possível desenvolver as aplicações necessárias para você/sua empresa, de uma forma robusta, dando mais facilidade ao trabalho tanto dos <em>designers</em> quanto dos programadores. A arquitetura possui 5 camadas lógicas para desenvolvimento: <em><strong>Controller</strong></em>, <em><strong>Facade</strong></em>, <em><strong>Model</strong></em>, <em><strong>DAO</strong></em>, <em><strong>View</strong></em>; possui os <em>frameworks</em>: <strong>Smarty</strong> e <strong>Doctrine</strong>; e possui uma <strong>forma padronizada de se nomear os <em>Controllers</em></strong>.</p>
<p>No próximo artigo demonstrarei os passos necessários para se desenvolver um sistema simples de controle de tarefas, para demonstrar o uso de alguns <em>helpers</em> e os exemplos de cada camada lógica desta arquitetura. Futuramente transformarei esta série de artigos referentes à arquitetura com o CodeIgniter em um <em>ebook</em> e publicarei sob a licença Creative Commons, aqui no meu site.</p>
<p>Ficarei agora um tempo sem postar artigos referentes a esta arquitetura, estou com vários projetos de <em>freelance</em>, além de estar trabalhando em tempo integral na <a href="http://b3informatica.com">B3,</a> e também tenho que refazer boa parte da fundamentação teórica da minha monografia (pois é, agora que troquei de orientador, eu vi que eu estava no rumo errado) e fazer todo o capítulo de experimento dela (digamos, o capítulo principal da monografia), ou seja, estou sem tempo disponível para escrever o próximo artigo. Colocarei alguns posts rápidos aqui no site, mas diariamente estou no <a href="http://twitter.com/fernandouhu">twitter</a>, falando do dia-a-dia, reclamando e etc <img src='http://fernandomantoan.com/wp-includes/images/smilies/icon_biggrin.gif' alt=':D' class='wp-smiley' /> . Bom, então é isso, até a próxima!</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-%e2%80%93-camada-facade-e-padronizacao-de-nomenclaturas/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>Arquitetura de Software com CodeIgniter &#8211; Integrando o Doctrine</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-doctrine/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-doctrine/#comments</comments>
		<pubDate>Mon, 08 Jun 2009 01:20:34 +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>

		<guid isPermaLink="false">http://localhost/fernandomantoan/?p=7</guid>
		<description><![CDATA[Neste quarto artigo sobre uma Arquitetura de Software com o CodeIgniter, mostrarei como fazer a integração do framework de persistência Doctrine com o framework CodeIgniter. Como explicado anteriormente, o Doctrine foi escolhido por fornecer formas robustas e flexíveis de se realizar consultas com uma sintaxe orientada a objetos, o que os desenvolvedores do projeto chamam [...]]]></description>
			<content:encoded><![CDATA[<p>Neste quarto artigo sobre uma Arquitetura de <em>Software</em>  com o CodeIgniter, mostrarei como fazer a integração do <em>framework</em> de persistência Doctrine com o <em>framework </em>CodeIgniter. Como explicado anteriormente, o Doctrine foi escolhido por fornecer formas robustas e flexíveis de se realizar consultas com uma sintaxe orientada a objetos, o que os desenvolvedores do projeto chamam de Doctrine <em>Query Language</em> (DQL), o que lembra a Hibernate <em>Query Language</em> (HQL) do Java. Além disso, ele fornece classes de persistência para cada tabela do banco de dados.</p>
<p>Agora saindo um pouco da teoria, é hora de por a mão na massa e começar a integração do <em>framework</em>. Antes de mais nada é necessário fazer o <em>download</em> da última versão estável do Doctrine, de preferência baixar a &#8220;Sandbox&#8221;, é possível encontrá-la na <a href="http://www.doctrine-project.org/download">página oficial do projeto</a>.</p>
<h2>Integrando o Doctrine</h2>
<p>A primeira etapa é criar uma pasta chamada <strong>doctrine</strong> dentro de <strong>system/database</strong>, do CodeIgniter. Após o <em>download</em> do pacote do Doctrine ser concluído, basta extraí-lo e copiar todo o conteúdo localizado na pasta <strong>lib</strong> deste pacote para a pasta <strong>system/database/doctrine</strong>. Agora, esta pasta deve conter uma pasta chamada <strong>Doctrine</strong> e um <em>script</em> PHP chamado <strong>Doctrine.php</strong>.</p>
<p>A segunda etapa é configurar algumas propriedades do Doctrine para que ele possa ser carregado e para deixá-lo apto a se conectar com um banco de dados. Dentro do arquivo <strong>system/application/config/database.php</strong>, basta localizar a linha com o seguinte trecho:</p>
<pre class="brush: php;">$db['default']['cachedir'] = &quot;&quot;; </pre>
<p>Logo abaixo desta linha, insira o seguinte trecho:</p>
<pre class="brush: php;">//Configura os dados da fonte de dados, declarados acima
$db['default']['dsn'] = $db['default']['dbdriver'] .
							'://' . $db['default']['username'] .
							':' . $db['default']['password'] .
							'@' . $db['default']['hostname'] .
							'/' . $db['default']['database'];
//Inclui a classe do Doctrine
require_once realpath(dirname(__FILE__) . '/../..') . DIRECTORY_SEPARATOR . 'database/doctrine/Doctrine.php';
//Seta o autoloader de classes
spl_autoload_register(array('Doctrine', 'autoload'));
//Carrega a conexão do Doctrine com a string de DSN configurada e o banco de dados escolhido
Doctrine_Manager::connection($db['default']['dsn'], $db['default']['database']);
//Seta a forma de se carregar os models para o tipo &quot;conservative&quot; ou &quot;lazy initiation&quot;
Doctrine_Manager::getInstance()-&gt;setAttribute('model_loading', 'conservative');
//Carrega os modelos para o autoloader
Doctrine::loadModels(realpath(dirname(__FILE__) . '/..') . DIRECTORY_SEPARATOR . 'models');
</pre>
<p>Este código define um Nome de Fonte de Dados (<em>Data Source Name</em> &#8211; DSN), depois inclui a classe Doctrine, configura o <em>autoloader</em> do <em>framework</em>, inicia a conexão com o banco de dados pelo DSN definido e no banco de dados definido neste arquivo de configuração (no trecho $db['default']['database'] = &#8220;&#8221;), seta para que o carregamento de classes seja &#8220;lazy&#8221;, ou seja, as classes agregadas são carregadas de acordo com a necessidade e, por último, seta a pasta para o Doctrine procurar por seus <em>Models</em>.</p>
<p>Após definir este trecho de código, deve-se garantir que o <strong>index.php</strong> da aplicação carregue o arquivo de configuração do banco de dados. Para que isso seja feito, basta entrar no arquivo <strong>index.php</strong> na raíz do CodeIgniter e modificar suas últimas duas linhas, deixando assim:</p>
<pre class="brush: php;">require_once APPPATH . 'config/database.php';
require_once BASEPATH . 'codeigniter/CodeIgniter'.EXT;</pre>
<h2>Configurando a <em>Interface</em> de Linha de Comando</h2>
<p>O Doctrine possui uma <em>interface</em> executada em linha de comando que pode auxiliar muito na geração dos <em>models</em>, migrações e etc. É sempre bom deixar esta interface funcionando, em qualquer projeto que utilize o Doctrine. Primeiramente, deve-se criar o arquivo <strong>doctrine</strong> na pasta <strong>system/application</strong>, sem extensão nenhuma mesmo, e dar um chmod para que ele possa ser executado (chmod a+x). Este arquivo deve ter o seguinte conteúdo:</p>
<pre class="brush: php;">#!/usr/bin/env php
&lt;?php
chdir(dirname(__FILE__));
include('doctrine.php');</pre>
<p>Agora, é necessário criar o arquivo <strong>doctrine.php</strong> na pasta <strong>system/application</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: php;">&lt;?php
require_once 'config/database.php';
//Configura o Doctrine Cli
$config = array('data_fixtures_path' =&gt; dirname(__FILE__) . DIRECTORY_SEPARATOR . '/fixtures',
				'models_path' =&gt; dirname(__FILE__) . DIRECTORY_SEPARATOR . '/models',
				'migrations_path' =&gt; dirname(__FILE__) . DIRECTORY_SEPARATOR . '/migrations',
				'sql_path' =&gt; dirname(__FILE__) . DIRECTORY_SEPARATOR . '/sql',
				'yaml_schema_path' =&gt; dirname(__FILE__) . DIRECTORY_SEPARATOR . '/schema');
$cli = new Doctrine_Cli($config);
$cli-&gt;run($_SERVER['argv']); ?&gt;
</pre>
<p>Ele será responsável por configurar cada pasta onde o Cli poderá atuar para realizar suas funcionalidades. A próxima etapa é criar os seguintes diretórios dentro de <strong>system/application</strong>:</p>
<ul>
<li>fixtures</li>
<li>migrations</li>
<li>schema</li>
<li>sql</li>
</ul>
<p>Agora é necessário setar o banco de dados que a aplicação utilizará, por exemplo, tarefas_ci:</p>
<pre class="brush: php;">$db['default']['database'] = &quot;tarefas_ci&quot;;</pre>
<p>Após estes passos estarem concluídos, a <em>interface</em> com a linha de comando deverá estar funcionando. Para testá-la, acesse um terminal e digite os seguintes comandos (para sistemas GNU/Linux), onde &#8220;suapasta&#8221; corresponde ao endereço físico da pasta da aplicação:</p>
<pre class="brush: bash;">$ cd suapasta/system/application
$ php doctrine</pre>
<p>Caso apareça uma mensagem dizendo &#8220;<em>No direct script access allowed</em>&#8221; será necessário acessar o arquivo <strong>database.php</strong> no diretório <strong>system/application/config</strong> e comentar o trecho:</p>
<pre class="brush: php;"> if ( ! defined('BASEPATH')) exit('No direct script access allowed'); </pre>
<p><strong>Importante:</strong> deixe este trecho comentando <strong>somente para utilizar o Cli</strong>, deixe-o descomentado principalmente no ambiente de produção, por questões de segurança. O resultado de executar o Cli é o seguinte:</p>
<pre class="brush: bash;">Doctrine Command Line Interface
doctrine generate-migrations-models
doctrine create-tables
doctrine migrate
doctrine build-all-load
doctrine dump-data
doctrine dql
doctrine generate-yaml-db
doctrine generate-models-db
doctrine rebuild-db
doctrine create-db
doctrine generate-migrations-diff
doctrine drop-db
doctrine load-data
doctrine generate-migration
doctrine build-all
doctrine generate-yaml-models
doctrine build-all-reload
doctrine compile
doctrine generate-migrations-db
doctrine generate-models-yaml
doctrine generate-sql</pre>
<h2>Testando a Integração</h2>
<p>Após várias etapas é hora de efetuar operações para testar a <em>interface</em> de linha de comando do Doctrine e a integração do mesmo com o CodeIgniter. O banco de dados utilizado nesta etapa é o seguinte:</p>
<pre class="brush: sql;">CREATE DATABASE tarefas_ci;
USE tarefas_ci;
CREATE TABLE `tarefas` (
id INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,
titulo VARCHAR(200) NOT NULL,
situacao ENUM('A', 'F') DEFAULT 'A'
)ENGINE=InnoDB;</pre>
<p>A configuração do banco de dados, encontrada no arquivo <strong>database.php</strong> da pasta <strong>system/application/config</strong>, deverá ser algo como o seguinte, onde os atributos <strong>hostname</strong>, <strong>username</strong> e <strong>password </strong>deverão ser configurados de acordo com os dados do banco:</p>
<pre class="brush: php;">//Host do banco de dados
$db['default']['hostname'] = &quot;localhost&quot;;
//Usuário para se conectar com o banco
$db['default']['username'] = &quot;root&quot;;
//Senha do usuário do banco de dados
$db['default']['password'] = &quot;&quot;;
//Banco de dados a se conectar
$db['default']['database'] = &quot;tarefas_ci&quot;;
//Driver de conexão com o banco
$db['default']['dbdriver'] = &quot;mysql&quot;;</pre>
<p>Primeiramente, é necessário criar o <strong>schema</strong> para o Doctrine poder gerar os <em>models</em> de acordo com o banco de dados, este arquivo segue o padrão YAML para definição dos dados. Para isso basta criar o arquivo <strong>schema.yml</strong> na pasta <strong>system/application/schema</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: plain;"> Tarefas:
  columns:
    id:
      primary: true
      autoincrement: true
      type: integer(10)
    titulo:
      type: string(200)
    situacao:
      type: enum
      length: 2
      values: ['A', 'F']
</pre>
<p>Agora, basta executar o seguinte comando, para os <em>models</em> serem criados em <strong>system/application/models</strong>:</p>
<pre class="brush: bash;">$ php doctrine generate-models-yaml
generate-models-yaml - Generated models successfully from YAML schema</pre>
<p>Ao verificar o conteúdo da pasta <strong>system/application/models</strong>, os seguintes arquivos devem estar presentes: <strong>Tarefas.php</strong> e <strong>generated/BaseTarefas.php</strong>. O conteúdo destes arquivos são, respectivamente:</p>
<pre class="brush: php;">abstract class BaseTarefas extends Doctrine_Record
{
	public function setTableDefinition()
	{
		$this-&gt;setTableName('tarefas');
		$this-&gt;hasColumn('id', 'integer', 10, array('primary' =&gt; true, 'autoincrement' =&gt; true, 'type' =&gt; 'integer', 'length' =&gt; '10'));
		$this-&gt;hasColumn('titulo', 'string', 200, array('type' =&gt; 'string', 'length' =&gt; '200'));
		$this-&gt;hasColumn('situacao', 'enum', 2, array('type' =&gt; 'enum', 'length' =&gt; 2, 'values' =&gt; array(0 =&gt; 'A', 1 =&gt; 'F')));
	}
}</pre>
<pre class="brush: php;">class Tarefas extends BaseTarefas
{
}</pre>
<p>Agora é necessário criar o arquivo <strong>TarefasDAO.php</strong> na pasta <strong>system/application/models</strong>, ele terá o seguinte conteúdo:</p>
<pre class="brush: php;">&lt;?php
class TarefasDAO
{
	/**
	 * Seleciona as tarefas do banco de dados, retornando um array de objetos
	 * @access public
	 * @return array = Array de objetos Tarefa
	 */
	public function allData()
	{
		$query = new Doctrine_Query();
		$query-&gt;from('Tarefas t');
		$query-&gt;orderby('t.id DESC');
		return $query-&gt;execute();
	}
}
?&gt;
</pre>
<p>Agora, pode-se carregar alguns dados para a aplicação, para popular o banco e posteriormente fazer algumas consultas. O primeiro passo para fazer isso é criar uma <em>fixture</em> que é utilizado para o Doctrine popular o banco, para isto basta criar o arquivo <strong>tarefas.yml</strong> na pasta <strong>system/application/fixtures</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: plain;">Tarefas:
  teste:
    titulo: teste
    situacao: A
  teste2:
    titulo: teste2
    situacao: F</pre>
<p>Então basta executar o seguinte comando no terminal:</p>
<pre class="brush: bash;">$ php 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 &quot;tarefas_ci&quot; named &quot;tarefas_ci&quot;
build-all-reload - Generated models successfully from YAML schema
build-all-reload - Successfully created database for connection &quot;tarefas_ci&quot; named &quot;tarefas_ci&quot;
build-all-reload - Created tables successfully
build-all-reload - Data was successfully loaded</pre>
<p>Neste ponto o banco está devidamente configurado e possui 2 registros inseridos. Agora basta verificar se o Doctrine foi corretamente integrado no CodeIgniter. No <em>Controller</em> <strong>welcome.php</strong> localizado na pasta <strong>system/application/controllers</strong>, coloque o seguinte conteúdo:</p>
<pre class="brush: php;">&lt;?php
class Welcome extends Controller
{
	public function Welcome()
	{
		parent::Controller();
		$this-&gt;load-&gt;library('smartyview');
	}
	public function index()
	{
		$dao = new TarefasDAO();
		$tarefas = $dao-&gt;allData();
		$this-&gt;smartyview-&gt;assign_by_ref('tarefas', $tarefas);
		$this-&gt;smartyview-&gt;display('index.tpl');
	}
}
?&gt;</pre>
<p>Nele pega-se a classe DAO, então é executado o método que retorna um array de todas as tarefas ordenadas pelo ID em ordem decrescente, passa-se este array de tarefas para a <em>View</em> e a exibe ao usuário. Agora basta então criar a <em>View</em>, ela ficará localizada na pasta <strong>system/application/views</strong> com o nome <strong>index.tpl</strong>, e terá o seguinte conteúdo:</p>
<pre class="brush: xml;">&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;Arquitetura CI&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;h1&gt;Lista de Tarefas&lt;/h1&gt;
		&lt;ul&gt;
		{foreach from=$tarefas item=tarefa}
		&lt;li&gt;{$tarefa.id}, {$tarefa.titulo} - {if $tarefa.situacao eq 'A'}Aberta{else}Fechada{/if}&lt;/li&gt;
		{/foreach}
		&lt;/ul&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Aqui é feito um laço no array de objetos de Tarefas retornado pela DAO e a cada iteração é impresso, em um elemento de uma lista desordenada, o ID da tarefa, seu título e a situação, que pode ser Aberta ou Fechada.</p>
<p>Bom, com isso encerro mais um artigo sobre a arquitetura de desenvolvimento de <em>software</em> com CodeIgniter, Smarty e Doctrine. No próximo artigo me focarei em impelementar o padrão <em>Facade</em> no <em>framework</em> CodeIgniter, seguido pela mudança de nomenclatura em algumas camadas e, finalmente, pelo desenvolvimento de um sistema de controle de tarefas. Aguardem, até a próxima.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-doctrine/feed/</wfw:commentRss>
		<slash:comments>14</slash:comments>
		</item>
		<item>
		<title>Arquitetura de Software com CodeIgniter &#8211; Integrando o Smarty</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-smarty/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-smarty/#comments</comments>
		<pubDate>Mon, 01 Jun 2009 21:55:02 +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[Frameworks]]></category>
		<category><![CDATA[smarty]]></category>

		<guid isPermaLink="false">http://localhost/fernandomantoan/?p=6</guid>
		<description><![CDATA[Neste terceiro artigo sobre uma proposta de arquitetura de software utilizando CodeIgniter e alguns outros frameworks, mostrarei na prática como fazer a integração do framework de templates Smarty com o CodeIgniter. Após fazer o download e instalar a última versão do framework CodeIgniter, é hora de fazer o download da última versão estável do Smarty, [...]]]></description>
			<content:encoded><![CDATA[<p>Neste terceiro artigo sobre uma proposta de arquitetura de <em>software</em> utilizando CodeIgniter e alguns outros <em>frameworks</em>, mostrarei na prática como fazer a integração do <em>framework</em> de <em>template</em>s Smarty com o CodeIgniter. Após fazer o <em>download</em><span style="font-style: normal;"> e instalar a última versão do </span><em>framework</em><span style="font-style: normal;"> CodeIgniter, é hora de fazer o download da última versão estável do Smarty, que pode ser encontrada no site <a href="http://smarty.net/download.php">oficial do framework</a>. Após efetuar o download, basta descompactar o pacote baixado e copiar a pasta </span><span style="font-style: normal;"><strong>libs</strong></span><span style="font-style: normal;"> para a pasta </span><span style="font-style: normal;"><strong>application/libraries</strong></span><span style="font-style: normal;"> da instalação do CodeIgniter. Então é só renomear a pasta </span><span style="font-style: normal;"><strong>libs</strong></span><span style="font-style: normal;"> para </span><span style="font-style: normal;"><strong>smarty_libs</strong></span><span style="font-style: normal;">, apenas para melhorar a organização dos diretórios.</span></p>
<p class="western">Na arquitetura proposta, o Smarty estará disponível a partir da variável <strong>smartyview</strong> dos <em>Controllers</em>, assim é necessária a criação de arquivos para localizar e disponibilizar o Smarty como uma biblioteca do CodeIgniter. O primeiro arquivo a ser criado estará localizado na pasta <strong>application/libraries</strong> e se chamará <strong>smartyview.php</strong>. Ele terá o seguinte conteúdo:</p>
<pre class="brush: php;">&lt;?php
if (!defined('BASEPATH')) die('Acesso direto ao script bloqueado.');
require_once BASEPATH . 'application/libraries/smarty_libs/Smarty.class.php';
/**
* Classe que extende smarty para definir algumas configurações básicas de inicialização
*
* @author Fernando
* @package libraries
*/
class SmartyView extends Smarty
{
	/**
	* Construtor da classe, define a pasta de compilação e a pasta de templates
	*
	* @access public
	* @author Fernando
	* @version 1.0
	*/
	public function SmartyView()
	{
		$this-&gt;compile_dir = BASEPATH . &quot;application/views/templates_c&quot;;
		$this-&gt;template_dir = BASEPATH . &quot;application/views&quot;;
		log_message('debug', 'Classe Smarty Inicializada');
	}
}
?&gt;</pre>
<p>Esta classe que herda de Smarty, é utilizada apenas a nível de inicialização das variáveis necessárias pelo <em>framework</em>. Ela define a pasta onde os <em>templates</em> compilados serão salvos, a pasta onde os <em>templates</em> (arquivos de <em>View</em><span style="font-style: normal;">) estão</span> localizados e grava no <em>log</em> do CodeIgniter uma informação de que a classe Smarty foi inicializada. É necessária a criação de uma pasta chamada <strong>templates_c</strong> dentro de <strong>application/views</strong>, com permissões 0755, ou 0777.</p>
<p class="western">O segundo arquivo a ser criado é o arquivo de configurações para gerar uma instância da classe e marcá-la como inicializada. O arquivo é o <strong>smartyview.php</strong> localizado dentro de <strong>application/config</strong>, o código é o seguinte:</p>
<pre class="brush: php;">&lt;?php
if (!defined('BASEPATH')) die('Acesso direto ao script bloqueado.');
if (!class_exists('SmartyView'))
{
	require_once APPPATH . 'libraries/smartyview' . EXT;
}
$obj =&amp; get_instance();
$obj-&gt;smartyview = new SmartyView();
$obj-&gt;ci_is_loaded[] = 'smartyview';
?&gt;
</pre>
<p>Ele inclui a classe SmartyView, criada anteriormente, pega a instância do objeto atual do CodeIgniter (<em>Controller</em>), armazena uma instância da classe SmartyView na variável <strong>smartyview</strong> e a marca como instanciada nas variáveis de controle do CodeIgniter. Estes são os passos necessários para que o <em>framework</em> Smarty funcione no CodeIgniter.</p>
<p>Agora para testar se tudo está funcionando, basta ir no <em>controller</em> <strong>welcome.php</strong> localizado em <strong>application/controllers</strong>, e colocar o seguinte código nele:</p>
<pre class="brush: php;">&lt;?php
class Welcome extends Controller
{
	public function Welcome()
	{
		parent::Controller();
		$this-&gt;load-&gt;library('smartyview');
	}
	public function index()
	{
		$this-&gt;smartyview-&gt;assign('mensagem', 'Mensagem');
		$this-&gt;smartyview-&gt;display('index.tpl');
	}
}
?&gt;
</pre>
<p>Agora é necessário criar o arquivo <strong>application/views/index.tpl</strong> e colocar o seguinte conteúdo nele:</p>
<pre class="brush: xml;">&lt;html&gt;
	&lt;head&gt;
		&lt;title&gt;Arquitetura CI&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;h1&gt;{$mensagem}&lt;/h1&gt;
	&lt;/body&gt;
&lt;/html&gt;</pre>
<p>Se tudo der certo, basta acessar agora a URL definida na instalação do CodeIgniter, por exemplo http://localhost/codeigniter, e será exibida a mensagem “Mensagem”. Isto indica que o Smarty está funcionando perfeitamente, encerrando assim este artigo. No próximo artigo será feita a integração com o Doctrine, seguindo pela implementação da camada <em>Facade</em> e por algumas mudanças na nomenclatura dos <em>Controllers</em>. Até a próxima.</p>
<div id="_mcePaste" style="overflow: hidden; position: absolute; left: -10000px; top: 9px; width: 1px; height: 1px;">﻿</div>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-integrando-o-smarty/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Arquitetura de Software com CodeIgniter &#8211; Design Patterns</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-design-patterns/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-design-patterns/#comments</comments>
		<pubDate>Sun, 10 May 2009 23:59:32 +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[Frameworks]]></category>

		<guid isPermaLink="false">http://localhost/fernandomantoan/?p=5</guid>
		<description><![CDATA[Neste segundo artigo sobre uma proposta de arquitetura utilizando o framework CodeIgniter, falarei sobre os design patterns escolhidos para compor a arquitetura, mais especificamente os patterns que os programadores necessitarão implementar e não os patterns do CodeIgniter em si. Caso vocês tenham curiosidade em ver os Design Patterns que o CodeIgniter implementa, vejam este post, [...]]]></description>
			<content:encoded><![CDATA[<p>Neste segundo artigo sobre uma proposta de arquitetura utilizando o <em>framework</em> CodeIgniter, falarei sobre os <em>design patterns</em> escolhidos para compor a arquitetura, mais especificamente os <em>patterns</em> que os programadores necessitarão implementar e não os <em>patterns</em> do CodeIgniter em si. Caso vocês tenham curiosidade em ver os <em>Design Patterns</em> que o CodeIgniter implementa, vejam <a onclick="window.open(this.href); return false;" href="http://codeigniterbrasil.com/passos-iniciais/padroes-de-projeto-ou-design-patterns-o-que-sao-para-que-servem-e-qual-sua-implicacao-de-uso/">este post</a>, onde o autor fala especificamente sobre isso.</p>
<h2><em>Design Patterns</em> (Padrões de Projetos)</h2>
<p>Baseando-se no livro PHP Profissional, escrito por Alexandre Altair de Melo e Mauricio G. F., página 189, os <em>Design Patterns</em> podem ser definidos como sendo soluções para problemas comuns em diversos cenários no desenvolvimento de <em>software</em> onde cada padrão terá:</p>
<ul>
<li>
um nome, para que se possa descrever um problema de projeto, suas soluções e 	consequências em uma ou duas palavras;
</li>
<li>
uma descrição do 	problema, para se saber quando aplicar o padrão;
</li>
<li>
uma solução, 	onde serão descritos os elementos que compõem o projeto, seus 	relacionamentos, suas responsabilidades e colaborações;
</li>
<li>
as consequências como sendo os resultados, vantagens e desvantagens da aplicação do padrão.
</li>
</ul>
<h2><em>Design Patterns</em> escolhidos para a arquitetura</h2>
<p>Para a arquitetura proposta, será necessária a aplicação de alguns padrões para se obter uma maior organização de código, separando-se cada coisa em sua devida camada lógica, ganhando maior abstração em cada parte da aplicação. Existem alguns <em>patterns</em> que são fornecidos pelos <em>frameworks</em> escolhidos e outros que deverão ser implementados no CodeIgniter, para que ele ofereça um suporte &#8220;nativo&#8221; a eles. Os padrões que a arquitetura terá são:</p>
<ul>
<li>
<em><strong>Model-View-Controller</strong> </em></p>
<ul>
<li>
Não 	especificamente um padrão de projeto e mais um padrão 	arquitetural, é o padrão que prega a separação entre a regra de negócio (<em>model</em>) e a apresentação dos dados (<em>view</em>) da aplicação. Para que ambas as partes consigam se interligar, existe um controlador de fluxo da aplicação (<em>controller</em>) que será responsável por pegar dados do <em>model</em> e passar para a <em>view</em>, ou passar requisições da <em>view</em> para o <em>model</em>. Na arquitetura, o MVC já é fornecido pelo 	CodeIgniter e ganhou ainda mais abstração com o Smarty, que 	fornece uma <em>View</em> completamente sem código PHP. O <em>model</em> pode ser abstraído em 2 partes, uma para DAO e outra para o <em>Model</em> em si (representação dos dados do banco de dados), e as regras de negócio ficarão na camada <em>Facade</em>.
</li>
</ul>
</li>
<li>
<em><strong>Facade 	Pattern </strong></em></p>
<ul>
<li>
Um padrão de projeto bastante comum em aplicações Java e que se tornou bastante útil nessa arquitetura. Um <em>Facade pattern</em> tem como principal objetivo melhorar a legibilidade do código entre 		camadas, no caso da arquitetura, seria a legibilidade do <em>Controller</em> e do <em>Model</em>, agregando em seus métodos códigos com várias linhas e fornecendo métodos que serão comuns a várias outras partes da aplicação. No caso dessa arquitetura cada controller terá sua própria <em>Facade</em>, essa extendendo de uma <em>Facade</em> abstrata, devendo implementar alguns métodos que serão definidos nela. Essas <em>Facades</em> conterão regras de negócio, deixando o <em>Model</em> e o <em>Controller</em> um pouco mais &#8220;limpos&#8221; de código.
</li>
</ul>
</li>
<li>
<em><strong>Data Access 	Object</strong></em></p>
<ul>
<li>
O DAO não está entre um dos 23 <em>Design Patterns</em> definidos pela Gang of Four, porém está entre os patterns corporativos mais utilizados em aplicações no geral. O conceito dele é simples, fornecer um 	objeto onde se tenha apenas métodos de persistência. Na 	arquitetura o DAO irá trabalhar com o <em>Model</em><span style="font-style: normal;"> gerado pelo Doctrine, contendo métodos de acesso ao banco de 	dados.</span>
</li>
</ul>
</li>
</ul>
<p>Com os padrões de projetos definidos, no próximo artigo apresentarei as implementações necessárias para tornar cada padrão de projeto o mais integrado possível com o framework CodeIgniter e posteriormente desenvolverei uma aplicação para gestão de tarefas utilizando a arquitetura definida. Até a próxima.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-design-patterns/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Arquitetura de Software com CodeIgniter &#8211; Introdução</title>
		<link>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-introducao-2/</link>
		<comments>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-introducao-2/#comments</comments>
		<pubDate>Wed, 06 May 2009 12:37:50 +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[Frameworks]]></category>

		<guid isPermaLink="false">http://localhost/fernandomantoan/?p=4</guid>
		<description><![CDATA[Arquiteturas de desenvolvimento de software são essenciais para garantir a manutenibilidade e produtividade de qualquer sistema e, unindo-as com design patterns, que são soluções reutilizáveis a problemas comuns encontrados em projetos de software, pode-se ter uma estrutura bem definida e altamente reutilizável. Na linguagem PHP arquiteturas de software também são de extrema importância e esta [...]]]></description>
			<content:encoded><![CDATA[<p>Arquiteturas de desenvolvimento de <em>software</em> são essenciais para garantir a manutenibilidade e produtividade de qualquer sistema e, unindo-as com <em>design patterns,</em> que são soluções reutilizáveis a problemas comuns encontrados em projetos de <em>software,</em> pode-se ter uma estrutura bem definida e altamente reutilizável. Na linguagem PHP arquiteturas de <em>software</em> também são de extrema importância e esta série de artigos visa a definição de uma arquitetura de <em>software</em> baseada no <em>framework</em> CodeIgniter, onde serão abordados os passos necessários para se definir a arquitetura, com todos os <em>frameworks</em> escolhidos para compô-la, e ao final será feita a elaboração de um sistema de controle de tarefas, para exemplificar o uso da arquitetura.</p>
<h2><em>Frameworks</em> Escolhidos</h2>
<p>Um <em>framework</em> nada mais é do que uma estrutura de <em>software</em> que contém elementos comuns e não-específicos dos sistemas, componentes como <em>helpers</em> HTML, ferramentas de autenticação e validação e geradores de PDF. Seguindo o conceito de <em>Don&#8217;t Repeat Yourself</em> (DRY), que prega o reaproveitamento de estruturas já prontas para se trabalhar, os <em>frameworks</em> se tornaram essenciais nesta arquitetura, e unindo cada um deles pode-se fornecer uma ótima estrutura de trabalho. Estes <em>frameworks</em> escolhidos são:</p>
<ul>
<li><strong>CodeIgniter </strong>
<ul>
<li>O CodeIgniter foi 		 escolhido para fornecer as camadas MVC e o controle das 		requisições (front_controller, rotas etc.). Existiam outras 		escolhas como CakePHP ou ZendFramework, porém acredito que o mais 		fácil de aprender e o mais fácil de se extender e customizar é o 		CodeIgniter. A partir dele, algumas customizações foram feitas 		para manter URLs amigáveis e a <em>View</em> e o <em>Model</em> dele 		foram modificados, graças aos <em>frameworks</em> descritos abaixo.</li>
</ul>
</li>
<li><strong>Smarty </strong>
<ul>
<li>Smarty é um dos 		principais e mais robustos <em>frameworks</em> de <em>templates</em> para a linguagem PHP. Ele foi escolhido por conter uma sintaxe 		limpa e simples para as <em>Views</em>, por fornecer capacidades de 		cache (o CodeIgniter também provia isso para a <em>View</em> padrão 		dele) e por não conter uma linha de código PHP em seus templates. 		A partir de algumas configurações, ele é carregado por todos os 		<em>Controllers</em> que extenderem a classe &#8220;<em>Controller</em>&#8221; 		do CodeIgniter. Equipes que contenham 		<em>designers</em> ganham muitas vantagens ao utilizar o 		Smarty, pois eles necessitam apenas aprender a  		linguagem de <em>template</em> do Smarty, que é muito mais fácil do que o PHP em si, além de 		fornecer uma independência entre programadores e <em>designers</em>.</li>
</ul>
</li>
<li><strong>Doctrine </strong>
<ul>
<li>Doctrine é um framework para persistência 		de dados que se utiliza de mapeamento objeto relacional. Ele é o 		framework para PHP que mais se assemelha ao Hibernate do Java, e 		possui uma linguagem customizada para consultas, o que eles chamam 		de Doctrine Query Language (DQL). Existem ótimas soluções para 		persistência no PHP, como Lumine ou EZPDO, mas o Doctrine foi 		escolhido por possuir uma comunidade grande e ativa de 		desenvolvimento e pela robustez e consistência de suas 		funcionalidades. As classes <em>Models</em> que o Doctrine gera 		substituem o <em>Model</em> padrão do CodeIgniter.</li>
</ul>
</li>
</ul>
<p>A partir desses <em>frameworks</em>, o desenvolvimento das aplicações se mostrou mais ágil, prático e organizado, fornecendo com poucas configurações um método de desenvolvimento que pode ser utilizado em diversas aplicações pequenas e médias.</p>
<p>Isso encerra o artigo de hoje, no próximo artigo falarei sobre os <em>Design Patterns</em> que a arquitetura implementa, alguns já disponibilizados pelo CodeIgniter, outros customizados para se conseguir mais organização de código e uma maior abstração entre as camadas. Até mais.</p>
]]></content:encoded>
			<wfw:commentRss>http://fernandomantoan.com/php/arquitetura-de-desenvolvimento-de-aplicacoes-com-codeigniter-introducao-2/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
	</channel>
</rss>
