segunda-feira, outubro 11, 2010

Tutorial CodeIgniter - Parte 5

Vamos finalizar a nossa aplicação desenvolvendo o CRUD para a tabela rio, grande parte do código utilizado nas postagens anteriores será reutilizado.

Vamos começar com o rio_model.php:

<?php
class Rio_model extends CI_Model
{

    function __construct()
    {
        parent::__construct();
    }

    function get_rio()
    {
        $this->db->order_by('nome_rio', 'asc');
        //junção com a tabela bacia_hidrografica
        $this->db->join('bacia_hidrografica', 'bacia_hidrografica.id_bacia = rio.id_bacia');
        $query = $this->db->get('rio');
        if ($query->num_rows() > 0)
        {
            return $query->result();
        }
        else
        {
            return false;
        }
    }

    function insert()
    {
        $data = $_POST;
        return $this->db->insert('rio', $data);
    }

    function get_where($id)
    {
        $this->db->where('id_rio', $id);
        $this->db->join('bacia_hidrografica', 'bacia_hidrografica.id_bacia = rio.id_bacia');
        $query = $this->db->get('rio');
        return $query->row();
    }

    function update($id)
    {
        $data = $_POST;
        $this->db->where('id_rio', $id);
        $this->db->update('rio', $data);
    }

    function delete($id)
    {
        $this->db->where('id_rio', $id);
        return $this->db->delete('rio');
    }

}

O nosso controllador rio.php vai carregar dois model´s, já que teremos nos formulários de inserção e de atualização uma lista das bacias cadastradas:

<?php

class Rio extends CI_Controller
{

    function __construct()
    {
        parent::__construct();
        $this->load->model(array('rio_model', 'bacia_model'));
        $this->load->library('form_validation');
    }

    function index()
    {
        $data['titulo'] = "SIRH";
        $data['cabecalho'] = "Rios";

        $data['rios'] = $this->rio_model->get_rio();

        $this->load->view('rio_view', $data);
    }

    function criar()
    {
        $data['titulo'] = "SIRH - Novo Rio";
        $data['cabecalho'] = "Criar novo Rio";

        $data['bacias'] = $this->bacia_model->get_bacia();

        $this->load->view('rio_new', $data);
    }

    function insere()
    {

        $data['titulo'] = "SIRH - Novo Rio | Erro na Validação, preencha corretamente!";
        $data['cabecalho'] = "Criar novo Rio | Preencha Corretamente!";

        $data['bacias'] = $this->bacia_model->get_bacia();

        $this->form_validation->set_rules('nome_rio', 'Nome do Rio', 'required|alpha');
        $this->form_validation->set_rules('comprimento_km', 'Comprimento', 'required|numeric');
        $this->form_validation->set_rules('id_bacia', 'Bacia Hidrográfica', 'required');

        if ($this->form_validation->run() == FALSE)
        {
            $this->load->view('rio_new', $data);
        }
        else
        {
            $this->rio_model->insert();
            $this->session->set_flashdata('msg', 'Registro Criado com Sucesso!');
            redirect('rio');
        }
    }

    function editar($id)
    {
        $data['titulo'] = "SIRH - Editar Rio";
        $data['cabecalho'] = "Editar Rio";

        $data['registro'] = $this->rio_model->get_where($id);

        $data['bacias'] = $this->bacia_model->get_bacia();

        $this->load->view('rio_new', $data);
    }

    function atualizar()
    {
        $id = $this->input->post('id_rio');

        $data['titulo'] = "SIRH - Editar Rio | Erro na Validação, preencha corretamente!";
        $data['cabecalho'] = "Editar Rio | Preencha Corretamente!";

        $data['registro'] = $this->rio_model->get_where($id);

        $data['bacias'] = $this->bacia_model->get_bacia();

        $this->form_validation->set_rules('nome_rio', 'Nome do Rio', 'required|alpha');
        $this->form_validation->set_rules('comprimento_km', 'Comprimento', 'required|numeric');
        $this->form_validation->set_rules('id_bacia', 'Bacia Hidrográfica', 'required');

        if ($this->form_validation->run() == FALSE)
        {
            $this->load->view('rio_new', $data);
        }
        else
        {
            $this->rio_model->update($id);
            $this->session->set_flashdata('msg', 'Registro Atualizado com Sucesso!');
            redirect('rio');
        }
    }

