<?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>Robertson Freitas &#187; PHP</title>
	<atom:link href="http://blog.robertsonfreitas.com/category/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://blog.robertsonfreitas.com</link>
	<description>Produtividade, processos de desenvolvimento de software e PHP.</description>
	<lastBuildDate>Sun, 04 Apr 2010 21:19:21 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>Acessando a API do Google Analytics com GAPI e Flot</title>
		<link>http://blog.robertsonfreitas.com/2010/04/04/acessando-a-api-do-google-analytics-com-gapi-e-flot/</link>
		<comments>http://blog.robertsonfreitas.com/2010/04/04/acessando-a-api-do-google-analytics-com-gapi-e-flot/#comments</comments>
		<pubDate>Sun, 04 Apr 2010 20:26:57 +0000</pubDate>
		<dc:creator>Robertson Freitas</dc:creator>
				<category><![CDATA[Google Analytics]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.robertsonfreitas.com/?p=110</guid>
		<description><![CDATA[Recentemente precisei gerar relatórios personalizados a partir do Google Analytics e exibi-los em um gerenciador de conteúdo. Encontrei algumas ferramentas que facilitaram o acesso aos dados e sua exibição.
Criei um aplicativo simples para demonstrar o acesso à API do Google Analytics utilizando o GAPI (Google Analytics API PHP Interface) e a exibição desses dados com [...]]]></description>
			<content:encoded><![CDATA[<p>Recentemente precisei gerar relatórios personalizados a partir do <a title="Ir para Google Analytics" href="http://www.google.com/analytics/" target="_blank">Google Analytics</a> e exibi-los em um gerenciador de conteúdo. Encontrei algumas ferramentas que facilitaram o acesso aos dados e sua exibição.</p>
<p>Criei um aplicativo simples para demonstrar o acesso à API do Google Analytics utilizando o <a title="Ir para GAPI" href="http://code.google.com/p/gapi-google-analytics-php-interface/" target="_blank">GAPI</a> (Google Analytics API PHP Interface) e a exibição desses dados com a biblioteca de geração de gráficos <a title="Ir para Flot" href="http://code.google.com/p/flot/" target="_blank">Flot</a> para jQuery.</p>
<p>O aplicativo permite exibir as estatísticas mensais de um perfil existente no GA. Veja o resultado:</p>
<div id="attachment_112" class="wp-caption alignnone" style="width: 440px"><a href="http://blog.robertsonfreitas.com/wp-content/uploads/report2.jpg"><img class="size-full wp-image-112" title="Report Pequeno" src="http://blog.robertsonfreitas.com/wp-content/uploads/report1.jpg" alt="Gráfico gerado com Flot a partir de informações do GAPI" width="430" height="177" /></a><p class="wp-caption-text">Gráfico gerado com Flot a partir de informações do GAPI</p></div>
<p><span id="more-110"></span>O GAPI é uma poderosa biblioteca que simplifica o acesso à API do Google Analytics, executando tarefas como efetuar login, encontrar IDs dos perfis a que seu e-mail tem acesso, gerar relatórios, filtrar relatórios etc.</p>
<p>O Flot é uma biblioteca de geração de gráficos para jQuery. Com ela é possível gerar <a title="Veja exemplos de gráficos" href="http://people.iola.dk/olau/flot/examples/" target="_blank">vários tipos de gráficos</a> e incrementar o visual dos seus relatórios.</p>
<p>Veja o código fonte (<strong>report.php</strong>) (o conteúdo e os comentários estão em inglês para alcançar mais pessoas):</p>
<pre class="brush: php;">
&lt;?php

// Configurations
$initial_year = 2009; // sets the first year to show on select options
$ga_email = 'your_email@gmail.com'; // email with a google analytics account
$ga_password = 'your_password';

require_once(&quot;gapi.class.php&quot;);

// Authentication
$ga = new gapi($ga_email, $ga_password);

// Defines report period
$month = isset($_POST['month']) ? $_POST['month'] : date(&quot;m&quot;, mktime()); //actual month
$year = isset($_POST['year']) ? $_POST['year'] : date(&quot;Y&quot;, mktime()); // actual year

$begin = $year.'-'.$month.'-01';
$end = $year.'-'.$month.'-'.date(&quot;t&quot;, mktime(0, 0, 0, $month, 1, $year));

if (isset($_POST['id'])) {
// Gets total visits and pageviews
$ga-&gt;requestReportData($_POST['id'], 'month', array('pageviews', 'visits'), null, null, $begin, $end);
foreach ($ga-&gt;getResults() as $data) {
$total_visits = $data-&gt;getVisits();
$total_pageviews = $data-&gt;getPageviews();
}

// Gets selected month's visits and pageviews day by day
$ga-&gt;requestReportData($_POST['id'], 'day', array('pageviews', 'visits'), 'day', null, $begin, $end, 1, 50);
foreach ($ga-&gt;getResults() as $data) {
// creating Flot data
$d1 .= '['.$data.','.$data-&gt;getPageviews().'],';
$d2 .= '['.$data.','.$data-&gt;getVisits().'],';
}
}
?&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&gt;
&lt;head&gt;
&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
&lt;title&gt;Analytics Report&lt;/title&gt;
&lt;!--[if IE]&gt;&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;flot/excanvas.min.js&quot;&gt;&lt;/script&gt;&lt;![endif]--&gt;
&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;flot/jquery.js&quot;&gt;&lt;/script&gt;
&lt;script language=&quot;javascript&quot; type=&quot;text/javascript&quot; src=&quot;flot/jquery.flot.js&quot;&gt;&lt;/script&gt;
&lt;style&gt;
body {
background:#EEE;
font-family:sans-serif;
font-size:12px;
color: #666666;
}
&lt;/style&gt;
&lt;/head&gt;

&lt;body&gt;
&lt;form method=&quot;post&quot;&gt;
Statistics
&lt;select name=&quot;id&quot;&gt;
&lt;?php
// Gets accounts listing
$ga-&gt;requestAccountData();
foreach($ga-&gt;getResults() as $result) {
$selected = ($_POST['id'] == $result-&gt;getProfileId()) ? 'SELECTED' : '';
echo '&lt;option value=&quot;' . $result-&gt;getProfileId() . '&quot; ' . $selected . '&gt;' . $result . '&lt;/option&gt;';
}
?&gt;
&lt;/select&gt;
&lt;select name=&quot;month&quot;&gt;
&lt;option value=&quot;01&quot; &lt;?php if ($month == &quot;01&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;01&lt;/option&gt;
&lt;option value=&quot;02&quot; &lt;?php if ($month == &quot;02&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;02&lt;/option&gt;
&lt;option value=&quot;03&quot; &lt;?php if ($month == &quot;03&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;03&lt;/option&gt;
&lt;option value=&quot;04&quot; &lt;?php if ($month == &quot;04&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;04&lt;/option&gt;
&lt;option value=&quot;05&quot; &lt;?php if ($month == &quot;05&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;05&lt;/option&gt;
&lt;option value=&quot;06&quot; &lt;?php if ($month == &quot;06&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;06&lt;/option&gt;
&lt;option value=&quot;07&quot; &lt;?php if ($month == &quot;07&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;07&lt;/option&gt;
&lt;option value=&quot;08&quot; &lt;?php if ($month == &quot;08&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;08&lt;/option&gt;
&lt;option value=&quot;09&quot; &lt;?php if ($month == &quot;09&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;09&lt;/option&gt;
&lt;option value=&quot;10&quot; &lt;?php if ($month == &quot;10&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;10&lt;/option&gt;
&lt;option value=&quot;11&quot; &lt;?php if ($month == &quot;11&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;11&lt;/option&gt;
&lt;option value=&quot;12&quot; &lt;?php if ($month == &quot;12&quot;) echo &quot; SELECTED&quot;; ?&gt; &gt;12&lt;/option&gt;
&lt;/select&gt;
&lt;select name=&quot;year&quot;&gt;
&lt;?php
// Shows years from $initial_year to actual
for ($i=$initial_year; $i&lt;=date(&quot;Y&quot;, mktime()); $i++) {
$selected = ($i == $year) ? 'SELECTED' : '';
echo '&lt;option value=&quot;'.$i.'&quot;'.  $selected  .'&gt;'.$i.'&lt;/option&gt;';
}
?&gt;
&lt;/select&gt;
&lt;input type=&quot;submit&quot; value=&quot;ok&quot;&gt;
&lt;/form&gt;

&lt;?php if (isset($_POST['id'])) { ?&gt;

&lt;div id=&quot;placeholder&quot; style=&quot;width:800px;height:300px&quot;&gt;&lt;/div&gt;

&lt;script id=&quot;source&quot; language=&quot;javascript&quot; type=&quot;text/javascript&quot;&gt;
$(function () {

var d1 = [&lt;?php echo $d1; ?&gt;];
var d2 = [&lt;?php echo $d2; ?&gt;];

$.plot($(&quot;#placeholder&quot;),
[
{
data: d1,
lines: { show: true, fill: true },
points: { show: true, radius: 3 },
label: &quot;Pageviews (&lt;?php echo $total_pageviews; ?&gt;)&quot;
},
{
data: d2,
lines: { show: true, fill: true },
points: { show: true },
label: &quot;Visits (&lt;?php echo $total_visits; ?&gt;)&quot;
}
],
{
xaxis: {
ticks: 27
},
grid: {
backgroundColor: { colors: [&quot;#999&quot;, &quot;#BBB&quot;] }
}
}
);
});
&lt;/script&gt;
&lt;?php } ?&gt;
 &lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Antes de executar o script, lembre-se de configurar as variáveis <strong>$ga_email</strong> e <strong>$ga_password</strong> com dados de uma conta do Google Analytics válida.</p>
<p>Os arquivos compactados desse exemplo (report.php + GAPI + Flot) podem ser baixados <a title="Baixar arquivos (gapi.rar)" href="http://blog.robertsonfreitas.com/wp-content/uploads/gapi.rar" target="_self">aqui</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.robertsonfreitas.com/2010/04/04/acessando-a-api-do-google-analytics-com-gapi-e-flot/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>CRUD Básico com CodeIgniter 1.7.2</title>
		<link>http://blog.robertsonfreitas.com/2009/09/20/crud-basico-com-codeigniter-1-7-2/</link>
		<comments>http://blog.robertsonfreitas.com/2009/09/20/crud-basico-com-codeigniter-1-7-2/#comments</comments>
		<pubDate>Mon, 21 Sep 2009 01:35:52 +0000</pubDate>
		<dc:creator>Robertson Freitas</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://blog.robertsonfreitas.com/?p=98</guid>
		<description><![CDATA[For those who do not speak Portuguese,  you can see a working example here and download the source code here. The comments are in English.
Fiz algumas melhorias no código do post anterior:

A versão do CI foi atualizada. Este exemplo agora usa o CodeIgniter 1.7.2.
As configurações de layout da paginação foram transferidas para o lugar [...]]]></description>
			<content:encoded><![CDATA[<p><em><span style="color: #808080;">For those who do not speak Portuguese,  you can see a working example <a href="http://www.robertsonfreitas.com/ci_sandbox2/user" target="_blank">here</a> and download the source code <a href="http://www.robertsonfreitas.com/files/ci_sandbox2.rar" target="_blank">here</a>. The comments are in English.</span></em></p>
<p>Fiz algumas melhorias no código do <a title="CRUD Básico com CodeIgniter 1.7.1" href="http://blog.robertsonfreitas.com/2009/08/24/crud-basico-com-codeigniter/">post anterior</a>:</p>
<ul>
<li>A versão do CI foi atualizada. Este exemplo agora usa o CodeIgniter 1.7.2.</li>
<li>As configurações de layout da paginação foram transferidas para o lugar correto (<strong>config/pagination.php</strong>).</li>
<li>O uso da função <strong>set_value</strong> do Form helper, como sugerido no manual do CI, ajudou a enxugar o código do Controller.</li>
<li>Pequenos ajustes no método <strong>_save</strong> do Controller.</li>
<li>As pastas<strong> i</strong>, <strong>js</strong> e <strong>css</strong> foram movidas para dentro da nova pasta <strong>web</strong>, organizando os arquivos e eliminando a necessidade de manutenção nas excessões do .htaccess.</li>
<li>O profiler foi habilitado para exibir informações de performance da aplicação.</li>
</ul>
<p>Antes de continuar, veja o exemplo funcionando <a href="http://www.robertsonfreitas.com/ci_sandbox2/user" target="_blank">aqui</a>.</p>
<p>Disponibilizei o código fonte completo, junto com o codeigniter 1.7.2 e o script de criação do banco <a href="http://www.robertsonfreitas.com/files/ci_sandbox2.rar" target="_blank">aqui</a>.</p>
<p><span id="more-98"></span>Decidi deixar o conteúdo e os comentários em inglês para alcançar mais pessoas.</p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 1 &#8211; Criação do banco de dados</strong></span><strong> </strong></p>
<p>Execute o script abaixo (utilizando o <a href="http://www.google.com/url?sa=t&amp;source=web&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fwww.phpmyadmin.net%2F&amp;ei=DwSSSpDSO4-GlAfBpNClDA&amp;usg=AFQjCNEVUIHBxbZboIeYNUd_4abvz6M1zw" target="_blank">phpMyAdmin</a>, por exemplo) para criar o banco &#8220;<strong>ci_sandbox</strong>&#8220;, criar e popular a tabela &#8220;<strong>users</strong>&#8221; no MySQL 5. Note que estou utilizando codificação UTF-8, que vem configurada por padrão no CodeIgniter (no arquivo <strong>application/config/database.php</strong>).</p>
<pre class="brush: sql;">
CREATE DATABASE `ci_sandbox` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `users` (`id`, `name`, `email`) VALUES
(1, 'Bob', 'bob@bob.com'),
(2, 'Philip', 'philip@philip.com'),
(3, 'Paty', 'paty@paty.com'),
(4, 'Kelly', 'kelly@kelly.com'),
(5, 'Bill', 'bill@bill.com'),
(6, 'Tedd', 'tedd@tedd.com'),
(7, 'John', 'john@john.com'),
(8, 'Paul', 'paul@paul.com'),
(9, 'Anna', 'anna@anna.com'),
(10, 'Hellen', 'hellen@hellen.com'),
(11, 'Kate', 'kate@kate.com');
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 2 &#8211; Criação do CSS da aplicação</strong></span><strong> </strong></p>
<p>Veja abaixo a folha de estilo usada na listagem, paginação e mensagens (arquivo <strong>web/css/style.css</strong>):</p>
<pre class="brush: css;">
*{
	margin: 0;
	padding: 0;
}

body {
	background:#FFFFFF;
	font-family:verdana,arial,helvetica,sans-serif;
	font-size:10px;
	margin:2px;
	padding:2px;
}

#container h1 {
	color:#678197;
	border: 2px solid #E5EFF8;
	margin-bottom: 10px;
	padding: 5px;
	width: 686px;
	_width: 700px;
	background-color: #F2F6F7;
	font-size: 20px;
}

#listing {
	width:700px;
	color:#678197;
	font-family:verdana,arial,helvetica,sans-serif;
	font-size:8pt;
	border-spacing: 0px;
	border: 1px solid #E5EFF8;
}

#listing td {
	padding:5px;
	font-size:8pt;
	border: 1px solid #E5EFF8;
}
#listing th {
	color:#21497D;
	font-weight:bold;
	background:#F2F6F7;
	font-size:8pt;
	padding:5px;
	text-align: left;
	border: 1px solid #E5EFF8;
}

ul {
	border:0; margin:0; padding:0;
}

#pagination li {
	border:0; margin:0; padding:0;
	font-size:11px;
	list-style:none;
	float:left;
}

#pagination a {
	border:solid 1px #DDDDDD;
	margin-right:2px;
}

#pagination .previous-off, #pagination .next-off {
	color:#666666;
	display:block;
	float:left;
	font-weight:bold;
	padding:3px 4px;
}

#pagination .next a, #pagination .previous a {
	font-weight:bold;
	border:solid 1px #FFFFFF;
}

#pagination .active {
	color:#ff0084;
	font-weight:bold;
	display:block;
	float:left;
	padding:4px 6px;
}

#pagination a:link, #pagination a:visited {
	color:#678197;
	display:block;
	float:left;
	padding:3px 6px;
	text-decoration:none;
}

#pagination a:hover {
	border:solid 1px #666666;
}

.error_field {
	padding:5px;
	margin-bottom:3px;
	margin-top:3px;
	border: 1px solid red;
	background: yellow;
	width: 300px;
}

.footer_info {
	color:#6f8dA1;
}

/* Content Elements: Messages */

.message, .warning, .success, .error {
	width: 690px;
	_width: 700px;
	padding: 5px;
	margin-bottom: 3px;
	font-size: 12px;
}

.message {
	color: #ffffff;
	background-color: #aaa9a6;
}

.warning {
	color: #ffffff;
	background-color: #ff9900;
}

.success {
	color: #ffffff;
	background-color: #009000;
}

.error {
	color: #ffffff;
	background-color: #900000;
}
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 3 &#8211; Instalação da Library e do Helper Message</strong></span></p>
<p>Para facilitar o envio e a exibição de mensagens para o usuário, encontrei esta prática biblioteca chamada Message no Wiki (<a href="http://codeigniter.com/wiki/Messages/" target="_blank">confira</a>) do Codeigniter, e no fórum encontrei um Helper (<a href="http://codeigniter.com/forums/viewthread/84694/" target="_blank">confira</a>) para reduzir a exibição de código nas views.</p>
<p>Crie o arquivo <strong>application/libraries/messages.php</strong> com o conteúdo abaixo:</p>
<pre class="brush: php;">
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Message:: a class for writing feedback message information to the session
*
* Copyright 2006 Vijay Mahrra &amp;amp; Sheikh Ahmed &lt;webmaster@designbyfail.com&gt;
*
* See the enclosed file COPYING for license information (LGPL).  If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author  Vijay Mahrra &amp;amp; Sheikh Ahmed &lt;webmaster@designbyfail.com&gt;
* @url http://www.designbyfail.com/
* @version 1.0
*/

class Messages
{
    var $_ci;
    var $_types = array('success', 'error', 'warning', 'message');

    function Messages($params = array())
    {
        $this-&gt;_ci =&amp;amp; get_instance();
        $this-&gt;_ci-&gt;load-&gt;library('session');
        // check if theres already messages, if not, initialise the messages array in the session
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (empty($messages)) {
            $this-&gt;clear();
        }
    }

    // clear all messages
    function clear()
    {
        $messages = array();
        foreach ($this-&gt;_types as $type) {
            $messages[$type] = array();
        }
        $this-&gt;_ci-&gt;session-&gt;set_userdata('messages', $messages);
    }

    // add a message, default type is message
    function add($message, $type = 'message')
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        // handle PEAR errors gracefully
        if (is_a($message, 'PEAR_Error')) {
            $message = $message-&gt;getMessage();
            $type = 'error';
        } else if (!in_array($type, $this-&gt;_types)) {
            // set the type to message if the user specified a type that's unknown
            $type = 'message';
        }
        // don't repeat messages!
        if (!in_array($message, $messages[$type]) &amp;amp;&amp;amp; is_string($message)) {
            $messages[$type][] = $message;
        }
        $messages = $this-&gt;_ci-&gt;session-&gt;set_userdata('messages', $messages);
    }

    // return messages of given type or all types, return false if none
    function sum($type = null)
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (!empty($type)) {
            $i = count($messages[$type]);
            return $i;
        }
        $i = 0;
        foreach ($this-&gt;_types as $type) {
            $i += count($messages[$type]);
        }
        return $i;
    }

    // return messages of given type or all types, return false if none, clearing stack
    function get($type = null)
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (!empty($type)) {
            if (count($messages[$type]) == 0) {
                return false;
            }
            return $messages[$type];
        }
        // return false if there actually are no messages in the session
        $i = 0;
        foreach ($this-&gt;_types as $type) {
            $i += count($messages[$type]);
        }
        if ($i == 0) {
            return false;
        }

        // order return by order of type array above
        // i.e. success, error, warning and then informational messages last
        foreach ($this-&gt;_types as $type) {
            $return[$type] = $messages[$type];
        }
        $this-&gt;clear();
        return $return;
    }
}
</pre>
<p>Crie o arquivo <strong>application/helpers/msg_helper.php</strong> com o conteúdo abaixo:</p>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('output_msg')) {
    function output_msg($type = null) {
        $CI =&amp;amp; get_instance();

        if ($CI-&gt;messages-&gt;sum($type) &gt; 0) {
        $messages = $CI-&gt;messages-&gt;get($type);
        // display all messages of the type
        if (is_array($messages)) {
            $output = '';
            foreach ($messages as $type =&gt; $msgs) {
                if (count($msgs) &gt; 0) {
                    $output .= '&lt;div class=&amp;quot;' . $type . '&amp;quot;&gt;';
                    $output .= '&lt;ul&gt;';
                    foreach ($msgs as $message) {
                        $output .= $message;
                    }
                    $output .= '&lt;/ul&gt;';
                    $output .= '&lt;/div&gt;';
                }
            }
        }
        return $output;
        }
    }
}
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 4 &#8211; Criação do Model</strong></span></p>
<p>O model anêmico abaixo (que está mais para um Active Record Layer), incrivelmente reusável, foi <span style="text-decoration: line-through;">inspirado no</span> copiado deste <a href="http://henrihnr.wordpress.com/2009/04/26/simple-crud-application/" target="_blank">exemplo de CRUD</a>. Controller gordo + Model magro é considerado um anti-pattern, mas eu gosto que as coisas estejam distribuídas assim, e o CodeIgniter, pelo que vi no manual, também. (O que você acha?)</p>
<p>Arquivo <strong>application/models/user_model.php</strong></p>
<pre class="brush: php;">
&lt;?php
class User_model extends Model {

    private $table = 'users';

    function User_model() {
        parent::Model();
    }

    function list_all($order_by = 'id') {
        $this-&gt;db-&gt;order_by($order_by,'asc');
        return $this-&gt;db-&gt;get($table);
    }

    function count_all() {
        return $this-&gt;db-&gt;count_all($this-&gt;table);
    }

    function get_paged_list($limit = 10, $offset = 0, $order_by = 'id') {
        $this-&gt;db-&gt;order_by($order_by,'asc');
        return $this-&gt;db-&gt;get($this-&gt;table, $limit, $offset);
    }

    function get_by_id($id) {
        $this-&gt;db-&gt;where('id', $id);
        return $this-&gt;db-&gt;get($this-&gt;table);
    }

    function save($obj) {
        $this-&gt;db-&gt;insert($this-&gt;table, $obj);
        return $this-&gt;db-&gt;insert_id();
    }

    function update($id, $obj) {
        $this-&gt;db-&gt;where('id', $id);
        $this-&gt;db-&gt;update($this-&gt;table, $obj);
    }

    function delete($id) {
        $this-&gt;db-&gt;where('id', $id);
        $this-&gt;db-&gt;delete($this-&gt;table);
    }
}
?&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 5 &#8211; Criação da view para listagem</strong></span></p>
<p>Nesta view é exibida a listagem paginada. Note a simplicidade da exibição de mensagens através da função <strong>output_msg</strong>, do Helper que instalamos acima.</p>
<p>Arquivo <strong>application/views/user_list.php</strong></p>
<pre class="brush: php;">
&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;User List&lt;/title&gt;
	&lt;link href=&quot;&lt;?php echo base_url(); ?&gt;web/css/style.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
	&lt;script&gt;
		function remove(id) {
			if (confirm(&quot;Are you sure?&quot;)) {
				window.location = '&lt;?php echo base_url(); ?&gt;user/delete/'+id;
			}
		}
	&lt;/script&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;?php
	// show user messages sent by controller
	echo output_msg($type = null);
?&gt;
&lt;div id=&quot;container&quot;&gt;
	&lt;h1&gt;USER LIST&lt;/h1&gt;
	&lt;table id=&quot;listing&quot; cellspacing=0&gt;
		&lt;tr&gt;
			&lt;th width=45%&gt;Name&lt;/th&gt;
			&lt;th width=45%&gt;E-mail&lt;/th&gt;
			&lt;th width=10%&gt;Actions&lt;/th&gt;
		&lt;/tr&gt;
		&lt;?php foreach($list as $user): ?&gt;
			&lt;tr&gt;
				&lt;td&gt;&lt;?php echo $user-&gt;name; ?&gt;&lt;/td&gt;
				&lt;td&gt;&lt;?php echo $user-&gt;email; ?&gt;&lt;/td&gt;
				&lt;td align=&quot;center&quot;&gt;
					&lt;a href=&quot;&lt;?php echo base_url(); ?&gt;user/prepareUpdate/&lt;?php echo $user-&gt;id; ?&gt;&quot;&gt;&lt;img src=&quot;&lt;?php echo base_url(); ?&gt;web/i/icon/b_edit.png&quot; border=0 title=&quot;Edit&quot;&gt;&lt;/a&gt;
					&lt;a href=&quot;#&quot; onclick=&quot;remove(&lt;?php echo $user-&gt;id; ?&gt;);&quot;&gt;&lt;img src=&quot;&lt;?php echo base_url(); ?&gt;web/i/icon/b_drop.png&quot; border=0 title=&quot;Delete&quot;&gt;&lt;/a&gt;
				&lt;/td&gt;
			&lt;/tr&gt;
		&lt;?php endforeach ?&gt;
	&lt;/table&gt;
	&lt;div style=&quot;padding:10px;&quot;&gt;&lt;?php echo $pagination; ?&gt;&lt;br clear=&quot;all&quot; /&gt;&lt;/div&gt;
	&lt;input type=button onclick=&quot;location.href='&lt;?php echo base_url(); ?&gt;user/prepareInsert/';&quot; value=&quot;New User&quot; class=&quot;buttonAdmin&quot;&gt;
&lt;/div&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;p class=&quot;footer_info&quot;&gt;
	Total execution time: &lt;?php echo $this-&gt;benchmark-&gt;elapsed_time() ?&gt; seconds;
	Memory usage: &lt;?php echo $this-&gt;benchmark-&gt;memory_usage() ?&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 6 &#8211; Criação da view contendo o formulário de cadastro e edição</strong></span></p>
<p>Esta view contém o formulário que será exibido para criar e editar usuários. Observe o uso da função <strong>set_value()</strong> e da variável <strong>$values</strong>, que contém as informações para popular os campos com os dados do item.</p>
<p>Arquivo <strong>application/views/user_form.php</strong></p>
<pre class="brush: php;">
&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;&lt;?php echo $title; ?&gt;&lt;/title&gt;
	&lt;link href=&quot;&lt;?php echo base_url(); ?&gt;web/css/style.css&quot; rel=&quot;stylesheet&quot; type=&quot;text/css&quot; /&gt;
&lt;/head&gt;
&lt;body&gt;
&lt;?php
	// show user messages sent by controller
	echo output_msg($type = null);
?&gt;
&lt;form method=&quot;post&quot; action=&quot;&lt;?php echo $action; ?&gt;&quot;&gt;
	&lt;div id=&quot;container&quot;&gt;
		&lt;h1&gt;&lt;?php echo $title; ?&gt;&lt;/h1&gt;
				&lt;label&gt;Name*&lt;/label&gt;&lt;br&gt;
				&lt;input type=&quot;text&quot; name=&quot;name&quot; value=&quot;&lt;?php echo set_value('name', $values['name']); ?&gt;&quot; style=&quot;width:500px;&quot; maxlength=&quot;100&quot;&gt;
				&lt;?php echo form_error('name'); ?&gt;&lt;br&gt;&lt;br&gt;

				&lt;label&gt;E-mail*&lt;/label&gt;&lt;br&gt;
				&lt;input type=&quot;text&quot; name=&quot;email&quot; value=&quot;&lt;?php echo set_value('email', $values['email']); ?&gt;&quot; style=&quot;width:500px;&quot; maxlength=&quot;100&quot;&gt;
				&lt;?php echo form_error('email'); ?&gt;&lt;br&gt;&lt;br&gt;

				&lt;input type=submit value=&quot; Save &quot;&gt;

				&lt;input type=button onclick=&quot;location.href='&lt;?php echo base_url(); ?&gt;user/index/';&quot; value=&quot;Back to listing&quot; class=&quot;buttonAdmin&quot; style=&quot;margin-left:20px;&quot;&gt;
	&lt;/div&gt;
	&lt;input type=hidden name=id value=&quot;&lt;?php echo set_value('id', $values['id']); ?&gt;&quot;&gt;
&lt;/form&gt;
&lt;br /&gt;&lt;br /&gt;
&lt;p class=&quot;footer_info&quot;&gt;
	Total execution time: &lt;?php echo $this-&gt;benchmark-&gt;elapsed_time() ?&gt; seconds;
	Memory usage: &lt;?php echo $this-&gt;benchmark-&gt;memory_usage() ?&gt;
&lt;/p&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 7 &#8211; O Controller</strong></span></p>
<p>O controller começa com duas variáveis de configuração: quantidade de linhas exibidas por página na listagem (<strong>$limit</strong>) e nome da coluna que determinará a ordenação da listagem (<strong>$order_by</strong>).</p>
<p>No construtor, carregamos as libraries e helpers necessários.</p>
<p>Entenda o papel de cada método:</p>
<p>O <strong>index()</strong> prepara os dados da paginação, invoca os dados do modelo e transfere esses dados para a view <strong>user_list.php</strong>.</p>
<p>O <strong>prepareInsert()</strong> monta um formulário de cadastro em branco.</p>
<p>O <strong>prepareUpdate()</strong> consulta o modelo e monta um formulário preenchido com os dados do <strong>$id</strong> solicitado.</p>
<p>O <strong>insert()</strong> e o <strong>update()</strong> são apenas chamadas para o <strong>_save()</strong>. Foram criados assim para facilitar a visualização e compreensão do fluxo da aplicação.</p>
<p>O método privado <strong>_save()</strong> cria ou edita um item, de acordo com a <strong>$action</strong> solicitada. Nesse método são configuradas as regras de validação dos dados vindos do formulário.</p>
<p>O <strong>delete() </strong>exclui o item com o <strong>$id</strong> informado, e retorna para a listagem de usuários.</p>
<p>Arquivo <strong>application/controllers/user.php</strong></p>
<pre class="brush: php;">
&lt;?php
	class User extends Controller {

		// records per page
		private $limit = 5;

		// column to order by at listing
		private $order_by = 'name';

		function User()  {
			parent::Controller();

			$this-&gt;load-&gt;database();
			$this-&gt;load-&gt;library('form_validation');
			$this-&gt;load-&gt;helper('url');

			// send and show messages to user
			$this-&gt;load-&gt;library('messages');
			$this-&gt;load-&gt;helper('msg');

			$this-&gt;load-&gt;model('user_model', '', TRUE);

			$this-&gt;output-&gt;enable_profiler($this-&gt;config-&gt;item('profiler'));
		}

		function index($offset = 0) {
			$data = array();

			// http://.../ci_sandbox(1)/index(2)/&lt;offset&gt;(3)
			$uri_segment = 3;
			// where this page begins
			$offset = $this-&gt;uri-&gt;segment($uri_segment);
			// load data list
			$data['list'] = $this-&gt;user_model-&gt;get_paged_list($this-&gt;limit, $offset, $this-&gt;order_by)-&gt;result();

			// generate pagination
			$this-&gt;load-&gt;library('pagination');
			$config['base_url'] = site_url('user/index/');
	 		$config['total_rows'] = $this-&gt;user_model-&gt;count_all();
	 		$config['per_page'] = $this-&gt;limit;
			$config['uri_segment'] = $uri_segment;
			$this-&gt;pagination-&gt;initialize($config);
			$data['pagination'] = $this-&gt;pagination-&gt;create_links();

			$this-&gt;load-&gt;view('user_list',$data);
		}

		function prepareInsert() {
			// set validation properties
			$data['values'] = NULL;

			// set common properties
			$data['title'] = 'NEW USER';
			$data['action'] = site_url('user/insert');

			$this-&gt;load-&gt;view('user_form', $data);
		}

		function prepareUpdate($id) {
			// prefill form values
			$obj = $this-&gt;user_model-&gt;get_by_id($id)-&gt;row();
			$data['values']['id'] = $id;
			$data['values']['name'] = $obj-&gt;name;
			$data['values']['email'] = $obj-&gt;email;

			// set common properties
			$data['title'] = 'EDIT USER';
			$data['action'] = site_url('user/update');

			$this-&gt;load-&gt;view('user_form', $data);
		}

		function insert() {
			$this-&gt;_save('insert');
		}

		function update() {
			$this-&gt;_save('update');
		}

		function _save($action = 'insert') {
			// set common properties
			if ($action == 'update') {
				$data['title'] = 'EDIT USER';
				$data['action'] = site_url('user/update');
			} else {
				$data['title'] = 'NEW USER';
				$data['action'] = site_url('user/insert');
			}

			// set validation properties
			$this-&gt;form_validation-&gt;set_rules('id','','');
			$this-&gt;form_validation-&gt;set_rules('name','Name','trim|required|max_length[100]|xss_clean');
			$this-&gt;form_validation-&gt;set_rules('email','E-mail','trim|required|max_length[100]|valid_email|xss_clean');
			$this-&gt;form_validation-&gt;set_error_delimiters('&lt;p class=&quot;error_field&quot;&gt;', '&lt;/p&gt;');

			// run validation
			if ($this-&gt;form_validation-&gt;run() == FALSE) {
				$data['values'] = NULL;

				// set user message
				$this-&gt;messages-&gt;add('Important: please see the itens below.', 'warning');

				$this-&gt;load-&gt;view('user_form', $data);
			} else {

				$obj-&gt;name = $this-&gt;input-&gt;post('name');
				$obj-&gt;email = $this-&gt;input-&gt;post('email');

				if ($action == 'update') {
					$id = $this-&gt;input-&gt;post('id');
					$this-&gt;user_model-&gt;update($id, $obj);
					$this-&gt;messages-&gt;add('User updated', 'success'); // ser user message
				} else {
					$id = $this-&gt;user_model-&gt;save($obj);
					$this-&gt;messages-&gt;add('User created', 'success'); // set user message
				}

				// redirect to list page
				redirect('user/index/','refresh');
			}
		}

		function delete($id) {
			$this-&gt;user_model-&gt;delete($id);

			// set user message
			$this-&gt;messages-&gt;add('User removed', 'success');

			// redirect to list page
			redirect('user/index/','refresh');
		}

	}
?&gt;
</pre>
<p>Espero que esse exemplo simples seja útil para quem está iniciando, e que os mais experientes comentem e sugiram melhorias.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.robertsonfreitas.com/2009/09/20/crud-basico-com-codeigniter-1-7-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>CRUD Básico com CodeIgniter 1.7.1</title>
		<link>http://blog.robertsonfreitas.com/2009/08/24/crud-basico-com-codeigniter/</link>
		<comments>http://blog.robertsonfreitas.com/2009/08/24/crud-basico-com-codeigniter/#comments</comments>
		<pubDate>Mon, 24 Aug 2009 03:02:18 +0000</pubDate>
		<dc:creator>Robertson Freitas</dc:creator>
				<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[CRUD]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[Pagination]]></category>
		<category><![CDATA[Validation]]></category>

		<guid isPermaLink="false">http://blog.robertsonfreitas.com/?p=72</guid>
		<description><![CDATA[Atenção: existe uma atualização para este post: CRUD Básico com CodeIgniter 1.7.2
Estou há algumas semanas utilizando o framework PHP CodeIgniter. A documentação é incrível, muito detalhada e organizada, com muitos exemplos simples, porém poucos exemplos completos, voltados para o mundo real. Senti falta de modelos de CRUD completos, por exemplo.
Mesmo procurando em outros sites, blogs [...]]]></description>
			<content:encoded><![CDATA[<p><span style="color: #ff0000;"><em>Atenção: existe uma atualização para este post: </em><a href="http://blog.robertsonfreitas.com/2009/09/20/crud-basico-com-codeigniter-1-7-2/">CRUD Básico com CodeIgniter 1.7.2</a></span></p>
<p>Estou há algumas semanas utilizando o framework PHP <a href="http://codeigniter.com/" target="_blank">CodeIgniter</a>. A <a href="http://codeigniter.com/user_guide/" target="_blank">documentação</a> é incrível, muito detalhada e organizada, com muitos exemplos simples, porém poucos exemplos completos, voltados para o mundo real. Senti falta de modelos de CRUD completos, por exemplo.</p>
<p>Mesmo procurando em outros sites, blogs e fóruns, só vi implementações muito básicas, ou utilizando libraries antigas. O melhor que encontrei foi <a href="http://henrihnr.wordpress.com/2009/04/26/simple-crud-application/" target="_blank">este</a>, que usa uma versão anterior do CI (utiliza a classe Validation, que está <em>deprecated</em>). Baseado nesse exemplo, criei um outro modelo de CRUD com paginação, validação e um sistema de exibição de mensagens utilizando o CodeIgniter 1.7.1. É o exemplo que eu gostaria de ter visto quando comecei a conhecer o framework.</p>
<p>Antes de continuar, veja o exemplo funcionando <a href="http://www.robertsonfreitas.com/ci_sandbox/user" target="_blank">aqui</a>.</p>
<p>Disponibilizei o código fonte completo, junto com o codeigniter e o script de criação do banco <a href="http://www.robertsonfreitas.com/files/ci_sandbox.rar" target="_blank">aqui</a>.</p>
<p><span id="more-72"></span>Decidi deixar o conteúdo e os comentários em inglês para alcançar mais pessoas.</p>
<p><strong> </strong></p>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 1 &#8211; Criação do banco de dados</strong></span><strong> </strong></p>
<p>Execute o script abaixo (utilizando o <a href="http://www.google.com/url?sa=t&amp;source=web&amp;ct=res&amp;cd=1&amp;url=http%3A%2F%2Fwww.phpmyadmin.net%2F&amp;ei=DwSSSpDSO4-GlAfBpNClDA&amp;usg=AFQjCNEVUIHBxbZboIeYNUd_4abvz6M1zw" target="_blank">phpMyAdmin</a>, por exemplo) para criar o banco &#8220;<strong>ci_sandbox</strong>&#8220;, criar e popular a tabela &#8220;<strong>users</strong>&#8221; no MySQL 5. Note que estou utilizando codificação UTF-8, que vem configurada por padrão no CodeIgniter (no arquivo <strong>application/config/database.php</strong>).</p>
<pre class="brush: sql;">
CREATE DATABASE `ci_sandbox` DEFAULT CHARACTER SET utf8 COLLATE utf8_general_ci;

CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL auto_increment,
  `name` varchar(100) NOT NULL,
  `email` varchar(100) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

INSERT INTO `users` (`id`, `name`, `email`) VALUES
(1, 'Bob', 'bob@bob.com'),
(2, 'Philip', 'philip@philip.com'),
(3, 'Paty', 'paty@paty.com'),
(4, 'Kelly', 'kelly@kelly.com'),
(5, 'Bill', 'bill@bill.com'),
(6, 'Tedd', 'tedd@tedd.com'),
(7, 'John', 'john@john.com'),
(8, 'Paul', 'paul@paul.com'),
(9, 'Anna', 'anna@anna.com'),
(10, 'Hellen', 'hellen@hellen.com'),
(11, 'Kate', 'kate@kate.com');
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 2 &#8211; Criação do CSS da aplicação</strong></span><strong> </strong></p>
<p>Veja abaixo a folha de estilo usada na listagem, paginação e mensagens (arquivo <strong>css/style.css</strong>):</p>
<pre class="brush: css;">
*{
    margin: 0;
    padding: 0;
}

body {
    background:#FFFFFF;
    font-family:verdana,arial,helvetica,sans-serif;
    font-size:10px;
    margin:2px;
    padding:2px;
}

#container h1 {
    color:#678197;
    border: 2px solid #E5EFF8;
    margin-bottom: 10px;
    padding: 5px;
    width: 686px;
    _width: 700px;
    background-color: #F2F6F7;
    font-size: 20px;
}

#listing {
    width:700px;
    color:#678197;
    font-family:verdana,arial,helvetica,sans-serif;
    font-size:8pt;
    border-spacing: 0px;
    border: 1px solid #E5EFF8;
}

#listing td {
    padding:5px;
    font-size:8pt;
    border: 1px solid #E5EFF8;
}
#listing th {
    color:#21497D;
    font-weight:bold;
    background:#F2F6F7;
    font-size:8pt;
    padding:5px;
    text-align: left;
    border: 1px solid #E5EFF8;
}

ul {
    border:0; margin:0; padding:0;
}

#pagination li {
    border:0; margin:0; padding:0;
    font-size:11px;
    list-style:none;
    float:left;
}

