Estandares Generales

error_reporting(E_ALL) es tu amigo. Utilízalo, junto con ini_set(‘display_errors’, ‘On’), para ver todas las advertencias del compilador de PHP, saber qué métodos están depreciados, índices inexistentes, etc.

Estructura

  • El código debe usar cuatro espacios para la identación en vez de usar el tabulado. Esto minimiza problemas con otras herramientas de desarrollo.
  • Las llaves de apertura deben ir en la siguiente línea y la llave de cierre debe ir en la siguiente línea después del cuerpo.
  • Las llaves de apertura en las estructuras de control debe ir en la misma línea y las llaves de cierre deben de ir después del cuerpo.
  • Los paréntesis en las estructuras de control no deben usar espacios antes o después.
  • Añadir un solo espacio después de cada limitador de coma.
  • Añadir un solo espacio alrededor de los operadores (==, &&, …)
  • Añadir una línea en blanco antes de una declaración de return, a no ser que esté dentro de una declaración como un grupo como if.
  • Usa llaves para indicar  el control de la estructura sin tener en cuenta el número de declaraciones que el grupo pueda contener.
  • Define una clase por archivo.
  • Declara las propiedades de clase antes que los propios métodos de clase.
  • Declara los métodos públicos primero, después los métodos protegidos y finalmente los métodos privados.

No emplear etiquetas cortas

Para que el intérprete de PHP ejecute un código, éste ha de estar delimitado por las etiquetas de apertura y cierre de PHP: <?php ?>. Si en la configuración de PHP de nuestro servidor (archivo php.ini) se permite el uso de etiquetas cortas (<? ?>) el script se ejecutará exactamente igual. Pero, ¿qué ocurre si cambiamos a otro servidor en el que no estén habilitadas? Nuestras páginas dejarán de funcionar como esperamos y, lo que es más grave, puede resultar en que todo nuestro código fuente se imprima por pantalla como texto plano (ya que no habrá sido interpretado), quedando a disposición de cualquier personaje.

<?php
echo "Hello World";
?>

Operadores de comparación: === vs ==

Los operadores, como +, +=, -, -=, *, *=, /, /=, %, %=, =, ==, ===, !=, >, >=, >>, <, <=, <<, =>, &, &&, |, ||, ?, etc., deben escribirse con espacios a ambos lados.

== (o !=) compara el valor, mientras que === (o !==) compara el valor y el tipo.

Dado que en PHP las variables no tienen un tipo asignado y éste puede cambiar “al vuelo” en tiempo de ejecución, conviene tener en cuenta cómo serán evaluadas las comparaciones en PHP:

<?php
$a = 0; $b = "0" $c = false; var_dump($a
==
$b);
// 0 == 0 -> true
var_dump($a)
===
$b);
// 0 == 0 && (integer) == (string) -> false
var_dump($a
==
$c);
// 0 == false -> true 

Por otro lado, existen funciones que retornan un número entero. Como el valor lógico de cualquier entero es true, exceptuando el cero, que es false, deberemos tenerlo en cuenta a la hora de evaluar nuestras condiciones. Por ejemplo, la función strpos() busca la posición de la primera ocurrencia de una subcadena dentro de otra:

<?php
$cadena = 'formación online';

$buscamos = 'm'; // presente en $cadena
$posicion = strpos($buscamos, $cadena); // $posicion = 3

$buscamos = 'z'; // ausente en $cadena
$posicion = strpos($buscamos, $cadena); // $posicion = false

$buscamos = 'f'; // presente en $cadena
$posicion = strpos($buscamos, $cadena); // $posicion = 0

Por lo tanto, si queremos comprobar la presencia o no de una cadena con strpos() no debemos comparar por valor (==) sino por tipo y valor (===).

Concatenación de cadenas, comillas simples(‘) vs comillas dobles(“)

Cuando trabajes con cadenas, evita siempre el uso de comillas dobles. La razón es que PHP analiza el contenido de las comillas dobles en búsqueda de variables que deban ser interpretadas, resultando en un tiempo de ejecución mayor.

Emplea siempre la función echo y concatena las cadenas con comas:
echo ‘Hola’, $nombre, ‘, ¿qué te trae por aquí?  requerirá menos tiempo al compilador que echo ‘Hola’ . $nombre . ‘, ¿qué te trae por aquí?’.
Por lo visto en el punto anterior, el “peor caso posible” sería print “Hola $nombre, ¿qué te trae por aquí?”

Variables

Las variables usadas en cualquier aplicación deben tener nombres que las identifiquen, es decir, nombres como “a”, “b” o “c” no se deberían usar sino que deberían tener un nombre coherente con con lo que contienen. En el siguiente ejemplo los nombres de las variables son cortos por lo que no se identifica su significado:

$a = 0, $b = 0, $c = 0;
if($a > 10 && $b > 20 && $c > 30) {
	return true;
} else {
	return false;
}

Este ejemplo debería ser:

$hora = 0, $minuto = 0, $segundo = 0;
if($hora > 10 && $minuto > 20 && $segundo > 30) {
	return true;
} else {
	return false;
}