    function deletar($id)
    {
        if ($this->rio_model->delete($id))
        {
            $this->session->set_flashdata('msg', 'Registro Deletado com Sucesso!');
        } else
        {
            $this->session->set_flashdata('msg', 'ERRO - Não foi possível deletar este registro!');
        }
        redirect('rio');
    }

}

A página de exibição dos rios (rio_view.php):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title><?= $titulo ?></title>
    </head>

    <body>
        <h2><?= $cabecalho ?></h2>

        <p><?= anchor('bacia', 'Ver Bacias Hidrográficas')?> &nbsp; <?= anchor('rio', 'Ver Rios')?></p>

        <p><?= anchor('rio/criar', 'Criar Rio') ?></p>

        <p><?= @$this->session->flashdata('msg'); ?></p>

        <table border="1">
            <thead>
                <tr>
                    <th>
                        Nome do rio
                    </th>
                    <th>
                        Comprimento (km)
                    </th>
                    <th>
                        Nome da bacia
                    </th>
                    <th>
                        Ações
                    </th>
                </tr>
            </thead>
            <tbody>
                <?php if ($rios != false): ?>
                <?php foreach ($rios as $rio): ?>
                        <tr>
                           <td>
                                <?= $rio->nome_rio ?>
                           </td>
                           <td>
                                <?= $rio->comprimento_km ?>
                           </td>
                           <td>
                                <?= $rio->nome_bacia ?>
                           </td>
                    <td>
                        <?= anchor('rio/editar/' . $rio->id_rio, 'Editar') ?> |
                        <?= anchor('rio/deletar/' . $rio->id_rio, 'Deletar') ?>
                    </td>
                </tr>
                <?php endforeach; ?>
                <?php else: ?>
                            <p>Não há registros cadastrados!</p>
                <?php endif ?>
            </tbody>
        </table>
    </body>
</html>

Da mesma forma como fizemos nas bacias, teremos um único arquivo responsável pelo cadastramento e atualização dos dados referentes a esta tabela (rio_new.php):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
 "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <title><?= $titulo ?></title>
    </head>
    <body>
        <h2><?= $cabecalho ?></h2>

        <p><?= validation_errors(); ?></p>

        <?php
        //verifica se o form vai ser usado para insert ou update
        if (!isset($registro->id_rio))
        {
            echo form_open('rio/insere');
        }
        else
        {
            echo form_open('rio/atualizar');

            echo form_hidden('id_rio', $registro->id_rio);
        }
        ?>
        <p>
            <label>Nome do rio:</label>
            <input name="nome_rio" type="text" id="nome_rio" size="40" value="<?= @$registro->nome_rio ?>" />
        </p>

        <p>
            <label>Comprimento (km): </label>
            <input name="comprimento_km" type="text" id="comprimento_km" size="40" value="<?= @$registro->comprimento_km ?>" />
        </p>

        <p>
            <label>Bacia Hidrográfica</label>
            <select name="id_bacia">
                <option value="<?= @$registro->id_bacia; ?>"> <?= @$registro->nome_bacia; ?> </option>
                <?php foreach ($bacias as $bacia): ?>
                <option value="<?= $bacia->id_bacia; ?>"> <?= $bacia->nome_bacia; ?> </option>
                <?php endforeach; ?>
            </select>
        </p>
        <p>
             <input type="submit" id="Enviar" value="Enviar" />
        </p>
               <?= form_close() ?>
    </body>
</html>