#pagination a {
    border:solid 1px #DDDDDD;
    margin-right:2px;
}

#pagination .previous-off, #pagination .next-off {
    color:#666666;
    display:block;
    float:left;
    font-weight:bold;
    padding:3px 4px;
}

#pagination .next a, #pagination .previous a {
    font-weight:bold;
    border:solid 1px #FFFFFF;
}

#pagination .active {
    color:#ff0084;
    font-weight:bold;
    display:block;
    float:left;
    padding:4px 6px;
}

#pagination a:link, #pagination a:visited {
    color:#678197;
    display:block;
    float:left;
    padding:3px 6px;
    text-decoration:none;
}

#pagination a:hover {
    border:solid 1px #666666;
}

.error_field {
    padding:5px;
    margin-bottom:3px;
    margin-top:3px;
    border: 1px solid red;
    background: yellow;
    width: 300px;
}

/* Content Elements: Messages */

.message, .warning, .success, .error {
    width: 690px;
    _width: 700px;
    padding: 5px;
    margin-bottom: 3px;
    font-size: 12px;
}

.message {
    color: #ffffff;
    background-color: #aaa9a6;
}

.warning {
    color: #ffffff;
    background-color: #ff9900;
}

.success {
    color: #ffffff;
    background-color: #009000;
}

