O cómo desarrollar bien en PHP y no morir en el intento
Empecemos por el principio. Desarrollar bien en PHP, no es fácil. Una de las características innatas de PHP es que es realmente fácil iniciarse en él y empezar a desarrollar “cosas que se véan”. Pero llegar a dominarlo y a doblegarlo a nuestra voluntad para hacer cosas realmente cool, no es fácil. Por eso aquí os mostramos una pequeña serie de posts donde explicaremos algunas best practices que se deberían aplicar. Let’s go!
Cuídame ese tipo!
Afrontémoslo. PHP es un lenguaje de tipado débil. Y por ello el propio intérprete actúa con reglas específicas cuando tiene que gestionar conflictos entre tipos. Es por ello que si hemos de realizar alguna operación o cálculo que implique jugar con los tipos deberíamos usar operadores seguros para tipos.
<?php
$string = 'Hola a todos!';
if (strpos($string, 'H')) {
$string .= ' Gracias por venir!';
}
echo $string; // Imprimirá "Hola a todos!"
El ejemplo correcto sería el siguiente
<?php
$string = 'Hola a todos!';
if (false !== strpos($string, 'H')) {
$string .= ' Gracias por venir!';
}
echo $string; // Imprimirá "Hola a todos! Gracias por venir!"
Podéis encontrar una referencia completa de tipos y operadores en el manual de PHP: tipos y operadores.
No usarás variables globales
Esta máxima y desarrollando bajo auténtica Orientación a Objetos debería ser un mandamiento. En general, ya no solo con PHP, no es recomendable usar el scope global para almacenar variables. La razón es que puede ser que entre diferentes componentes de nuestras aplicaciones haya colisiones con el uso de ese scope global. Y cosas que use un componente acaben siendo sobreescritas por otro componente.
<?php
$myDb = new PDO(...);
function getRowSet()
{
global $myDb;
return $myDb->query('SELECT ...');
}
function getAnotherRowSet()
{
global $myDb;
$myDb = new PDO(...);
return $myDb->query('SELECT ...');
}
$rowSet = getRowSet();
$anotherRowSet = getAnotherRowSet();
$thirdRowSet = getRowSet();
Aunque tampoco sería la mejor solución, hay quién utiliza un Registry pattern para mantener ordenado y centralizado el uso de globals.
<?php
class Registry extends ArrayObject
{
private $_instance;
private function __construct() {}
public function __clone()
{
throw new Exception('This object cannot be clonned!');
}
public static function getInstance()
{
if (null === static::$_instance) {
static::$_instance = new static();
}
return static::$_instance;
}
}
Registry::getInstance()->offsetSet('test', 'stringTest');
Aunque sin duda la mejor solución, es intentar desacoplar cada componente de nuestra aplicación e inyectar las dependencias que cada uno precise, ya sea por un Dependency Injection Container o bien de la manera “tradicional” (constructor injection, setter injection o interface injection).
Desarrollar en E_STRICT
E_STRICT es una constante de PHP que indica un nivel de reporting de errores. Si se habilita PHP va a sugerir cambios en el código a modo de asegurar la compatibilidad con versiones posteriores de PHP.
Con la versión 5.4.0 de PHP a punto de salir del horno no hay excusa para no desarrollar en E_STRICT, puesto que se va a incluir dentro de E_ALL.
Entrecomíllame. echo vs printf
Existe diferencia entre usar comillas dobles o comillas simples. PHP no las trata exactamente igual. La diferencia reside en que PHP permite la interpolación de variables dentro de un string delimitado por comillas dobles. Su uso es desaconsejable primero por motivos de seguridad y segundo por motivos de rendimiento. Poniendo por caso que algún atacante lograra inyectar valores arbitrários en vuestro código, hacer uso de la interpolación de variables puede suponer un riesgo de vulnerabilidad dentro de vuestra aplicación
<?php
if (array_key_exists('submit-btn', $_POST)) {
// Vulnerabilidad muy muy obvia
// a modo de ejemplo
$firstName = $_POST['firstname'];
$path = __DIR__ . "/user/profiles/$firstname.txt";
@readfile($path);
}
Lo mejor es usar comillas simples. Son más rápidas, pues PHP no tiene que buscar referencias a variables, y en algunos casos pueden ayudar a mitigar el riesgo de inyectar valores arbitrários en vuestro código.
Por otra parte existe la disyuntiva de usar echo o printf. En este caso y sin duda alguna el más rápido de los dos es echo. Y si tenéis que concatenar alguna variable al string que se le pasa a echo, hacedlo con comas pues también es más rápido.
<?php
$string = ' Gracias por venir!';
printf('Hola a todos' . $string); // Lento
echo 'Hola a todos' , $string; // Rápido
APC for the win and glory
APC es una extensión de PHP (disponible vía PECL) que proporciona una capa de cache de opcode que trae consigo PHP y su activación y utilización es totalmente gratuita. El opcode o código operacional es código interpretado por la máquina que especifica parte de una instrucción. Solo por activarlo vuestra aplicación va a experimentar una ganancia en términos de rendimiento. Es casi obligado su uso. Carlos Buenosvinos da toda una serie de pautas para optimizar el rendimiento de APC, que es casi lectura obligada.
> pecl install apc > echo "extension=apc.so" >> /etc/php5/conf.d/apc.ini
Nota: En este último snippet de código en shell, se presupone que PHP escanea el directorio /etc/php5/conf.d en busca de archivos ini. Deberá cambiarse apropiadamente.
Ya para concluir
Éste es la primera entrada de dos que hablan de best practices en PHP. Es importante aplicar estas best practices, dan al código excelencia y hacen que sea sexy. Podéis encontrar los snippets de código en formato repositorio de git en Github (es un gist).