Finalizamos o CRUD das duas tabelas, no nosso próximo post, vou mostrar como habilitar o mod_rewrite e retirar da url o index.php, e também fazer algumas pequenas melhorias visuais com CSS. Até lá!

domingo, outubro 10, 2010

Tutorial CodeIgniter - Parte 4

Vamos agora adicionar a validação no formulário de criação das Bacias Hidrográficas e em seguida, no próximo post, finalizar a aplicação com o CRUD dos rios.

A validação no CodeIgniter é feita através da biblioteca  "form_validation", o único problema que eu tive com ela, foi o fato da mesma não aceitar acentos da língua portuguesa,  para resolvermos  isso, vamos extender a classe do core realizando uma modificação no código da função alpha().

Para ver as mensagens dos erros de validação em português, é necessário baixar este arquivo, em seguida descompactar a pasta pt_br em sirh/system/language, feito isso, agora abra o arquivo config.php (dentro da pasta config) e mude a linha 69 para: $config['language'] = "pt-br";

Temos então que copiar o arquivo Form_validation.php da pasta /system/libraries para a pasta /system/application/libraries, agora abra o arquivo copiado e procure pela função alpha(), comente o return dela, e faça a seguinte alteração:

function alpha($str)
{
    //return ( ! preg_match("/^([a-z])+$/i", $str)) ? FALSE : TRUE;
    return (!preg_match("/^([A-Za-zá-úÁ=Ú.\s])+$/i", $str)) ? FALSE : TRUE;
}
 

Modificada a expressão regular, agora é possível trabalhar com palavras acentuadas.

Abra o controller bacia.php, vamos adicionar a validação nas funções insere() e atualizar(). Para isso é necessário Carregar a biblioteca form_validation no método construtor do controlador:

function __construct()
{
    parent::_construct();
    $this->load->model('bacia_model');
    $this->load->library('form_validation');
}



A função insert() ficará assim:

function insere()
{
    // o campo é requerido e deve ser uma string (alpha)
    $this->form_validation->set_rules('nome_bacia', 'Nome da Bacia', 'required|alpha');
    // caso a validação não passe,  carregue a view com o array $data
    if ($this->form_validation->run() == FALSE)
    {
        $data['titulo'] = "SIRH - Nova Bacia Hidrográfica | Erro na Validação, preencha corretamente!";
        $data['cabecalho'] = "Criar Bacia Hidrográfica | Preencha Corretamente!";

        $this->load->view('bacia_new', $data);
    }
    else
    {
        $this->bacia_model->insert();
        $this->session->set_flashdata('msg', 'Registro Criado com Sucesso!');
        redirect('bacia');
    }
}

e a update():

function atualizar()
{
    $id = $this->input->post('id_bacia');

    $this->form_validation->set_rules('nome_bacia', 'Nome da Bacia', 'required|alpha');

    // caso a validação não passe, carregue a view com o array $data
    if ($this->form_validation->run() == FALSE)
    {
        $data['titulo'] = "SIRH - Editar Bacia Hidrográfica | Erro na Validação, preencha corretamente!";
        $data['cabecalho'] = "Editar Bacia Hidrográfica | Preencha Corretamente!";

        $data['registro'] = $this->bacia_model->get_where($id);

        $this->load->view('bacia_new', $data);
    }
    else
    {
        $this->bacia_model->update($id);
        $this->session->set_flashdata('msg', 'Registro Atualizado com Sucesso!');
        redirect('bacia');
    }
} 

A regra adicionada não permite que o campo "nome" da Bacia Hidrográfica fique sem preenchimento (required), e será permitido apenas o preenchimento com texto (alpha). Para sinalizar as mensagens de erro, Abra a view bacia_new.php e adicione a função abaixo, logo depois do cabeçalho:

<p><?= validation_errors(); ?></p>

É isso... no próximo post vou mostrar como ficará o CRUD da tabela rio. Um abraço e até lá!