.error {
    color: #ffffff;
    background-color: #900000;
}
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 3 &#8211; Instalação da Library e do Helper Message</strong></span></p>
<p>Para facilitar o envio e a exibição de mensagens para o usuário, encontrei esta prática biblioteca chamada Message no Wiki (<a href="http://codeigniter.com/wiki/Messages/" target="_blank">confira</a>) do Codeigniter, e no fórum encontrei um Helper (<a href="http://codeigniter.com/forums/viewthread/84694/" target="_blank">confira</a>) para reduzir a exibição de código nas views.</p>
<p>Crie o arquivo <strong>application/libraries/messages.php</strong> com o conteúdo abaixo:</p>
<pre class="brush: php;">
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');

/**
* Message:: a class for writing feedback message information to the session
*
* Copyright 2006 Vijay Mahrra &amp;amp; Sheikh Ahmed &lt;webmaster@designbyfail.com&gt;
*
* See the enclosed file COPYING for license information (LGPL).  If you
* did not receive this file, see http://www.fsf.org/copyleft/lgpl.html.
*
* @author  Vijay Mahrra &amp;amp; Sheikh Ahmed &lt;webmaster@designbyfail.com&gt;
* @url http://www.designbyfail.com/
* @version 1.0
*/

class Messages
{
    var $_ci;
    var $_types = array('success', 'error', 'warning', 'message');

