7 coisas simples em PHP que alguns ainda complicam
É comum ver scripts com dezenas de linhas de código pra fazer algo extremamente simples. Fica aqui meu apelo desesperado com algumas dicas rápidas.
1 – Listar 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:
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:
$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:
'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:
parse_str($url['query'], $query);
echo $query['q'];
// anneke van giersbergen
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:
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:
'cidade' => 'Rio de Janeiro',
'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:
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:
$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:
// Amanhã: domingo
echo 'Próxima segunda: ', strftime('%d de %B de %Y', strtotime('next monday'));
// Próxima segunda: 01 de junho 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:
$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.




Dicas interessantes, não conhecia o que apresentou na 2ª e na 4ª dica. São formas relmante simplistas de se montar e ler querystrings e de se submeter requisições remotas.
Até mais.
Ótimo post! Parabéns. Realmente existe muita gente que ainda dificulta as coisas.
Abraços
[...] this article: 7 coisas simples em PHP que alguns ainda complicam « garotosopa Share and [...]
Muito bom!!!! Parabéns!
Nossa, nao conhecia esse 4 =o
parabens ;D
Mto legal estas dicas.
Outra coisa q costumo usar, é ao invés de $_POST['variavel'] pra pegar cada variável de um POST de formulário, utilizo no início do arquivo um
extract($_POST). E com isso, extraio todas variáveis vindas do POST e uso direto como variável $variavel.
Abs
Bill, fazer extract($_POST) é extremamente perigoso, você pode acabar sobrescrevendo alguma variável por engano.
Experimente, por exemplo, submeter um formulário com um input hidden name=”_SERVER[REMOTE_ADDR]” value=”123″ e o seu script vai passar a considerar outro IP do usuário.
Pior ainda, dependendo de como você faz a autenticação, submeter name=”_SESSION[username]” value=”admin” pode ser desastroso.
Dicas muito uteis. Obrigado!
Bem útil =]
Quanto ao POST, voce pode usar os flags do extract pra adicionar um prefixo =}
ou num foreach($_POST) mesmo
extract($_POST, EXTR_PREFIX_ALL, “prefixo”);
ou
foreach($_POST as $key=>$value){
$_{$key} = $value;
}
o foreach e ‘melhor, ja que voce pode filtrar os dados, tipo com o addslashes direto, sem fazer um por um
Rond, não esqueça que você deve tratar esses dados.
foreach($_POST as $key=>$value){
$_{$key} = addslashes($value);
}
ou funcao propria sua, tanto faz.
por isso citei o foreach pra tratar =]
[...] http://garotosopa.wordpress.com/2009/05/30/7-coisas-simples-em-php-que-alguns-ainda-complicam/ [...]
Parabéns pelo post!
Boaaaa, sopa! ;-)
Excelentes dicas! Diretas e objetivas.
Muito bom artigo: criativo e útil.
Ficou muito legal sopa, livrou muitos caracteres digitados no #php-br :)
Agora é só copy/paste a url no #!
Valeu!!
o item 7.. ainda existe quem complique e não são poucos.
e por mais que vc explique nao dão ouvidos..
[...] fazer um comentário » Bom, vou fazer uma série de posts dizendo sobre coisas simples de se fazer em C++ que muitos ainda complicam. A idéia surgiu do post de um colega. [...]
Muito bom!
Esse Garotosopa parece um cara muito estranho pra mim, mas até que algumas dicas foram excelentes, principalmente o POST com file_get_contents(). Queria chegar a ser uma partícula infinitesimal do cocô do micróbio que fica nos pés dos sapatos dele.