A Django site.
May 4, 2008

Antonio Ognio
gnrfan
Gnrfan.org
» PHP Best Practices

Yesterday I attended the Ubuntu 8.04 Hardy Heron LTS Release Party event the folks from Ubuntu Peru and Linurp organized here in Lima at Universidad Ricardo Palma. Nice talks on Ubuntu, KDE, GNOME, Drupal and PHP among some other stuff. I particularly liked the talk by the good old Jesus Castagnetto of PEAR and Professional PHP Programming fame. His slides (spanish) are posted at his site. My summary including bits i’ve been adding follows:

  • PHP is an easy language to pick up & learn but it’s a bit tricky to master
  • During the development phase of your project set the error_reporting value of php.ini to E_STRICT in order to get all sort of errors
  • Please set an error log and read it! You are going to need it to monitor your application when it’s deployed for production. Don’t forget to stop displaying errors to the end user in production sites. If you do, chances are you’re disclosing very useful information for an attacker trying to take control of your site or shutting it down.
  • If you’re using clean urls (and you should!) and not using the .php extension for your pages you don’t need to disclose that you’re site is running PHP. Setting the expose_php value to zero in php.ini might be a good idea.
  • Please get rid of code (yours or written by someone else) that depends on registers_globals = On. This configuration option won’t even exists when PHP 6 is released. Having PHP or your own code create global variables automagically from data sent by the user is a major security threat. So please resit the temptation of using it.
  • Please stop using magic quotes. Today they’re not a good idea. Actually they never were a good idea and will be depracated in PHP 6. As the programmer you’re responsible for adding quotes properly to any string that might need them.
  • Since version 5, PHP got exception handling. Please don’t abuse then exception handling mechanism by raising an exception at the minimal user-generated error. Raise an exception instead when a critical condition that is need for your program to continue working properly is not met, specially when you expect some other part of you code catching the exception and doing something about it.
  • Exceptions can consume considerable memory if your stack trace gets big. They are useful but not cheap.
  • Don’t debug you’re code using exclusively echoes, prints and var_dumps. You should be using a proper debugger instead. A very good one is XDebug. You get the extra advantages of getting a full stack trace and profiling capabilities.
  • No matter if you’re a solo coder or part of a team you need to follow coding standard in order to produce a consistent-looking codebase that can be easily read by anyone including yourself. PEAR has a good coding standard that has been proved in many PEAR contributions over a good few years. The Zend Framework provides you with a newer coding stardard (draft) that is also based on PEAR’s.
  • Documenting might be a bit boring but it’s critical for the success of your project over it’s lifetime. If you’re code is non-trivial you’re much better embedding good documentation in it that will help you in the first place to understand that are those lines of code doing when you come back to make changes. A quality tool for generating PHP documentation is phpDocumentor. It’s fast and can generate not just only API docs but tutorials by parsing your code if you learn to use it properly.
  • Please don’t reinvent the wheel. PHP has lots of useful functions that are implemented in C and will definitely run faster than you’re code. If you caught yourself reimplementing native functionality it’s your fault for not reading the manual and keep up with the changes and additions to PHP and it’s core extensions. Know your tool. Investing a bit of time in reading the manual will definitively pay off.

There are a few tips related to OOP with PHP, specially PHP 5:

  • Don’t over-engineer your code. PHP is not Java and in many circumstances you’ll be good using just a simple array which is a native data structure instead of a user defined class. Keep things simple.
  • Don’t use is_a() but instanceof() instead for checking if an object is a member of a class since is_a() was depracated as of PHP 5.

In order to improve the security of your code you can follow this guidelines:

  • You must ALWAYS initialize your variables, specially those involved in authentication, authorization and security checks.
  • Never ever trust your user on providing the right kind of input for your program to work properly. You must always validate that the user’s input is good for you
  • PHP has the filter and ctype extensions for validating user input. You can always use regular expressions for custom validations.