    function Messages($params = array())
    {
        $this-&gt;_ci =&amp;amp; get_instance();
        $this-&gt;_ci-&gt;load-&gt;library('session');
        // check if theres already messages, if not, initialise the messages array in the session
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (empty($messages)) {
            $this-&gt;clear();
        }
    }

    // clear all messages
    function clear()
    {
        $messages = array();
        foreach ($this-&gt;_types as $type) {
            $messages[$type] = array();
        }
        $this-&gt;_ci-&gt;session-&gt;set_userdata('messages', $messages);
    }

    // add a message, default type is message
    function add($message, $type = 'message')
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        // handle PEAR errors gracefully
        if (is_a($message, 'PEAR_Error')) {
            $message = $message-&gt;getMessage();
            $type = 'error';
        } else if (!in_array($type, $this-&gt;_types)) {
            // set the type to message if the user specified a type that's unknown
            $type = 'message';
        }
        // don't repeat messages!
        if (!in_array($message, $messages[$type]) &amp;amp;&amp;amp; is_string($message)) {
            $messages[$type][] = $message;
        }
        $messages = $this-&gt;_ci-&gt;session-&gt;set_userdata('messages', $messages);
    }

    // return messages of given type or all types, return false if none
    function sum($type = null)
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (!empty($type)) {
            $i = count($messages[$type]);
            return $i;
        }
        $i = 0;
        foreach ($this-&gt;_types as $type) {
            $i += count($messages[$type]);
        }
        return $i;
    }

    // return messages of given type or all types, return false if none, clearing stack
    function get($type = null)
    {
        $messages = $this-&gt;_ci-&gt;session-&gt;userdata('messages');
        if (!empty($type)) {
            if (count($messages[$type]) == 0) {
                return false;
            }
            return $messages[$type];
        }
        // return false if there actually are no messages in the session
        $i = 0;
        foreach ($this-&gt;_types as $type) {
            $i += count($messages[$type]);
        }
        if ($i == 0) {
            return false;
        }

        // order return by order of type array above
        // i.e. success, error, warning and then informational messages last
        foreach ($this-&gt;_types as $type) {
            $return[$type] = $messages[$type];
        }
        $this-&gt;clear();
        return $return;
    }
}
</pre>
<p>Crie o arquivo <strong>application/helpers/msg_helper.php</strong> com o conteúdo abaixo:</p>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('output_msg')) {
    function output_msg($type = null) {
        $CI =&amp;amp; get_instance();

        if ($CI-&gt;messages-&gt;sum($type) &gt; 0) {
        $messages = $CI-&gt;messages-&gt;get($type);
        // display all messages of the type
        if (is_array($messages)) {
            $output = '';
            foreach ($messages as $type =&gt; $msgs) {
                if (count($msgs) &gt; 0) {
                    $output .= '&lt;div class=&amp;quot;' . $type . '&amp;quot;&gt;';
                    $output .= '&lt;ul&gt;';
                    foreach ($msgs as $message) {
                        $output .= $message;
                    }
                    $output .= '&lt;/ul&gt;';
                    $output .= '&lt;/div&gt;';
                }
            }
        }
        return $output;
        }
    }
}
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 4 &#8211; Criação do Model</strong></span></p>
<p>O model anêmico abaixo (que está mais para um Active Record Layer), incrivelmente reusável, foi <span style="text-decoration: line-through;">inspirado no</span> copiado do <a href="http://henrihnr.wordpress.com/2009/04/26/simple-crud-application/" target="_blank">exemplo de CRUD</a> que mencionei acima. Controller gordo + Model magro é considerado um anti-pattern, mas eu gosto que as coisas estejam distribuídas assim, e o CodeIgniter, pelo que vi no manual, também. (O que você acha?)</p>
<p>Arquivo <strong>application/models/user_model.php</strong></p>
<pre class="brush: php;">
&lt;?php
class User_model extends Model {

