DGmike

DGmike

Calma! não entre em pânico! Amanhã (talvez) tem novo post…

  • Alice Andrade
  • Rafael Zamana
  • Home
  • Guia Rápido jQuery
  • Códigos prontos
    • PHP: Função __auloload()
    • Classe sqlsimples e sql – PHP
    • Bancos, bancos e mais bancos…
  • PagSeguro
  • Artigos
    • JavaScript (parte 1)
  • Quem?

PDO e classe de resultados

Posted in icephp, php, sql by DGmike
Oct 22 2009
TrackBack Address.

Estava fazendo alguns testes com PDO e SQLite e descobri uma coisa muito interessante sobre o PDO: classe de resultados. O que isso quer dizer, que quando você faz um fetchObject você pode usar sua própria classe com seus próprios métodos.

Atenção! Este post é totalmente NERD e destinado para programadores com algum conhecimento em PHP e banco de dados. Caso este não seja seu perfil aconselho a desistir enquanto é tempo.

Caixa, guarde o que é seu

O código começou mais ou menos assim, eu queria desenvolver um model específico para o ICEPHP, e com o advento do PDO decidi usá-lo como base. Então precisei de alguns definitions: diretório onde se encontra o arquivo (script) e o separador de pastas que em linux é barra e no windows é contra-barra. Também criei duas tabelas no banco de dados, post e categoria:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
define('DS', DIRECTORY_SEPARATOR);
define('ICE_DIR', dirname(__FILE__));
 
$bd = new PDO('sqlite:'.ICE_DIR.DS.'banco.db');
# A conexão do PDO não é linda?!