Sólo en el caso de que la variable sea lo demasiado genérica para no tener un nombre concreto (por ejemplo el índice de un bucle) ésta se declarará con el nombre de “i” siguiendo el orden alfabético en caso de varios bucles anidados (“i”, “j”, “k”,…).

Nota: Utilizar en nombres de variables el prefijo “var” pegado al nombre en lowerCamelCase con esto se evita que el nombre sea igual a los de las clases, funciones, etc. y minimizando errores de sobre escritura en otras áreas como los nombre de las clases, funciones, etc.

Los nombres largos de las variables se escribirán en lowerCamelCase.

Siempre inicializar las variables

El propósito de esto es que la variable no quede suelta y pueda ser alterada mediante un error de programación o por algún ataque que se realice a la página.
Ejemplo:

if (check_user($_POST['username'], $_POST['password'])
$login = false;

if ($login) {
ingrese_pagina_segura();
}

Como podemos ver la variable login no fue inicializada, al pasar al segundo “if” donde, la variable si fue alterada puede pasar como verdadera, para esto es mejor siempre inicializarle como se muestra enseguida

$login = false;

if (check_user($_POST['username'], $_POST['password'])
$login = true;

if ($login) {
ingrese_pagina_segura();
}

Búsqueda de cadenas y patrones case insensitive

La búsqueda de una cadena sin importar mayúsculas/minúsculas (stripos()) es entre un 400% y un 600% más lenta que su equivalente case sensitive, strpos()).
En cuanto a las expresiones regulares, las búsquedas sensibles, preg_match(“/$patron/”, $cadena), son, como norma, ligeramente más eficaces que su equivalente no sensible: preg_match(“/$patron/i”, $cadena).
Si las coincidencias se realizan de modo iterativo (dentro de un bucle for, while, foreach), es recomendable convertir a lowercase o uppercase antes y realizar las operaciones en su versión case sensitive.

Convenciones

  • Los nombres de las clases en MixedCase. Ejemplo: ElNombreDeMiClase
  • Los nombres de los métodos en camelCase. Ejempo: nombreDelMetodo()
  • Las constantes siempre en ALL_CAPS. Ejemplo: COLOR_DEFINIDO_PARA_MI
  • Las variables, propiedades y parámetros en camelCase. Ejemplo: $variableEnLaQueAlmacenoAlgo
  • Los métodos y variables que no sean públicos, precedidos por un guión bajo (underscore-prefixed). Ejemplo: $_miPalabraSecreta

Veámoslo en un ejemplo:

<?php  
class MyNewClass{
    const LIMIT_OF_ITERATIONS = 10;
    public $myProperty;
    public $myOtherProperty;
    protected $_myProtectedProperty; // observa guión bajo por no ser public

    // constructor 
    function __construct(){
    }

    public function hacerAlgoConMiClase($parametroRecibido){
        for ($i = 0; $i < self::LIMIT_OF_ITERATIONS; $i++){
            // lo que sea
        }
    }

    public function getMyProtectedProperty(){
        return $this->_myProtectedProperty;
    }
}

Emplea un Entorno de Desarrollo Integrado (IDE)

Un IDE es un editor de código que ofrece la posibilidad de depurar, autocompletar e identar el código. Existen multitud de alternativas, gratuitas y de pago. Entre las opciones gratuitas destacan Eclipse y Netbeans; por su parte, Zend Studio y PHP Designer destacan como opciones de pago.

Separa y reutiliza tu código

Evita tener archivos con cientos o miles de líneas. Agrupa las funciones que vayas a emplear con frecuencia en archivos e inclúyelos para su posterior reutilización. Ejemplo:

<?php 
class General{
    ...
    function date_sql_screen($fecha,$inarray=false,$lang="en",$sep="/"){
      $fechanor="";
      preg_match("/([0-9]{2,4})-([0-9]{1,2})-([0-9]{1,2})/", $fecha, $frev);
      if($frev){
	if($inarray){ return $frev; }
	   if($lang=="en"){
	      $fechanor=date("m".$sep."d".$sep."Y",mktime(0,0,0,$frev[2],
                        $frev[3],$frev[1]));
	   } else {
	      $fechanor=date("d".$sep."m".$sep."Y",mktime(0,0,0,$frev[2],
                        $frev[3],$frev[1]));
	   }
	}
	return $fechanor;
      }
}

Así, si alguna vez queremos convertir una fecha en formato timestamp a un formato con el que estamos más familiarizados, sólo tenemos que hacer <?php echo General::date_sql_screen($myDate) ?>.

Al iterar arrays, fija el valor máximo fuera del bucle

Cada llamada al método count() aumenta hasta en un 50% el tiempo de ejecución, según el tamaño del array.

// mal
for ($i = 0, $i < count($miArray); $i++){
   ... 
}
// bien
$limite = count($miArray);
for ($i = 0; $i < $limite; $i++){
    ...
}

Mantén las opciones de configuración en un archivo

A medida que la aplicación vaya creciendo se necesitará acceder en distintos lugares a determinados valores. Almacenándolos todos en un único lugar, se evitará tener que modificar todos los archivos cada vez que haya un cambio. Imagina que se programa un carrito de compra y en un determinado momento hay que cambiar el IVA(Impuesto).

Incluyendo código

include, require y sus derivados (include_once, require_once) son sentencias, no métodos. No debe ponerse la ruta al fichero entre paréntesis.
Emplea siempre include o require en vez de include_once o require_once para que el cacheado de código sea más efectivo.

Codificación de caracteres

Emplea UTF-8 (sin BOM) en lugar de ANSI. Lo que en ANSI u otra codificación
puede ser un determinado caracter (una eñe, por ejemplo), en otra codificación puede ser algo completamente distinto. Si tu público emplea tu misma codificación no hay problema pero, si en un momento dado alguien de, por ejemplo, Rusia entra en tu página, verá la pantalla llena de caracteres sin sentido.
Si tu web va a estar disponible en más de un idioma, es indispensable que tu codificación sea UTF-8 (incluyendo la codificación y colación de la base de datos).

El BOM es un carácter 0xFEFF son la serie de caracteres 0xef 0xbb 0xbf que se coloca al comienzo de los archivos y que se usa como marca para indicar que el texto está codificado en UTF-8; en un texto con codifcación ISO-8859-1 se representaría como “”.

Minimiza el número de variables globales

Operar con variables globales es en torno a un 200% más costoso que hacerlo con locales.

No implementes todas las estructuras de datos como objetos

Los array son más rápidos y consumen menos memoria que instanciar un objeto.

Incrementar o Decrementar variables: ++$i vs $i++

Pre-incrementar (++$i) es en torno a un 10% más rápido que post-incrementar ($i++). La razón es que cuando hacemos post-incremento, PHP necesita crear una variable temporal en la que almacenar el valor a ser incrementado.

Minimiza el número de consultas a la base de datos

Realizar una consulta es costosa en términos temporales. En todas aquellas ocasiones en que los datos no vayan a cambiar con mucha frecuencia, es interesante realizar una única vez la consulta y almacenar el resultado de ésta en un archivo de texto plano. Cuando se produzcan cambios en la consulta, se vuelve a generar el archivo a ser incluido. Por ejemplo: imagina que tienes una web de películas, y en algún sitio de la página se ve el listado de películas mejor valoradas. Para obtener las diez películas mejor valoradas tendrías que hacer una consulta similar a la siguiente:

$sqlVotos = 'SELECT p.id, p.titulo, SUM(v.voto) AS suma_votos, 
	COUNT(v.id) AS numero_votos, 
	(SUM(v.voto)/COUNT(v.id)) AS valoracion 
	FROM peliculas p 
INNER JOIN votos v ON p.id=v.id 
GROUP BY v.id_pelicula
ORDER BY valoracion DESC 
LIMIT 0,10';
$resVotos = mysql_query($sql);
$votos = mysql_fetch_array($res, MYSQL_ASSOC);

echo "<h3>Mejor valoradas</h3>n<ul class="list">";
foreach ($votos as $voto){
    echo '<li><a href="....">' . $voto['titulo'] 
	. ' (' . $voto['valoracion'] . ')</a></li>' . "n";
}
echo '</ul>';

Este script debería ejecutarse para todas y cada una de las peticiones de página que tuviera tu web. Lo que podemos hacer es ejecutar el siguiente código cada vez que se produzca una votación, o bien un Cron que se ejecute cada 30 minutos o el intervalo que consideremos:

$filename = PATH_TO_VOTACIONES_FILE . 'votos.txt';  // ruta al fichero
$handle = fopen($filename, 'w+'); // abrimos el fichero
// ejecutamos la consulta anterior ($sqlVotos / $resVotos)
foreach ($votos as $voto){
    fwrite($handle, '<li><a href="...">'. $voto['titulo'] 
	. ' (' . $voto['valoracion'] . ')</a></li>' . "n";
}
fclose($handle);

Entonces, sólo tendríamos que hacer un require PATH_TO_VOTACIONES_FILE . ‘votos.txt’; para mostrar los votos.

isset()

La función isset() (isSet) resulta de una utilidad tremenda. Nos sirve tanto para saber si una determinada variable ha sido inicializada como para comprobar que un índice existe e incluso para trabajar con longitudes de cadenas de un modo más eficiente: Si en un determinando momento necesitamos comprobar que una cadena tiene al menos una determinada longitud, por ejemplo que el nombre de usuario tenga más de 4 caracteres, lo más inmediato que se nos puede ocurrir es utilizar strlen()

if (strlen($username) < 5){
    ....
}

Pero, en tanto que strlen es una función, PHP necesita realizar un trabajo previo para ejecutar la llamada (convertirla a lowercase y buscarla en la tabla hash de funciones), además de ejecutar la propia función.

Por contra, isset no es una función sino una construcción del lenguaje. Esto significa que PHP no tendrá que hacer ninguna operación previa ni habrá sobrecarga.

Así, si queremos comprobar que una variable tiene más de una determinada longitud, podemos hacerlo de un modo más efectivo de la siguiente manera:

if (isset($username{5})){
    ....
}
administratorEstandares Generales

Deja un comentario