    private $table = 'users';

    function User_model() {
        parent::Model();
    }

    function list_all($order_by = 'id') {
        $this-&gt;db-&gt;order_by($order_by,'asc');
        return $this-&gt;db-&gt;get($table);
    }

    function count_all() {
        return $this-&gt;db-&gt;count_all($this-&gt;table);
    }

    function get_paged_list($limit = 10, $offset = 0, $order_by = 'id') {
        $this-&gt;db-&gt;order_by($order_by,'asc');
        return $this-&gt;db-&gt;get($this-&gt;table, $limit, $offset);
    }

    function get_by_id($id) {
        $this-&gt;db-&gt;where('id', $id);
        return $this-&gt;db-&gt;get($this-&gt;table);
    }

    function save($obj) {
        $this-&gt;db-&gt;insert($this-&gt;table, $obj);
        return $this-&gt;db-&gt;insert_id();
    }

    function update($id, $obj) {
        $this-&gt;db-&gt;where('id', $id);
        $this-&gt;db-&gt;update($this-&gt;table, $obj);
    }

    function delete($id) {
        $this-&gt;db-&gt;where('id', $id);
        $this-&gt;db-&gt;delete($this-&gt;table);
    }
}
?&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 5 &#8211; Criação da view para listagem</strong></span></p>
<p>Nesta view é exibida a listagem paginada. Note a simplicidade da exibição de mensagens através da função <strong>output_msg</strong>, do Helper que instalamos acima.</p>
<p>Arquivo <strong>application/views/user_list.php</strong></p>
<pre class="brush: php;">
&lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&gt;
&lt;head&gt;
    &lt;meta http-equiv=&amp;quot;content-type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&gt;
    &lt;title&gt;User List&lt;/title&gt;
    &lt;link href=&amp;quot;&lt;?php echo base_url(); ?&gt;css/style.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; /&gt;
    &lt;script&gt;
        function remove(id) {
            if (confirm(&amp;quot;Are you sure?&amp;quot;)) {
                window.location = '&lt;?php echo base_url(); ?&gt;user/delete/'+id;
            }
        }
    &lt;/script&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;?php
    // show user messages sent by controller
    echo output_msg($type = null);
