Ítalo Barboza

Naturalmente um sonhador. Programador e fotógrafo somente nas horas vagas

Arquivo da categoria ‘PHP’

Gerando IDs únicos

deixe seu comentário

Olá pesso@l, tudo bem? Outro dia eu precisei gerar um número de identificação (ID) aleatório para uma rotina em que eu estava dando manutenção e uma rápida pesquisa no “Pai” Google, fui contemplado com um link para o PHPIt onde ele explica a utilização da função uniqid(), nativa do próprio PHP.

A sua utilização é tão simples quanto o seu conceito:

echo uniqid();
// Saída: 4e84c7d5a6987

Utilizando a função em um laço:

for ($i = 0; $i < 10; $i++) {
    echo uniqid() . '<br />';
}
// Saída: 4e84c875f38a8
// Saída: 4e84c875f38af
// Saída: 4e84c875f38b0
// Saída: 4e84c875f38b1
// Saída: 4e84c875f38b1
// Saída: 4e84c875f38b2
// Saída: 4e84c875f38b3
// Saída: 4e84c875f38b4
// Saída: 4e84c875f38b5
// Saída: 4e84c875f38b5

Analisando as saídas, percebe-se que existe um padrão seguido por esta função na geração da ID. Este padrão dar-se pelo uso da função microtime(), interna ao uniqid().

Podemos aumentar a entropia da função utilizando outras funções (tanto de hash quando de criptografia) no prefixo do código (primeiro parâmetro da função) e modificando a quantidade de caracteres gerados de 13 para 23 alterando o segundo parâmetro de FALSE (valor default) para TRUE. Confira no exemplo abaixo:

for ($i = 0; $i < 10; $i++) {
    echo uniqid(sha1(rand()), TRUE) . '<br />';
}
// Saída: 9f4b9d9df13f74457c4f0eb1bfed5b922ddb1bb34e84cbe9ec1ce7.27897791
// Saída: 299f161d0bb46a462bef82fdd45303fc965c6af34e84cbe9ec1dd5.74207369
// Saída: 644e71d99c5d8deadbe61949142ea5c40b576c0c4e84cbe9ec1e15.04481648
// Saída: bc85daf847620bcb9f88a09dee8880d6677a7e9d4e84cbe9ec1e53.09937296
// Saída: a812f5ddfdd241c29f9645ea09e14dedbdae2f1b4e84cbe9ec1e80.40306498
// Saída: 4ffba05e292341e54f6b149967cf0e728d4f11e84e84cbe9ec1eb9.94583297
// Saída: a456f63f28045d345974578e5c8cdc7929cae7844e84cbe9ec1ee1.01013992
// Saída: dd06d79f71ff9b2149eeb520a2a81b62d03808a24e84cbe9ec1f09.94216867
// Saída: d6b901451053e09732274be095410d19d44550794e84cbe9ec1f34.05750617
// Saída: 55f330cf75634311ecc24172f7dd61c3140b37f14e84cbe9ec1f61.26749318

Analisando a saída, percebe-se que a entropia agora é muito maior, otimizando ainda mais o resultado.

Bom, é isso. Acho que ficou claro e satisfatório o resultado para que a função uniqid() se propõe. Bons estudos e até a próxima. :D

Share on TwitterShare on TumblrSave on DeliciousShare via email

Publicado por Ítalo Barboza

29 de setembro de 2011 as 4:45 pm

Posted in PHP

Marcado com , , , ,

7 coisas simples em PHP que ainda complicam

deixe seu comentário

1. Listas arquivos de um diretório

Se não houver um motivo muito claro pra usar opendir, readdir e closedir (não consigo pensar em nenhum), a forma mais prática de listar o conteúdo de um diretório é com DirectoryIterator:

$iterator = new DirectoryIterator('/var/www');

foreach ( $iterator as $entry ) {
    echo $entry->getFilename(), "\n";
}

Se for necessário listar os arquivos recursivamente, percorrendo todos os subdiretórios, é só usar o RecursiveDirectoryIterator junto com o RecursiveIteratorIterator:

$iterator = new RecursiveDirectoryIterator('/var/www');
$recursiveIterator = new RecursiveIteratorIterator($iterator);

foreach ( $recursiveIterator as $entry ) {
    echo $entry->getFilename(), "\n";
}

Com um pouco de criatividade, é possível estender essas classes com qualquer lógica facilmente, como por exemplo, para montar uma árvore com a estrutura dos diretórios.

2. Montar e desmontar query strings

Mesmo que menos comum (e menos útil), colocar uma query string numa URL é um trabalho trivial demais pra ser feito com implode, concatenando tudo ou qualquer outro método engenhoso. Desde o lançamento do PHP 5 é possível contar com a http_build_query:

$dados = array(
    'hl' => 'pt-BR',
    'q'  => 'Forgetting Sarah Marshall',
    'testa-escape' => 'acentuação',
);

