Aplicativos em PHP/Apêndices/Segurança/Escrevendo Código Robusto em PHP

Escrevendo Código Robusto em PHP editar

Resumo

  • Evite ter mais que 10 ou 15 arquivos no diretório raiz do seu apache
  • Se a aplicação envia mais que 40KB de dados ou...
  • Aplicação requer mais que 5 segundos para carregar, então está na hora de refazer seu projeto.
  • Caso alguma tabela tenha mais de 15 campos, provavelmente ela tem um projeto equivocado
  • Scripts grandes devem ser divido em menores
A importância de se criar um código robusto é tanto maior quanto maior for a aplicação. Para que o código seja robusto, antes o banco deve ser robusto, ter integridade bem definida, tipos e tamanhos de campos, etc. Padrões ajudam na revisão do código após alguns meses. Até um padrão não muito bom é melhor que nenhum padrão, por todos estarem falando a mesma língua. O menor padrão que se deve utilizar é em um projeto, ou seja, caso não queira adotar um padrão para todos os projetos, pelo menos cada projeto deve usar um único padrão. Simplicidade, clareza e consistência ajudam a evitar erros comuns do código e a mantê-lo. Sempre separe código OO de código procedural. Evite usar comentários tipo shell (#), pois estão em desuso e não serão compatíveis com versões futuras do PHP. Dê preferências aos comentários advindos do C e C++ (// e /* ... */), especialmente ao /* ... */, que é mais eficiente. Também temos os comentários compatíveis com o PHPDocumentor:
/**
  *  Assim temos
  * comentários
  * para documentação
  * compatível com PHPDocumentor
  */

Documentar é mais prático durante a codificação que depois de pronta.

Outra boa prática é a indentação do código, que o torna mais compreensível.

Nomes de Variáveis

Atualmente temos duas linhas, o estilo camelo IntMinhaSoma e usando sublinhados (_), como int_minha_soma. O mais importante é que se escolha um estilo e o utilize em todo o projeto.

Para nomes de variáveis, funções, constantes, classes, etc, nunca utilizar nomes obscuros nem de uma única letra.

Sugestão:

prefixo + tipo + nomevariavel

glb – Global
tmp – Temporária
frm – Variável de formulário


Adicionalmente:

Todas as letras em minúsculas

separar partes com sublinhado (_)

variáveis de loops com $i, $j, $k e assim por diante

$str_consulta e $res_resultado em strings SQL e identificador de resultado

$arr_usuarios;

$glb_int_codigo;

Com variáveis podemos abstrair dados e com funções podemos abstrair várias linhas de código.

Dica: somente crie uma variável se pretende utilizá-la novamente em outro trecho do código. Caso não pretenda, não crie a variável.


Nomes de Constantes

Usar nomes com todas as letras em maiúsculas.


Nomes de Arquivos

Todas as letras em minúsculas (compatibilizar com Unices)

palavras separadas por “_”

Sempre usar a extensão php, mesmo com outras intermediárias

Manter nomes de arquivos com o máximo de 32 caracteres.

Exemplo:

conexao.inc.php


Formatação de Consultas SQL

Palavras-chave SQL devem estar em maiúsculas

$str_consulta = “SELECT * FROM clientes WHERE apelido = 'RibaFS' “;


Operadores

Adicionar espaços antes e após os operadores de atribuição, lógicos, aritméticos e de comparação:

// atribuição
$a = 5; // e não $a=5;
$minha_string .= “alguma coisa”;
$i += 2;

//lógicos e comparação
if (($nome == 'Victor') or ($nome == 'Andrei') )

// aritméticos
$a = (10 * $b) / 20;

Estrutura que se mostra útil:

$int_nome_longo = 8;
$int_curto	     = 5;


Estruturas de Controle

Deixar um espaço em branco antes e após a chave em estruturas de controle.

if () {

Indentar código entre as chaves

Nunca usar a sintaxe alternativa de algumas estruturas de controle:

if (conf): declaracoes endif; // Serão descontinuados

Deixar espaço adicional após “;” nas estruturas for.

for ($i; $i < 10; $i++ ) {

Estruturas Switch ... Case utilizam apenas 1/5 do código de estruturas semelhantes if .. else. Utilizar sempre que possível.

Comentar estruturas de controle aninhadas

for ($x=1; $x<10; $x++) {
	if ($x = = 3) {
		echo “X vale 3”;
	} // if
} // for

Quando temos muitas vale a pena descrever com mais detalhes o final de cada uma.

//OPTION 1
$r = mysql_query('SELECT * FROM someTable LIMIT 1500');
for ($i = 0; $i < mysql_num_rows($r); $i++) {
 print mysql_result($r, $i, 'ColA').mysql_result($r, 	$i, 'ColB');
}

// OPTION 2
while (($row = mysql_fetch_assoc($r)) !== false) {
 print $row['ColA'].$row['ColB'];
}

OPTION2 roda significativamente mais rápido

- Utilizar a tag maxlength em todos os campos de formulário, de acordo com o tamanho dos campos na tabela.

- Criticar em JavaScript ou em PHP todos os campos obrigatórios do form, de preferência criticando o tamanho dos campos, ao invés apenas de se estão vazios (no evento onSubmit do form).

- Adicionar máscara e validação em campos data, CPF, CNPJ, etc.

Outros cuidados com forms

foco em campo inicial, teclas de atalho (accesskey="a", no rótulo do campo sublinhar a a letra da tecla de atalho) e usar tabindex, readonly, etc.

- Evitar código complexo e muito extenso. Sempre que o script crescer muito divida-o em scripts menores.

- Utilizar nomes de fácil identificação em bancos, tabelas, campos, scripts, classes, funções, parâmetros, variáveis, constantes, etc.

- Para consultas em tabelas com muitos registros e que consumam muita memória, usar a função “pg_free_result()”.

- Primeiro termine o sistema, depois cuide melhor de detalhes como segurança, desempenho e design.

- Lembre-se de que um sistema robusto é formado por partes robustas e se além de robusto ele for amigável, os futuros contatos com os usuários (pedidos de suporte) serão reduzidos.

Evitar exclusão de registros. Mas se permitir, sempre solicitar uma confirmação antes de excluir e esta confirmação deve receber informações do banco para ser robusta e não simplesmente fazer a consulta e informar que foi feita.

Exemplo de código de confirmação de exclusão.

(Gerado pelo phpcodegenie)

<?php
$thisCodigo_aluno = $_REQUEST['codigo_alunoField']
?>
<?php
$sql = "SELECT * FROM aluno WHERE codigo_aluno = '$thisCodigo_aluno'";
$result = MYSQL_QUERY($sql);
$numberOfRows = MYSQL_NUMROWS($result);
if ($numberOfRows==0) {  
?>

Desculpe. Nenhum registro encontrado!!

<?php
}
else if ($numberOfRows>0) {
// Vai ao banco e traz o registro
        $i=0;
        $thisCodigo_aluno = MYSQL_RESULT($result,$i,"codigo_aluno");
        $thisNome = MYSQL_RESULT($result,$i,"nome");
        $thisLogin = MYSQL_RESULT($result,$i,"login");
        $thisSenha = MYSQL_RESULT($result,$i,"senha");
        $thisEmail = MYSQL_RESULT($result,$i,"email");
        $thisCurso = MYSQL_RESULT($result,$i,"curso");

}
?>

<h2>Confirmação de exclusão do Registro</h2><br><br>

<table>
<tr height="30">
        <td align="right"><b>Codigo_aluno : </b></td>
        <td><? echo $thisCodigo_aluno; ?></td>
</tr>
<tr height="30">
        <td align="right"><b>Nome : </b></td>
        <td><? echo $thisNome; ?></td>
</tr>
<tr height="30">
        <td align="right"><b>Login : </b></td>
        <td><? echo $thisLogin; ?></td>
</tr>
<tr height="30">
        <td align="right"><b>Senha : </b></td>
        <td><? echo $thisSenha; ?></td>
</tr>
<tr height="30">
        <td align="right"><b>Email : </b></td>
        <td><? echo $thisEmail; ?></td>
</tr>
<tr height="30">
        <td align="right"><b>Curso : </b></td>
        <td><? echo $thisCurso; ?></td>
</tr>
</table>

<h3>Se tem certeza de que deseja excluir o regsitro acima, favor pressionar o botão delete abaixo.</h3><br><br>
<form name="alunoEnterForm" method="POST" action="deleteAluno.php">
<input type="hidden" name="thisCodigo_alunoField" value="<? echo $thisCodigo_aluno; ?>">
<input type="submit" name="submitConfirmDeleteAlunoForm" value="Delete  from Aluno">
<input type="button" name="cancel" value="Voltar" onClick="javascript:history.back();">
</form>


Como usar as Chaves

As formas mais comuns são:

function minhaf() {

}

e

function minhaf() 
{

}

Realmente a última é mais clara e fácil de identificar a chave inicial.


Funções

Deixar um espaço em branco antes e após as chaves. minha_func () {

Nomes de função precisam ser verbos. fazer_sth () é melhor que a_sth ()

Preservar nomes de funções em minúsculas.

Usar “_” para separar as palavras do nome.

Use nomes descritivos mas não muito longos.

Não use espaços extras entre o nome de função e os parêntesis na chamada de funções.

Exemplo:

minha_func();

Documente a função da melhor maneira possível. Idealmente comentários compatíveis com o PHPDocumentor.


Classes

- Usar o estilo camelo para nomes de classes e com inicial maiúscula. NomeEstiloCamelo

-Todas as recomendações acima mencionadas aplicam-se para classes.

class MinhaClasse {
	/* Código da classe */
}

Escrevendo Código Decente

Estrutura do código – criar estrutura de diretórios, arquivo de configuração, padrões de nomes, comentários e formatação

Manipulação de Erros – Checar todas as consultas ao banco e adequadamente exibir os erros para o usuário. Checar todas as possibilidades de erro, como divisões, etc. Em caso de arquivos e diretórios, sempre testar se existem antes de usar. Sempre cheque a normalização de suas tabelas. Caso alguma tabela tenha mais de 15 campos, provavelmente ela tem um projeto equivocado. Se você está usando um campo texto para armazenar datas, também não é coisa boa.

$consulta = pg_query($conexao, $str) or die (“A consulta ao banco falhou”);

Dois exemplos:

$conexao = pg_connect("dbname=databasename user=username password=password") or die("Erro na conexão ao banco: ".pg_last_error());

$query = "CREATE TABLE contacts (
name varchar(50),
surname varchar(50),
email varchar(50)
)";

$query = pg_query($query); // Execute the Query
if($query)
  echo "Tabela Criada"; // Tasta se query funciona
else{
  echo "Erro na consulta! ".pg_last_error();
}


Conexão ao Banco

Criar um script de conexão ao banco e incluir em cada arquivo que for conectar ao banco é muito indicado, pois caso tenha que fazer alteração em algum parâmetro da conexão, basta alterar o script de conexão e não todas as páginas que conectem ao banco. É indicado que se crie um diretório que conterá os scripts que serão incluídos nos demais scripts.


Estrutura de Diretórios

Evite ter mais que 10 ou 15 arquivos em seu diretório. Caso isso aconteça deverá criar uma estrutura de diretórios organizado por categorias.

Critérios de um código Limpo

Eficiência – o código roda o mais rápido e eficiente possível Manutenibilidade – código fácil de entender para outros desenvolvedores. Bem planejado, lógico, adequadamente documentado e fácil de atualizar.

Criar o código o mais modular e reusável possível.

Dividir para Conquistar

É mais fácil trabalhar com um pequeno script do que com um enorme arquivo de um enorme aplicativo. Cada pequeno módulo deve ser o mais genérico possível para que possa ser reutilizado.

Evitar Tecnologias Extras

Evitar o uso de tecnologias que não estejam disponíveis do lado do cliente e requeiram plugins adicionais ao browser, como PDF, Flash, etc. Com isso se estará deixando alguns clientes sem acesso.

Como regra se a aplicação envia mais que 40KB de dados ou se requer mais que 5 segundos para carregar, então está na hora de refazer seu projeto.

Separar código, conteúdo e apresentação

Ajuda muito quanto as 3 camadas estão separadas.

Separar a camada de apresentação (HTML), do código (PHP) e do acesso ao banco.

Com isso podemos ter separados os trabalhos de desenvolvedores e designers.

Se em dúvida sobre se seu Código é Seguro, se pergunte:

Ele é seguro?

É simples e compreensível?

É independente de plataforma?

É rápido o suficiente?

Qualquer sistema que atenderá uma grande quantidade de usuários precisa ser seguro. Isto é ainda mais importante para aplicações com transações comerciais, que armazenem informações como números de cartões de créditos e transmite dados confidenciais.

Lembre bem que colocar sua aplicação na internet estará expondo seu sistema, seu software, seus dados e também seus negócios para a grande rede.

Independente de Plataforma

Atualmente é muito importante a preocupação com a independência de plataforma, pois sistemas como Windows, Linux, Mac OS, UNIX e Solaris não são tão raros.

Aplicativos em PHP criados no Windows rodam nos demais sistemas, desde que não abordem o sistema de arquivos nem caracteres de new line.

Outra boa idéia é utilizar uma camada de abstração de bancos de dados, para deixar o aplicativo disponível para qualquer dos bancos suportados pelo PHP e cuja alteração de banco requeira apenas mudar o nome do banco na conexão. Uma ótima alternativa é a Pear/DB.

Paginação é um bom recurso, que alivia a carga do banco e torna mais rápida a carga da página. Sempre perseguir um código rápido, pois ninguém gosta de esperar muito.


Referências

- Modelagem e Normalização de Dados de Shadow Brujah (site PHPBrasil.com)

- PHP Coding Standard - http://www.phpfreaks.com/print.php?cmd=tutorial&tut_id=35

- http://www.phpbuilder.com/columns/perdue20030310.php3 - Writing Clean and Efficient PHP Code - http://www.devshed.com/c/a/PHP/Writing-Clean-and-Efficient-PHP-Code/ - Using PostgreSQL With PHP - http://www.phpfreaks.com/print.php?cmd=tutorial&tut_id=60 - Develop rock-solid code in PHP - http://www-128.ibm.com/developerworks/library/wa-phprock1/