?&gt;

&lt;div id=&amp;quot;container&amp;quot;&gt;
    &lt;h1&gt;USER LIST&lt;/h1&gt;
    &lt;table id=&amp;quot;listing&amp;quot; cellspacing=0&gt;
        &lt;tr&gt;
            &lt;th width=45%&gt;Name&lt;/th&gt;
            &lt;th width=45%&gt;E-mail&lt;/th&gt;
            &lt;th width=10%&gt;Actions&lt;/th&gt;
        &lt;/tr&gt;
        &lt;?php foreach($list as $user): ?&gt;
            &lt;tr&gt;
                &lt;td&gt;&lt;?php echo $user-&gt;name; ?&gt;&lt;/td&gt;
                &lt;td&gt;&lt;?php echo $user-&gt;email; ?&gt;&lt;/td&gt;
                &lt;td align=&amp;quot;center&amp;quot;&gt;
                    &lt;a href=&amp;quot;&lt;?php echo base_url(); ?&gt;user/prepareUpdate/&lt;?php echo $user-&gt;id; ?&gt;&amp;quot;&gt;&lt;img src=&amp;quot;&lt;?php echo base_url(); ?&gt;i/icon/b_edit.png&amp;quot; border=0 title=&amp;quot;Edit&amp;quot;&gt;&lt;/a&gt;
                    &lt;a href=&amp;quot;#&amp;quot; onclick=&amp;quot;remove(&lt;?php echo $user-&gt;id; ?&gt;);&amp;quot;&gt;&lt;img src=&amp;quot;&lt;?php echo base_url(); ?&gt;i/icon/b_drop.png&amp;quot; border=0 title=&amp;quot;Delete&amp;quot;&gt;&lt;/a&gt;
                &lt;/td&gt;
            &lt;/tr&gt;
        &lt;?php endforeach ?&gt;
    &lt;/table&gt;
    &lt;div style=&amp;quot;padding:10px;&amp;quot;&gt;&lt;?php echo $pagination; ?&gt;&lt;br clear=&amp;quot;all&amp;quot; /&gt;&lt;/div&gt;
    &lt;input type=button onclick=&amp;quot;location.href='&lt;?php echo base_url(); ?&gt;user/prepareInsert/';&amp;quot; value=&amp;quot;New User&amp;quot;&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 6 &#8211; Criação da view contendo o formulário de cadastro e edição</strong></span></p>