echo http_build_query($dados);
// hl=pt-BR&q=Forgetting+Sarah+Marshall&testa-escape=acentua%C3%A7%C3%A3o

E o inverso também é possível com as funções parse_url e parse_str:

$url = parse_url('http://www.google.com/search?q=php+manual&num=50');

parse_str($url['query'], $query);

echo $query['q'];
// php manual

Só fique atento que, por motivos alheios ao bom senso, parse_str por padrão extrai as variáveis no escopo onde foi chamada. É necessário passar um segundo argumento para ter um array gerado por referência, como no exemplo acima com a variável $query.

3. Ler páginas remotas

Dentre todas as implementações, a mais desnecessária costuma ser fsockopen, fwrite, feof, fgets e fclose para ler arquivos remotos por HTTP.

Uma função já resolve:

$contents = file_get_contents('http://php.net/file_get_contents');

Isso é possível graças aos protocol wrappers que encapsulam a lógica de acesso aos respectivos protocolos, tal como HTTP. Esta forma de acesso, no entanto, depende da configuração allow_url_fopen estar habilitada no php.ini (que é o padrão).

Para ler os response headers da requisição, utilize fopen com stream_get_meta_data.

E se um dia você quiser impressionar a mulherada, veja a função stream_wrapper_register para criar o seu próprio protocol wrapper.

4. Submeter dados por post para uma página remota

A coisa fica mais complicada quando o desenvolvedor pensa em usar cURL pra submeter dados por POST para outro servidor. A extensão até tem seu mérito, mas usá-la apenas pra este propósito é um grande equívoco.

As funções que fazem uso dos protocol wrappers aceitam um objeto de stream context, criado pela função stream_context_create, para configurar alguns aspectos do protocolo. As opções de contexto do protocolo HTTP permitem definir, entre outras coisas, o método de acesso (GET, POST, etc) e o conteúdo a ser postado:

$content = http_build_query(array(
    'cidade' => 'Recife',
    'tipo'   => 'Apartamento',
));

$context = stream_context_create(array(
    'http' => array(
        'method'  => 'POST',
        'content' => $content,
    )
));

$contents = file_get_contents('http://exemplo/teste.php', null, $context);

Quando não for necessário ler o retorno da requisição, basta chamar a url com fopen passando o contexto como quarto argumento.

5. Fazer download de um arquivo remoto

Vale lembrar que a maioria das funções de stream e filesystem aceitam URLs completas e fazem uso da abstração do protocolo. O que eu vejo muita gente esquecer é que isso inclui a função copy:

$url = "http://userserve-ak.last.fm/serve/500/4349551/Terri+Clark.jpg";

copy($url, '/tmp/' . urldecode(basename($url)));

O trecho acima vai baixar a imagem remota e salvar no arquivo local /tmp/Terri Clark.jpg. E caso não seja óbvio, “local” se refere a quem está executando o script PHP, que no caso será o seu servidor caso seja um script web, e não o cliente que está acessando pelo browser.

Se o objetivo for realmente repassar o conteúdo remoto para o cliente que estiver acessando pelo browser, o script é igualmente simples:

$url = 'http://userserve-ak.last.fm/serve/500/4349551/Terri+Clark.jpg';

$handle = fopen($url, 'r');

$meta_data = stream_get_meta_data($handle);

// Repassa todos os headers do servidor remoto para o nosso cliente
foreach ( $meta_data['wrapper_data'] as $header ) {
    header($header);
}

// Repassa o conteúdo para o nosso cliente
fpassthru($handle);

Considerando que estamos apenas testando a funcionalidade. Ter um script de proxy totalmente funcional é bem mais complexo, e certamente já tem algo pronto por aí.

6. Fazer cálculo com data

Dentre todas as simplificações possíveis, a que mais costuma comover é a função strtotime. Pra quem já está acostumado, parece que não faz mais do que sua obrigação. Mas pra quem ainda faz cálculos com data multiplicando por 86400, chega a parecer mágico:

echo 'Amanhã: ', strftime('%A', strtotime('tomorrow'));
// Amanhã: domingo

echo 'Próxima segunda: ', strftime('%d de %B de %Y', strtotime('next monday'));
// Próxima segunda: 12 de setembro de 2009

echo 'Vencimento: ', strftime('%d/%m/%Y', strtotime('+3 months'));
// Vencimento: 30/08/2009

Mais exemplos você mesmo pode ver no manual do PHP ou na página de Date Input Formats do projeto GNU. Para o nome dos meses e dias da semana ficarem em português, utilize setlocale(LC_TIME, ‘pt_BR’); antes de chamar a função strftime.

7. Escapar SQL e HTML

Felizmente nunca mais vi nenhum script com aberrações anti-sql-injection, mas há algum tempo era possível encontrar pessoas removendo palavras-chave de SQL de todas as strings que íam para o banco de dados. Se o usuário digitasse palavras como select, delete ou drop, elas eram simplesmente removidas da frase. Isso quando o programador não interrompia o script e acusava o usuário de estar tentando explorar alguma falha de segurança. Eu juro, isso existia.