Finally, for performance improvements you have this recommendations available:

  • Don’t use double quotes in strings if there’s no variable interpolation or character escaping taking place. This saves a few miliseconds in each string so if you have many strings in your code and many visits in your website this alone can be a huge CPU and time saver.
  • In many places you can speed things a bit up by avoiding string concatenation. Just use a comma in echo to get the same output effect.
  • Prefix variable incrementation is a bit faster than postfix incrementation so if you’re not assigning the value of the variable before incrementing it you can easily gain a few extra milliseconds and consume less server CPU with this simple change so you ++$i instead of $i++ whenever you have the chance.
  • By all means you must avoid recreating the same dynamic content over and over again if you can be sure it won’t be changing. This is when content caching comes handy. Something as simple as reading a generated HTML chunk from a file in the filesystem instead of issuing again the database queries and/or performing the calculations needed to generate can be a big improvement. Generally cached content is not useful or trusty after some period of time has passed so put your attention in regenerating the cached content when it’s no longer valid.
  • Your own PHP can benefit a lot from using a caching mechanism so PHP doesn’t have to compile your code over and over again if it hasn’t change. Avoid wasting server CPU and response time. APC is a very good code caching solution for PHP and is mantained by Rasmus Lerdorf, the creator of PHP himself.
  • Don’t guess which parts of your code are the bottlenecks. Use a profiling tool instead. Remember XDebug includes a profiler.
  • Even if it’s not something you do at the PHP level you can always take advantage of a data compressing mechanism like Apache’s mod_gzip. Compressing content in both requests and replies is something that has been available in the HTTP specs for a while and you can easily save up to 80% of the bandwidth and response time.

I really think it’s a good idea to use lists like this as check-lists and use the techniques in your projects.

February 15, 2008

Cesar Villegas
slayer
» Bugs en Wordpress: contenido no encontrado y categorias desaparecidas

Encontré 2 problemas en wordpress ( o por lo menos en mi instalación), no sé que problema hubo pero de la noche a la mañana, varios días después de haber actualizado a la última versión 2.3.3 me dí cuenta que el contador bajo terriblemente, entre al panel de administración y todo lucía bien, cargue el blog y todo bien.

No input file specified
Pensé que era una falla del contador, pero al ver Google Analytics encontré el mismo problema, decidí investigar mas a fondo y el resultado fué que había una gran cantidad de post que tenían un problema con el permalink y en vez de visualizar la página aparecía un mensaje de error que decía: No input file specified . Inicialmente pensé que erá el PHP pero no, quedó descartado porque había post que si se visualizaban correctamente, luego me dí cuenta que los feeds tampoco funcionaban. Entonces ví la luz, el problema tenía que ser el .htaccess.

Lo borré. lo hice de nuevo, recreé la estructura de permalinks desde el wordpress y todo seguía igual, asi que no me quedó otra que revisar el código, luego de mucho mirar y casi tirar la toalla, encontré un enlace muy ilustrativo: de como funcionan los permalinks en Wordpress

Fué asi que llegué a la solución, lo que tiene que hacer es lo siguiente:

1.- Editar el archivo wp-includes/vars.php
2.- Busquen una línea que tenga el texto $is_apache = bla bla bla puede ir cualquier cosa aqui dependiendo de tu version bla bla bla
3.- Comentar esa línea anteponiendo “//” para que quede asi // $is_apache = bla bla bla
4.- Agregar una línea que diga exactamente: $is_apache = 1;

Por lo visto hay un problema entre wordpress y como detecta el webserver que estas ejecutando, lógicamente esto aplica para todos aquellos que usen Apache :)

Las categorías se perdieron!
Todo el problema anterior me hizo tomar la decisión de cambiar de hosting, pues fueron 3 días entre que empezó el problema y que yo lo pude solucionar, debido al limitado acceso que tengo al servidor (no tengo privilegios de root), si hubiera sido un problema de apache o php no lo hubiera podido solucionar debido a la falta de privilegios.

Pasé mi blog a DreamHost, todo salió supuestamente bien, hasta que caí en la cuenta que todas las categorías habían desaparecido! todos mis posts aparecían como “Uncategorized”.

Revisé las 3 tablas que tienen que ver con las categorías en wordpress que son las siguientes: wp_categorias, wp_link2cat y wp_post2cat las volví a pasar, pero tenía el mismo problema, me pusé a buscar y encontré que era un problema conocido:
Upgrade caused loss of Categories

El problema es que mi blog no tenía exactamente ese problema, yo no estaba haciendo un upgrade, realmente estaba haciendo una migración sobre un “fresh install”. Hice muchas pruebas, hasta que en ese mismo topic encontré la solución: como forzar el upgrade de tu base de datos en Wordpress, no, no se trata del mysql en realidad, sino del control de versiones interno que tiene Wordpress y que tiene este problema.