<p>Esta view contém o formulário que será exibido para criar e editar usuários. Observe o uso da variável <strong>$values</strong>, que contém as informações para popular os campos com os dados do item.</p>
<p>Arquivo <strong>application/views/user_form.php</strong></p>
<pre class="brush: php;">
&lt;html xmlns=&amp;quot;http://www.w3.org/1999/xhtml&amp;quot;&gt;
&lt;head&gt;
    &lt;meta http-equiv=&amp;quot;content-type&amp;quot; content=&amp;quot;text/html; charset=utf-8&amp;quot; /&gt;
    &lt;title&gt;&lt;?php echo $title; ?&gt;&lt;/title&gt;
    &lt;link href=&amp;quot;&lt;?php echo base_url(); ?&gt;css/style.css&amp;quot; rel=&amp;quot;stylesheet&amp;quot; type=&amp;quot;text/css&amp;quot; /&gt;
&lt;/head&gt;

&lt;body&gt;

&lt;?php
    // show user messages sent by controller
    echo output_msg($type = null);
?&gt;

&lt;form method=&amp;quot;post&amp;quot; action=&amp;quot;&lt;?php echo $action; ?&gt;&amp;quot;&gt;
    &lt;div id=&amp;quot;container&amp;quot;&gt;
        &lt;h1&gt;&lt;?php echo $title; ?&gt;&lt;/h1&gt;
                &lt;label&gt;Name*&lt;/label&gt;&lt;br&gt;
                &lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;name&amp;quot; value=&amp;quot;&lt;?php echo $values['name']; ?&gt;&amp;quot; style=&amp;quot;width:500px;&amp;quot; maxlength=&amp;quot;100&amp;quot;&gt;
                &lt;?php echo form_error('name'); ?&gt;&lt;br&gt;&lt;br&gt;

                &lt;label&gt;E-mail*&lt;/label&gt;&lt;br&gt;
                &lt;input type=&amp;quot;text&amp;quot; name=&amp;quot;email&amp;quot; value=&amp;quot;&lt;?php echo $values['email']; ?&gt;&amp;quot; style=&amp;quot;width:500px;&amp;quot; maxlength=&amp;quot;100&amp;quot;&gt;
                &lt;?php echo form_error('email'); ?&gt;&lt;br&gt;&lt;br&gt;

                &lt;input type=submit value=&amp;quot; Save &amp;quot;&gt;

                &lt;input type=button onclick=&amp;quot;location.href='&lt;?php echo base_url(); ?&gt;user/index/';&amp;quot; value=&amp;quot;Back to listing&amp;quot; style=&amp;quot;margin-left:20px;&amp;quot;&gt;
    &lt;/div&gt;
    &lt;input type=hidden name=id value=&amp;quot;&lt;?php echo $values['id']; ?&gt;&amp;quot;&gt;
