domingo, setembro 26, 2010

Tutorial CodeIgniter - parte 2

Vamos dar continuidade ao desenvolvimento da aplicação usando o CodeIgniter, na pasta sirh/system/application/controllers crie o arquivo bacia.php com o conteúdo abaixo:

<?php
class Bacia extends CI_Controller
{

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

    function index()
    {
        echo "<h1>Testando... 1, 2, 3</h1>";
    }
}
 No código anterior, criamos o controlador bacia, com a função index, que é exibida por default quando o controlador é chamado. Logo ao digitarmos a url:  http://localhost/sirh/index.php/bacia, veremos a mensagem de teste (Figura 1).

Figura 1 - teste do controlador bacia
Testado o funcionamento do controller bacia, vamos adicionar o cabeçalho e título da nossa página, modificando o código da função index:

function index()
{
  $data['titulo'] = "SIRH";
  $data['cabecalho'] = "Bacias Hidrográficas";

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

agora, dentro da pasta views, em sirh/system/application/, crie um arquivo com o nome bacia_view.php, com o seguinte conteúdo:


<!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>
   </body>
</html>

Abra mais uma vez o endereço http://localhost/sirh/index.php/bacia , o resultado deve ser o da Figura 2

Figura 2 - definidos o título e o cabeçalho da página
Está na hora de inserirmos alguns dados para a visualização, execute o script abaixo no banco, para povoar as duas tabelas:

-- INSERINDO 3 Bacias Hidrográficas
INSERT INTO bacia_hidrografica(nome_bacia) VALUES ('Abiaí');
--
INSERT INTO bacia_hidrografica(nome_bacia) VALUES ('Mamanguape');
--
INSERT INTO bacia_hidrografica(nome_bacia) VALUES ('Gramame');

-- INSERINDO 6 Rios nas suas respectivas Bacias
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Papocas', 9, 1);
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Graú', 12, 1);
--
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Mogeiro', 23, 2);
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Gavião', 9, 2);
--
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Guarabira',31, 3);
INSERT INTO rio(nome_rio, comprimento_km, id_bacia) VALUES ('Jacaré', 7, 3);

vamos agora exibir os dados que foram inseridos na tabela bacia_hidrografica, para isso será necessário criar um model (dentro de sirh/system/application/model) , que chamaremos de bacia_model.php, com o seguinte conteúdo:

<?php
class Bacia_model extends CI_Model
{
    function  __construct()
    {
        parent:__construct();
    }

    function get_bacia()
    {
        $this->db->order_by('nome_bacia', 'asc');
        $query = $this->db->get('bacia_hidrografica');
        if ($query->num_rows() > 0)
        {
            return $query->result();
        }
        else
        {
            return false;
        }
    }
}

Agora, vamos modificar o nosso controlador, carregando o model criado e povoando uma variável com um array de objetos, obtidos através da função get_bacia():

<?php
class Bacia extends CI_Controller
{

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

    function index()
    {
        $data['titulo'] = "SIRH";
        $data['cabecalho'] = "Bacias Hidrográficas";

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

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

Para finalizar esta postagem, vamos agora modificar a nossa view, basicamente vamos varrer o array de objetos $data['bacias'] e exibir os resultados, também vamos utilizar a função anchor() do CodeIgniter para definir os links desta página, que serão finalizados no próximo Post:


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

<p><?=anchor('bacia/criar', 'Criar Bacia Hidrográfica') ?></p>

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

Salve todos os arquivos e abra o navegador e veja o resultado: http://localhost/sirh/index.php/bacia

Figura 3 - Exibição das Bacias Hidrográficas
  Bem pessoal, por hoje é só, para ajudar no entendimento deste exemplo, sugiro dar uma boa olhada na série de screencasts do Nettus+ sobre o CodeIgniter (item 5 do link).

Tutorial CodeIgniter - parte 1

O CRUD é definido como acrônimo da expressão inglesa (Create Retrieve Update and Delete), para as quatro operações básicas utilizadas em um bancos de dados relacionais (RDBMS).
Nesta série de  postagens, criaremos uma aplicação Web com CRUD através da linguagem PHP, para as duas tabelas do modelo lógico da Figura 1, utilizando o Framework CodeIgniter. Para codificar, sugiro o uso do Netbeans com o autocomplete do CodeIgniter, este último pode ser baixado no link: http://rhasan.com/blog/2009/09/codeigniter-auto-complete-with-netbeans/ . Já o banco que irei utilizar nesse exemplo, será o PostgreSQL.

OBS: É necessário que o leitor tenha uma base em PHP OO, pois não vou entrar em muitos detalhes, também sugiro, dar uma boa lida no Manual do CodeIgniter em português.


Figura 1 – modelo lógico do exemplo
 
1o Passo: criar o banco no PostgreSQL

Crie um banco com o nome sirh com a codificação UTF-8 e rode o modelo físico abaixo, observe que as chaves primárias foram definidas como serial, criando automaticamente o auto-incremento para esses dois campos:


CREATE TABLE bacia_hidrografica (
id_bacia serial PRIMARY KEY,
nome_bacia varchar(40)
);

CREATE TABLE rio (
id_rio serial PRIMARY KEY,
nome_rio varchar(40),
comprimento_km int,
id_bacia int,
FOREIGN KEY(id_bacia) REFERENCES bacia_hidrografica (id_bacia)
ON UPDATE CASCADE );

Após rodar o script acima, o seu banco ficará da seguinte forma (Figura 2):

Figura 2 - Banco com as duas tabelas criadas (PgAdmin)


2o Passo: download do CodeIgniter

Vá até o endereço: http://codeigniter.com/downloads/ e baixe a última versão do CI (nesse post, usei a versão 1.7.2), a instalação é bem simples, descompacte o arquivo zipado na pasta de publicação do seu servidor web, no meu caso “/var/www/”, para quem usa o MS4W (Mapserver for Windows), descompacte na pasta htdocs do servidor.
Agora, vamos mudar o nome da pasta que foi descompactada para sirh (abreviação de “sistema para recursos hídricos”).

3o Passo: configurar a url do sistema e a conexão com o banco PostgreSQL

Abra  o arquivo config.php, dentro de sirh/system/application/config. Mude a linha 14 para http://localhost/sirh/ , salve o arquivo em seguida.

Abra o arquivo database.php (na mesma pasta) e configure a conexão com o banco (em seguida salve o arquivo):

$db['default']['hostname'] = "localhost";
$db['default']['username'] = "postgres";
$db['default']['password'] = "postgres";
$db['default']['database'] = "sirh";
$db['default']['dbdriver'] = "postgre";

4° Passo: configurar as bibliotecas e os helpers que serão carregados de forma automática

Abra o arquivo autoload.php, modifique a linha 42 para:

 $autoload['libraries'] = array(‘database’); 

e a 54 para:

$autoload['helper'] = array(‘url’);

5° Passo: testar a instalação

Abra o seu navegador e digite a url: http://localhost/sirh, você verá a tela da Figura 3, caso a mesma não seja exibida dessa forma, verifique os passos anteriores. No próximo Post continuaremos a desenvolver esta aplicação, até lá!

figura 3 - tela de boas vindas do codeigniter

quarta-feira, julho 07, 2010

PostGIS: conversão de coordenadas em graus decimais para graus, minutos e segundos (e vice-versa)

Recentemente tive que implementar uma solução, onde através de um formulário, o usuário informava as coordenadas em graus, minutos e segundos, logo em seguida era mostrado em um mapa, se essa coordenada caía em uma área válida da aplicação.
Acontece que por padrão, o PostGIS armazena as geometrias no formato decimal, logo eu teria que tratar as coordenadas digitadas (no código PHP ou no Banco), transformando-as em graus decimais, foi aí que eu encontrei duas funções muito úteis na lista de discussão do PostGIS. Fiz  uma pequena modificação na segunda função, que aumenta a quantidade de casas decimais dos minutos e segundos, caso do resultado seja um número inteiro nesses dois elementos.

Para utilizá-las é necessário carregá-las em um banco com o PostGIS instalado.


Create or Replace Function DMS2DD(  dDeg In Float,
                                    dMin In Float, 
                                    dSec In Float )                                
Returns Float
AS
$BODY$
Declare
   dDD Float;
BEGIN
   dDD := ABS(dDeg) + dMin / 60::float + dSec / 3600::float;
   Return SIGN(dDeg) * dDD;
End;
$BODY$
  LANGUAGE 'plpgsql' IMMUTABLE STRICT
  COST 100;

create or Replace Function DD2DMS(  dDecDeg in Float,
                                    pDegreeSymbol in VarChar(1),
                                    pMinuteSymbol in VarChar(1),
                                    pSecondSymbol in VarChar(1) )
Returns varchar(50)
AS
$BODY$
DECLARE
   iDeg Int;
   iMin Int;
   dSec Float;
   
BEGIN

   iDeg := Trunc(dDecDeg)::Int;
   iMin := Trunc(   (Abs(dDecDeg) - Abs(iDeg)) * 60)::Int;
   dSec := Round(((((Abs(dDecDeg) - Abs(iDeg)) * 60) - iMin) * 60)::numeric, 3)::float;
   
Return trim(to_char(iDeg,'9999')) || pDegreeSymbol::text ||
       trim(to_char(iMin,'99.00')) || pMinuteSymbol::text || 
       case when dSec = 0::Float
       then '00' else replace(trim(to_char(dSec,'99.999')),'.000','') 
       end || pSecondSymbol::text;
END;
$BODY$
  LANGUAGE 'plpgsql' IMMUTABLE STRICT
  COST 100; 

Utilizando as funções:
-- Converter as coordenadas da geometria 
-- POINT(-38.4969 -6.4026) para graus, minutos e segundos: 
 
SELECT DD2DMS(x(geometryFromText('POINT(-38.4969 -6.4026)')), '°','\'','\"' ) as Longitude,
DD2DMS(y(geometryFromText('POINT(-38.4969 -6.4026)')), '°','\'','\"' ) as Latitude;
 

Resultado:

       Longitude      |       Latitude
--------------------------+-----------------------
-38°29.00'48.840" | -6°24.00'9.360"

-- Converter as coordenadas (-34° 10' 50", -7° 33' 30")
-- para graus decimais:
 
SELECT DMS2DD(-34,10,50) as longitude,
DMS2DD(-7,33,30) as latitude;
 

Resultado:

       Longitude       |       Latitude
----------------------------+-----------------------
-34.1805555555556 | -7.55833333333333

sexta-feira, setembro 25, 2009

Corrigindo a Codificação na Exportação de Shapefiles para SQL

No processo de exportação de Shapefiles para SQL já podemos modificar a codificação do arquivo gerado para a mesma codificação do Banco, evitando a inserção de caracteres estranhos nas tabelas (�). Também é comum nos depararmos com o erro abaixo quando tentamos importar um arquivo .sql na codificação LATIN1 (ou ISO-8859-1) para um Banco de Dados em UTF-8:

ERRO:  sequência de bytes é inválida para codificação "UTF8": 0xed7269
HINT:  Este erro pode acontecer também se a sequência de bytes não corresponde a codificação esperado pelo servidor, que é controlada por "client_encoding".


Para evitar este problema, use o comando shp2psql junto com o comando iconv, que é responsável por fazer esta modificação. A sintaxe é a seguinte:


shp2pgsql -s SRID shapefile nome_da_tabela | iconv  -f codificacao_de_origem -t codificacao_de_destino > arquivo_sql.sql


Exemplo:

shp2pgsql -s 4291 municipios_ibge.shp municipios | iconv -f LATIN1 -t UTF-8 > municipios.sql  

Em seguida, use psql -f municipios.sql -d seu_banco_utf8 para criar a tabela com seus registros.

quinta-feira, setembro 17, 2009

Utilizando Javascript e CSS em aplicações Mapserver via CGI

Para finalizar a postagem “Integrando o Mapserver com o PostGIS” vou disponibilizar aqui  uma aplicação Mapserver CGI que utiliza algumas funções Javascript em um layout baseado em CSS (Cascading Style Sheets – CSS). 

Esta aplicação também roda no Windows através do pacote MS4W. Veja como configurá-la através do arquivo como_instalar.txt.






Fico a disposição de vocês caso haja alguma dúvida sobre o código.