La solución es bastante sencilla y rápida
1.- Entra a la consola de mysql y digita
UPGRADE wp_options SET db_version="5183"
2.- Debes usar el número de versión adecuado, no es un número fijo, el número varia de acuerdo a la versión de Wordpress que tengas, aqui una tablita para las ultimas versiones:
2.3.2 = 6124
2.3.1 = 6124
2.3 = 6124
2.2.3 = 5183
2.2.x = 5183
2.2 = 5183
2.1.3 = 4773
2.1.x = 4773
2.1 = 4772
2.0.11 = 3441
2.0.x = 3441
2.0 = 3441

3.- Si no puedes acceder a la consola en mysql, puedes usar Phpmyadmin o el gestor de mysql que tengas y realizas exactamente el mismo cambio, ubicar el campo db_version en la tabla wp_options y cambiarlo.
4.- Desactiva todos los plugins y luego pon en tu navegador
http://www.tublog.com/wp-admin/upgrade.php sigue los pasos y todo se arreglará
5.- Todas las categorías y subcategorías aparecieron otra vez, peeeero mis post seguían uncategorized :P

Por lo visto mi problema era bastante particular y ponerme a categorizar todo de nuevo me da muuuuucha flojera, asi que tenía que encontrar la solución. Luego de mucho investigar, llegué a la conclusión de que había un problema entre las categorías y los tags, desactive todos los plugins, los volví a activar y no paso nada, hasta que se me probé usar la opción de transformar alguna categoría en tag.

Lo hice solo con una para probar y voilá! se arregló todo! como no creo en la magia seguí buscando y la explicación es que todo este rollo se arma por la nueva forma de manejar las categorías y los tags que tiene la versión 2.3.3 de Wordpress.

Por cierto una de las causas conocidas para este problema es la utilización del plugin Google Sitemap Generator que yo lo usaba, pero al pasar al nuevo hosting nunca instalé.

A ver si le sirve de ayuda a alguien :)

October 27, 2007

Cesar Villegas
slayer
» Como escribir un plugin de Wordpress

Mientras tuve problemas con mi servidor inicié una investigación sobre todos los plugins que utilizo para ver si alguno me causaba problemas. De esta forma me puse a revisar mucho código y me entraron ganas de modificar unos cuantos plugins. Asi fue como llegué a DevLounge donde Ronald Huereca ha escrito una magnífica guía sobre como escribir un plugin para wordpress en una serie de 12 artículos cubriendo desde los aspectos básicos de diseño y programación hasta añadir florituras como Ajax y promocionar tu plugin.

Lectura más que interesante :)
How to write a Wordpress plugin

Share This

December 26, 2006

Diego Escalante
dieguito
hack my cow
» Anewt y PHP 5.2

Estaba probando Anewt (Almost No Effort Web Toolkit) escrito por Wouter Bolsterlee y me encontré un error inocente y gracioso acerca de que la clase DateTime ya estaba definida.

Me pareció raro pues el repositorio de Anewt no había tenido cambios en mucho tiempo y pues no tenía mucho sentido que un error tan evidente y grosero estuviese en el último commit del repositorio (el cual data de hace unas semanas). Entonces le pregunté a Rudy si sabía cómo podía averiguar quién y dónde llamaba/era llamada una función pero antes de poder obtener una idea de cómo hacerlo se me vino a la mente que quizá DateTime ya estaba definido en otro lugar (quizá algún paquete de PEAR que había bajado, a pesar que mi sistema está recién instalado). Así que dije:

(01:07:33 AM) dieg0_rm: espera
(01:07:36 AM) dieg0_rm: creo que ya sé qué pasa
(01:07:47 AM) dieg0_rm: tienes idea si DateTime es una palabra reservada en php5.2?
(01:07:53 AM) stone_head: it is
(01:07:59 AM) stone_head: it breaks it all

Eso quiere decir que si tu aplicación tiene una clase con ese nombre estará inexorablemente rota al momento de actualizar a 5.2 :) .

Entonces, aquí un lo que concluímos Rudy y yo:

(01:17:39 AM) dieg0_rm: a ver blogueemos rápidamente sobre esto
(01:17:51 AM) stone_head: claro
(01:17:56 AM) stone_head: collaborative blogging
(01:18:25 AM) dieg0_rm: claro
(01:18:28 AM) dieg0_rm: pondré rápidamente
(01:18:54 AM) dieg0_rm: putos php devs: por qué carajo implementan una clase DateTime en el core de php jodiendo así miles de aplicaciones, pudieron habernos dado la gracia de los namespaces
(01:18:56 AM) dieg0_rm: end of rant
(01:19:02 AM) stone_head: <o/
(01:19:07 AM) dieg0_rm: firmado: rudy y diego
(01:19:13 AM) stone_head: ello

BTW, Feliz navidad!.