&lt;/form&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong> </strong></p>
<p><span style="color: #333399;"><strong>Passo 7 &#8211; O Controller</strong></span></p>
<p>O controller começa com duas variáveis de configuração: quantidade de linhas exibidas por página na listagem (<strong>$limit</strong>) e nome da coluna que determinará a ordenação da listagem (<strong>$order_by</strong>).</p>
<p>No construtor, carregamos as libraries e helpers necessários.</p>
<p>Confira o papel de cada método:</p>
<p>O <strong>index()</strong> prepara os dados da paginação, invoca os dados do modelo e transfere esses dados para a view <strong>user_list.php</strong>.</p>
<p>O <strong>prepareInsert()</strong> monta um formulário de cadastro em branco.</p>
<p>O <strong>prepareUpdate()</strong> consulta o modelo e monta um formulário preenchido com os dados do <strong>$id</strong> solicitado.</p>
<p>O <strong>insert()</strong> e o <strong>update()</strong> são apenas chamadas para o <strong>_save()</strong>. Foram criados assim para facilitar a visualização e compreensão do fluxo da aplicação.</p>
<p>O método privado <strong>_save()</strong> cria ou edita um item, de acordo com a <strong>$action</strong> solicitada. Nesse método são configuradas as regras de validação dos dados vindos do formulário.</p>
<p>O <strong>delete() </strong>exclui o item com o <strong>$id</strong> informado, e retorna para a listagem de usuários.</p>
<p>Arquivo <strong>application/controllers/user.php</strong></p>
<pre class="brush: php;">
&lt;?php
    class User extends Controller {

        // records per page
        private $limit = 5;

        // column to order by at listing
        private $order_by = 'name';

        function User()  {
            parent::Controller();

            $this-&gt;load-&gt;database();
            $this-&gt;load-&gt;library('form_validation');
            $this-&gt;load-&gt;helper('url');

            // send and show messages to user
            $this-&gt;load-&gt;library('messages');
            $this-&gt;load-&gt;helper('msg');

            $this-&gt;load-&gt;model('user_model', '', TRUE);
        }

        function index($offset = 0) {
            $data = array();

            // http://localhost/ci_sandbox/index/(offset)
            $uri_segment = 3;
            // where this page begins
            $offset = $this-&gt;uri-&gt;segment($uri_segment);

            // load data list
            $data['list'] = $this-&gt;user_model-&gt;get_paged_list($this-&gt;limit, $offset, $this-&gt;order_by)-&gt;result();

            // generate pagination
            $this-&gt;load-&gt;library('pagination');
            $config['base_url'] = site_url('user/index/');
             $config['total_rows'] = $this-&gt;user_model-&gt;count_all();
             $config['per_page'] = $this-&gt;limit;
            $config['uri_segment'] = $uri_segment;
            $this-&gt;pagination-&gt;initialize($config);
            $data['pagination'] = $this-&gt;pagination-&gt;create_links();

            $this-&gt;load-&gt;view('user_list',$data);

        }

        function prepareInsert() {
            // set validation properties
            $data['values']['id'] = '';
            $data['values']['name'] = '';
            $data['values']['email'] = '';

            // set common properties
            $data['title'] = 'NEW USER';
            $data['action'] = site_url('user/insert');

            $this-&gt;load-&gt;view('user_form', $data);
        }

        function prepareUpdate($id) {

            // prefill form values
            $obj = $this-&gt;user_model-&gt;get_by_id($id)-&gt;row();
            $data['values']['id'] = $id;
            $data['values']['name'] = $obj-&gt;name;
            $data['values']['email'] = $obj-&gt;email;

            // set common properties
            $data['title'] = 'EDIT USER';
            $data['action'] = site_url('user/update');

            $this-&gt;load-&gt;view('user_form', $data);
        }

        function insert() {
            $this-&gt;_save('insert');
        }

        function update() {
            $this-&gt;_save('update');
        }

        function _save($action = 'insert') {
            // set common properties
            if ($action == 'update') {
                $data['title'] = 'EDIT USER';
                $data['action'] = site_url('user/update');
            } else {
                $data['title'] = 'NEW USER';
                $data['action'] = site_url('user/insert');
            }

            // set validation properties
            $this-&gt;form_validation-&gt;set_rules('id','','');
            $this-&gt;form_validation-&gt;set_rules('name','Name','trim|required|max_length[100]|xss_clean');
            $this-&gt;form_validation-&gt;set_rules('email','E-mail','trim|required|max_length[100]|valid_email|xss_clean');
            $this-&gt;form_validation-&gt;set_error_delimiters('&lt;p class=&amp;quot;error_field&amp;quot;&gt;', '&lt;/p&gt;');

            // run validation
            if ($this-&gt;form_validation-&gt;run() == FALSE) {
                $data['values']['name'] = set_value('name');
                $data['values']['email'] = set_value('email');
                $data['values']['id'] = set_value('id');

                $this-&gt;load-&gt;view('user_form', $data);
            } else {
                // save data
                if ($action == 'update') {
                    $id = $this-&gt;input-&gt;post('id');
                }
                $obj = array(
                    'name' =&gt; $this-&gt;input-&gt;post('name'),
                    'email' =&gt; $this-&gt;input-&gt;post('email')
                );
                if ($action == 'update') {
                    $this-&gt;user_model-&gt;update($id, $obj);
                } else {
                    $id = $this-&gt;user_model-&gt;save($obj);
                }

                // set user message
                if ($action == 'update') {
                    $this-&gt;messages-&gt;add('User updated', 'success');
                } else {
                    $this-&gt;messages-&gt;add('User created', 'success');
                }

                // redirect to list page
                redirect('user/index/','refresh');
            }

        }

        function delete($id) {
            $this-&gt;user_model-&gt;delete($id);

            // set user message
            $this-&gt;messages-&gt;add('User removed', 'success');

            // redirect to list page
            redirect('user/index/','refresh');
        }

    }
?&gt;
</pre>
<p>Espero que esse exemplo simples seja útil para quem está iniciando, e que os mais experientes comentem e sugiram melhorias.</p>
]]></content:encoded>
			<wfw:commentRss>http://blog.robertsonfreitas.com/2009/08/24/crud-basico-com-codeigniter/feed/</wfw:commentRss>
		<slash:comments>9</slash:comments>
		</item>
	</channel>
</rss>