Ao trabalhar com PDO, a melhor opção (pra não dizer a única!) é utilizar prepare e execute pra separar a query em si dos seus parâmetros:

$conexao = new PDO('mysql:dbname=banco;host=localhost', 'login', 'senha');

$uf = 'RJ';
$idade = 18;

$sth = $conexao->prepare('SELECT nome FROM pessoa WHERE uf = ? AND idade > ?');

$sth->execute(array($uf, $idade));

while ( $row = $sth->fetch() ) {
    echo $row['nome'];
}

Se estiver utilizando drivers nativos, veja as funções mysql_real_escape_string ou mysqli_prepare e mysqli_stmt_bind_param, dependendo da extensão. Certamente outros bancos de dados têm a mesma funcionalidade.

A única preocupação é garantir que os parâmetros não se misturem com a query; não precisa inventar moda e remover o que o usuário digitou.

Outra confusão comum é ao escapar HTML. O objetivo é evitar que o texto digitado por um usuário seja interpretado pelo browser de todos os usuários do site.

Conceitualmente, esta é uma responsabilidade da camada de exibição. O template é que deve utilizar htmlspecialchars antes de gerar a saída na tela, e não antes de salvar no banco. Isso garante que o conteúdo que está no banco é fiel ao que foi digitado pelo usuário e pode ser reaproveitado em outras mídias além do HTML.

O que pode e deve ser feito é filtrar conteúdo realmente indevido, como caracteres inválidos ou espaços extras, dependendo da aplicação.

via: garotosopa

Share on TwitterShare on TumblrSave on DeliciousShare via email

Publicado por Ítalo Barboza

9 de setembro de 2011 as 10:30 am

Diferenças entre: include(), require(), include_once() e require_once()

um comentário

Olá para tod@s, hoje eu vou explicar a diferença entre as funções:

Estas quatro funções são bem parecidas em seu funcionamento, o que causa muita confusão em quem está começando a estudar a linguagem e hoje, eu tentarei solucionar esta dúvida de uma vez por todas.

include();

A função include() do PHP tem como objetivo incluir (como sugere o nome) um arquivo dentro do outro quando acessado. Caso ocorra algum problema na inclusão deste, será apresentado um Warning (aviso) que não foi possível incluir o arquivo e continuará a exibição da página normalmente sem a inclusão do arquivo. A função include() aceita parâmetros via GET quando chama um arquivo. Confira o exemplo abaixo.

<?php
  //Exemplo de utilização da função include()
  include('./arquivo1.php?perfil=123'); //incluindo o arquivo1.php
  include('./lembrete.html'); //incluindo o arquivo lembrete.html
?>

No exemplo acima, estão sendo incluídos 2 arquivos: arquivo1.php e lembrete.html. Estes arquivos serão incluídos sem problema algum desde que eles estejam no mesmo caminho que foi informado como parâmetro no uso da função include();

require();

A função require() do PHP tem a mesma funcionalidade da função include(), citada acima, com a diferença que se caso o arquivo que você está incluindo não exista (ou não seja encontrado), será gerado um Fatal Error (erro fatal), paralizando a execução de qualquer script que venha após a linha do require(); outra divergência é o fato desta função não aceitar parâmetros via GET para o arquivo chamado. Caso você utilize este parâmetro, ele será ignorado. Confira o exemplo abaixo:

<?php
  //Exemplo de utilização da função require()
  require('./arquivo1.php'); //incluindo o arquivo1.php
  require('./lembrete.html'); //incluindo o arquivo lembrete.html
?>

include_once(); e require_once();

As funções include_once() e require_once() do PHP tem as suas funcionalidades “idênticas” às funções include() e require(), respectivamente. Digo “idênticas” (entre aspas) pois a única diferença entre elas é o fato da funções que possuem o “_once” só permitirem a inclusão do arquivo uma única vez na página.

<?php
  //Exemplo de utilização da função include() e include_once()
  include('./arquivo1.php'); //incluindo o arquivo1.php
  include('./lembrete.html'); //incluindo o arquivo lembrete.html
  include_once('./arquivo1.php'); //tentando incluir o arquivo1.php novamente, ele não será incluso (caso o arquivo não exista, será apresentado um segundo warning)
?>
<?php
  //Exemplo de utilização da função require() e require_once()
  require('./arquivo1.php'); //incluindo o arquivo1.php
  require('./lembrete.html'); //incluindo o arquivo lembrete.html
  require_once('./arquivo1.php'); //tentando incluir o arquivo1.php novamente, ele não será incluso
?>

Bom, acho que por hoje é isso. Espero que tenham gostado e qualquer dúvida, só é perguntar na sessão de comentários logo abaixo. Bons estudos.

Share on TwitterShare on TumblrSave on DeliciousShare via email

Publicado por Ítalo Barboza

3 de agosto de 2011 as 4:00 pm

Posted in PHP

Marcado com , , ,