$bd->query("
    CREATE TABLE IF NOT EXISTS categoria (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        nome VARCHAR(40),
        slug VARCHAR(40)
    );
");
$bd->query("
    CREATE TABLE IF NOT EXISTS post (
        id INTEGER PRIMARY KEY AUTOINCREMENT,
        titulo VARCHAR(40),
        slug VARCHAR(40),
        post TEXT,
        data TIMESTAMP
    );
");

Após isso fiz um select no banco de dados e se não me retornasse resultados, inseri um dado no banco de dados:

1
2
3
4
5
6
7
8
9
10
11
12
$c=$bd->query("SELECT COUNT(*) as c FROM post;");
 
if (!$c->fetchObject()->c) {
    $bd->query("
        INSERT INTO post (titulo, slug, post, data) VALUES (
            'Apenas um teste',
            'apenas-um-teste',
            'Este post é apenas um teste do novo Framework: ICEPHP',
            CURRENT_DATE
        );
    ");
}

Com isso eu consigo usar o resultado de forma linda (orientado a objetos):

1
2
3
4
5
$c=$bd->query("SELECT * FROM post;");
$r = $c->fetchObject();
echo $r->titulo;
 
// Isto retorna "Apenas um teste"

Lendo a documentação sobre o fetchObject do PDO vi que é possivel passar como parâmetro uma string com o nome da Classe que você deseja que seja utilizado para o resultado, lembrando que (!), o padrão é o stdClass. Entao passei minha classe resultado como exemplo e o que descobri. Coisas lindas de se fazer. Eis a classe Resultado:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
class Resultado
{
    var $_data = array();
    var $_updated = false;
 
    function __toString()
    {
        return "O resultado é: ".$this->titulo . ' ('.date('d-m-Y h:i:s', $this->data).")\n";
    }
 
    function __get($k)
    {
        return $this->_data[$k];
    }
 
    function __set($k, $v)
    {
        if (isset($this->_data[$k]) AND $this->_data[$k] != $v) {
            $this->_updated = true;
        }
        $this->_data[$k] = $v;
    }
 
    function salvaPost()
    {
        global $bd;
 
        $sql = "UPDATE post SET ";
        foreach ($this->_data as $k=>$v) {
            if ($k!='id' || $k != 'data') {
              $sql .= "\n  $k = '$v',";
            }
        }
        $sql = substr($sql, 0, -1);
        $sql .= "\n WHERE id = ".$this->id;
 
        $bd->query($sql);
    }
 
    function __destruct()
    {
        if ($this->_updated) {
            $this->salvaPost();
        }
    }
}

Veja, apenas usei um método de verdade, todos os outros usei os métodos mágicos do PHP (__toString, __get, __set, __destruct). Recomendo que leia sobre estes métodos e use-os, eles podem salvar sua vida. Whatever, com essa classe Resultado é possivel fazer o que eu sempre quis fazer, um objeto de resultado de banco de dados que atualiza o banco sem usar o estilo seta parametros e depois salva. Veja como é feito na maioria dos ORMs por aí:

1
2
3
$r=$post->get(1);
$r->titulo = 'Titulo Alterado';
$r->save();

Pense comigo, se você atribuiu um valor, você quer que ele seja salvo, correto? Então não ficaria mais fácil se forsse assim?

1
2
$r=$post->get(1);
$r->titulo = 'Titulo Alterado';

Sim!!! Às vezes você atribui um valor que não deseja salvar, faz isso apenas para configurar os dados e etc, mas pense, quantas vezes você faz isso? Além disso, óbvio que é possivel fazer tudo o que deseja gastando um pouco mais de massa cinzenta, mas a proposta não é essa no momento.

Usando a classe Resultado é possivel fazer o update quase que “on the fly”. Na verdade, para o programador parece que é instantâneo, mas não é. O update se dá no destruct do objeto, normalmente quando o script finaliza, mas pode ser quando damos um novo fetchObject nessa variável. Se ele não for alterado ele, obviamente, não salva as alterações no banco de dados. Veja como fica o exemplo do que estou falando.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
$c=$bd->query("SELECT * FROM post;");
# Pegando o objeto e jogando-o na classe de resultados
$r = $c->fetchObject('Resultado');
 
# Imprimindo, devido ao método __toString aparece:
# O resultado é: Apenas um teste (31-12-1969 09:33:29)
print ($r);
 
# Alterando o resultado
$r->titulo = 'Teste';
 
# Imprimindo mais uma vez, aparece
# O resultado é: Teste (31-12-1969 09:33:29)
# mas isto está em 'cache'
print ($r);
 
# Quando o objeto é destruído, ao finalizar o script
# ele faz o update necessário

Testei isso no foreach e também funcionou, então é fazer updates de objetos em escala, mas não exagere, o ideal é fazer isso no sql. Veja como fica com o foreach:

1
2
3
4
5
$c=$bd->query("SELECT * FROM post;");
 
while ($x = $c->fetchObject('Resultado')) {
    $x->data = time();
}

Isso me deixa com várias ideias para criar o ORM do ICEPHP. Mas fica a dica para vocês desenvolverem seus códigos, experimente criar um método FORM que já cria um formulário html para você facilitar sua vida. :D

1 Comment »
Tagged as: banco de dados, classe, framework, icephp, pdo, php, sqlite

Campo DataTransacao no retorno do PagSeguro

Posted in Dia-a-dia, pagseguro by DGmike
Apr 03 2009
TrackBack Address.

Algumas vezes algumas pessoas me perguntam sobre o campo DataTransacao quando trabalhamos com boletos? Qual data vem nesse campo? A data em que o boleto foi emitido? A data em que o status foi alterado? Ou a data em que o POST foi enviado para você. (se quiser uma explicação sobre o que é esse tal de POST ou como funciona o PagSeguro, aconselho a ler meu artigo escrito no forum do iMasters)

No PagSeguro, o Boleto você pode gerar boletos para seus clientes de forma segura, mas atente para a data de compensação desse boleto. Nem você nem seu cliente querem erros nessas datas

No PagSeguro, o Boleto você pode gerar boletos para seus clientes de forma segura, mas atente para a data de compensação desse boleto. Nem você nem seu cliente querem erros nessas datas

Claro que isso é uma preocupação muito grande para quem trabalha com créditos que dependem da data em que a pessoa efetuou o pagamento. Cinco dias corridos de acesso a partir do pagamento por exemplo.

Então fui procurar uma resposta em meu log de dados, eis que me deparo com dois casos e verifiquei a seguinte sequencia de pagamentos via boletos (os IDs das tranações foram alterados para segurança dos clientes):

//-
Thu Apr 2 21:04:17 2009

‘StatusTransacao’: ‘Aguardando Pagto’,
‘DataTransacao’: ‘02/04/2009 21:08:58‘,
‘TipoPagamento’: ‘Boleto’,
‘TransacaoID’: ‘XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXA’,

Fri Apr 3 06:27:04 2009

‘StatusTransacao’: ‘Aprovado’,
‘DataTransacao’: ‘02/04/2009 21:08:58‘,
‘TipoPagamento’: ‘Boleto’,
‘TransacaoID’: ‘XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXA’,
-//

//-
Thu Apr 2 11:04:38 2009

‘StatusTransacao’: ‘Aguardando Pagto’,
‘DataTransacao’: ‘02/04/2009 11:09:18‘,
‘TipoPagamento’: ‘Boleto’,
‘TransacaoID’: ‘XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXB’,

Fri Apr 3 06:02:47 2009

‘StatusTransacao’: ‘Aprovado’,
‘DataTransacao’: ‘02/04/2009 11:09:18‘,
‘TipoPagamento’: ‘Boleto’,
‘TransacaoID’: ‘XXXXXXXX-XXXX-XXXX-XXXX-XXXXXXXXXXXB’,
-//

Como podemos perceber, o campo “DataTransacao” não é alterado e provavelmente se refere à data em que a compra foi efetuada, logo aconselho a alterar a data do seu banco de dados com a data atual do sistema. Em mysql você pode usar NOW() (faz um “SELECT NOW()” para ver o que estou falando).

Abraços, espero que isso retire a dúvida de uma ou duas pessoas =D

No Comments yet »
Tagged as: aplicar, banco de dados, boleto, data, dinheiro, e-commerce, loja, loja virtural, mysql, pagamento, pagseguro, php, postgree, retorno, retorno automático, simples

Post Rápido: Unir dois resultados em um só SQL

Posted in Tutorial, sql by DGmike
Mar 30 2009
TrackBack Address.

Aqui onde estamos trabalhando (@rodrideme e @deninhu) precisamos fazer uma busca em dois bancos de dados e mostrar o resultado em um lugar só. Por que? Porque temos dois bancos de dados e em um ficarão os registros de quem já é registrado, e no outro quem ainda não é registrado, mas que pode vir a se registrar (mas isso é outra história).

Banco de dados. Sempre que puder, use esta ferramenta para ajudar no seu dia a dia

Banco de dados

Aqui nós estamos trabalhando com db2[bb], mas o que irei mostrar é independente de banco.

Tá, para de enrolar e fala logo!

Você pode unir dois resultados (inclusive de drivers/bancos que estejam na mesma conexão) em um unico result, mesclando os dados. Para isso use a estrutura UNION.

Tome as seguintes queries:

1
2
3
SELECT cod, nome, idade FROM pessoas
 
SELECT codigo, nome_completo, idade FROM pessoas_nao_cadastradas

Primeiro, você deve ter resultados iguais para cada select, para isso use alias para igualar os resultados.

1
2
3
SELECT cod, nome, idade FROM pessoas
 
SELECT codigo AS cod, nome_completo AS nome, idade FROM pessoas_nao_cadastradas

Agora, basta você usar o UNION entre os dois selects:

1
2
3
SELECT cod, nome, idade FROM pessoas
UNION
SELECT codigo AS cod, nome_completo AS nome, idade FROM pessoas_nao_cadastradas

Pronto! Você tem o resultado de dois bancos de dados mesclados em um só.

Legal, mas como faço WHERE nisso?

Você deve fazer um where ou nos dois selects ou fazer um select que totaliza os dois (como eu gosto de fazer):

1
2
3
4
5
SELECT z.* FROM (
  SELECT cod, nome, idade FROM pessoas
  UNION
  SELECT codigo AS cod, nome_completo AS nome, idade FROM pessoas_nao_cadastradas
) z WHERE nome = 'Michael'
  • Insert simples de SQL
  • IcePHP: O framework gelado como um picolé!
  • PDO e classe de resultados
  • Campo DataTransacao no retorno do PagSeguro
  • Post Rápido: Prevenindo SQL injection

2 Comments »
Tagged as: banco, banco de dados, dados, database, db2, dois bancos, mesclar, querie, query, select, sql, union

Insert simples de SQL

Posted in php, sql by DGmike
Sep 27 2008
TrackBack Address.

Uma funçãozinha simples que ajuda muito para trabalhar com inserção de dados no SQL (MySQL, MS-SqlServer, SQLite ou PostGree, por exemplo) pelo PHP. O comando SQL para realizar a inserção é:

INSERT INTO `tabela` (`campo1`,`campo2`,`campo3`...) VALUES (`valor1`,`valor2`,`valor3`...);

Desta forma, deixamos os dados separados de forma dificil de manipular… Então desenvolvi esta função em PHP para minha classe SQL.

function adicionar_sql ($tabela,$dados) {
if (is_array($dados)) {
$keys='';
foreach ($dados as $k=>$v) {
$keys[]="`$k`";
$values[]=$v==='NOW()'?"NOW()":$v;
}
$keys=implode(', ',$keys);
$values=implode(', ',$values);
return "INSERT INTO `$tabela` ($keys) VALUES ($values)";
}
return false;
}

Ela funciona da seguinte forma:

adicionar_sql ('tabela', array (
'campo1'=>'valor1',
'campo2'=>'valor2',
'campo3'=>'valor3',...
));

Esta função também está habilitada para o valor NOW() que coloca o valor da hora atual no banco de dados.

[update] Fiz uma leve alteração no código, usando funções que facilitam e deixar a função mais rápida, por se tratar de função interna do próprio PHP. O interessante é que ficou com menos linhas de código e mais compreensível.

function adicionar_sql($tabela, $dados = array()){
  if (!is_array($dados)) return false;
  foreach ($dados as $k=>$v)
    $dados[$k] = $v==='NOW()' ? 'NOW()' : "'".addslashes($v)."'";
  return sprintf ('INSERT INTO %s (`%s`) VALUES (%s);', $tabela, implode('`, `', array_keys ($dados)), implode(', ', $dados));
}

3 Comments »
Tagged as: banco de dados, insert, insert simples, ms-sql, mysql, php, postgree, simples, sql

IcePHP: O framework gelado como um picolé!

Posted in Programação, icephp, php by DGmike
Apr 01 2008
TrackBack Address.

O framework gelado como um picolé!

Estou desenvolvendo meu próprio framework para PHP: IcePHP. Como sempre gosto de começar pelo banco de dados, este é o primeiro lugar de onde a aplicação vai partir. Os unicos arquivos no repositório do projeto são de banco de dados além do começo da documentação do mesmo. Até agora, o banco só funciona com a extensão mysqli (mysql implemented do PHP), mas pretenderá extender-se a outros bancos desde que eu tenha necessidade de tais bancos ou mesmo as pessoas que quiserem ajudar.

O IcePHP será um framework para projetos simples, sites simples ou mesmo blogs ou pequenos portais de conteúdo, já que terá integrado em sua engine um sistema de cache. Não! O IcePHP não é um CMS é um FrameWork que poderá desenvolver todos esses tipos de sistemas.

Vamos a um exemplo simples, de como a classe de banco de dados se comporta. Faremos um simples blog. Mostrando os itens de uma determinada categoria. Então, este é o nosso banco de dados:


CREATE TABLE categorias (
id int(5) NOT NULL,
nome varchar(255) NOT NULL,
PRIMARY KEY (id)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

CREATE TABLE IF NOT EXISTS `posts` (
`id` int(5) NOT NULL,
`categoria_id` int(5) NOT NULL,
`titulo` varchar(255) NOT NULL,
`post` text NOT NULL,
`data` date NOT NULL,
PRIMARY KEY (`id`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1;

Duas tabelas simples com poucos campos, que são a maioria dos casos que temos nos projetos diários. Agora, vamos à classe banco. Primeiro, conectamos ao banco.

require_once ("banco.php");
$banco = new banco ('mysqli://root:123456@localhost/icephp');

Na primeira linha, fiz o requerimento do arquivo (require_once para não chamar o arquivo duas vezes se ele tiver sido chamado antes), e na segunda linha a coneção através de uma url simples onde coloco o driver, usuario, senha, url do banco (localhost) e o banco (icephp).

Isto fará com que minha instancia $banco receba dois objetos (as tabelas) então posso chamá-las assim:

$banco->categorias;
$banco->posts;

Cada uma delas possui uma série de funções como novo(), get(), select() e por aí vai (ainda não está totalmente pronta, por isso só tem o get). Que me auxilia da seguinte forma. Digamos que queremos o primeiro post da tabela.

$post = $banco->posts->get(1);

Agora, post é um objeto tabela que tem os dados que queriamos. Logo, podemos pegar as seguintes informações.

$post->id;
$post->titulo;
$post->post;
$post->data;
$post->categoria;

Categoria?! Sim, a classe banco já instancia a categoria atraves de um belo join implicido ao criar um campo com a sintaxe NomeDaTabela_id. post->categoria é um objeto tabela que pode ser retirado as seguintes informações.

$post->categoria->id;
$post->categoria->nome;

Agora, faremos o procedimento contrário. Vamos pegar uma categoria com o método get.

$categoria = $banco->categorias->get(1);

Agora $categoria tem as seguintes propriedades:

$categoria->id;
$categoria->nome;
$categoria->posts;

Sim! Ele faz o inverso também! Temos um array de tabelas posts com os posts continos nessa categoria. Agora, vamos a um exemplo bem prático, vamos listar os posts da 3ª categoria:

foreach ($banco->categorias->get(3)->posts as $post) {
printf ('
<h1>%s</h1>
<p>Postado em %s na categoria %s</p>
<p>%s</p>
', $post->titulo, $post->data, $post->categoria->nome, $post->post);
}

Como vocês podem ver, a classe banco resolve muitos problemas de uma vez só, basta usá-la com conciencia. :D

Estava querendo começar a desenvolver um framwork de verdade há um bom tempo, mas nunca conseguia me agradar o suficiente (nossa!). Cheguei a montar um pseudo framework, o frwk-br, mas tinha um nome muito complicado de decorar.

Para o IcePHP vou me basear bastante no frwk-br e em algumas coisinhas que aprendi no curso de Python que fiz recentemente com o Elcio da visie. Espero que o IcePHP não fique guardado na geladeira e seja usado por várias pessoas no seu dia-a-dia.

Para este trunfo, conto com a ajuda do meu amigão Zamana, que está sempre bisbilhotando meus códigos indicando onde tem erros (isso é bom). ;D

4 Comments »
Tagged as: aplicação, banco, banco de dados, documentação, framework, icephp, mysql, mysqli, php, projetos

Categorias

  • Amigos  (16)
  • cases  (4)
  • Cotidiano  (71)
  • CSS  (19)
  • Design  (1)
  • Dia-a-dia  (29)
  • Diversão  (18)
  • eventos  (9)
  • extensions  (11)
  • flash  (3)
  • Games  (1)
  • html  (5)
  • icephp  (4)
  • Ilustração  (6)
  • Imagem  (8)
  • Inspiração  (5)
  • javascript  (35)
    • jQuery  (7)
    • yui  (2)
  • Não categorizado  (27)
  • Navegadores  (17)
    • Chrome  (4)
    • Firefox  (16)
    • Internet Explorer  (5)
  • pagseguro  (10)
  • php  (41)
    • PHP Conference  (2)
  • plugin  (3)
  • Programação  (41)
  • python  (5)
  • Semântica  (16)
  • sql  (8)
  • tableless  (18)
  • Tecnologia  (46)
  • Trabalho  (25)
  • Tutorial  (23)
  • Vetorial  (5)
  • video  (7)
  • video-tutorial  (5)
  • Windows  (4)
  • wordpress  (2)
  • xHTML  (23)

Tags

ajax artigo banco de dados biblioteca blog browser classe CSS data Design Dia-a-dia evento eventos Firefox framework google html icephp internet Internet Explorer javascript jQuery loja mysql online opera pagseguro palestra php plugin Programação python retorno automático simples site solução sql string tableless Tecnologia Tutorial twitter visie web wordpress

Arquivo

SlideSare

Últimos Posts

  • Frete com PagSeguro: simples!
  • Palestra PagSeguro na Impacta
  • PagSimples: faça combranças facilmente com o PagSeguro
  • IcePHP agora é IceBaby
  • O PagSeguro mudou a URL de retorno automático, e agora?

Amigos

  • Alice Andrade
  • Rafael Zamana
Powered by WordPress | “Blend” from Spectacu.la WP Themes Club