Hay mucha información obsoleta en la Web que lleva por mal camino a los nuevos usuarios de PHP, propagando malas prácticas y el código inseguro. PHP: La Manera Correcta es una referencia rápida y fácil de leer, referencia rápida para los estándares de codificación PHP más populares, enlaces a tutoriales autorizados y lo que los colaboradores consideran las mejores prácticas en la actualidad.
No existe una fórmula única para utilizar PHP. Este sitio web pretende introducir a los nuevos desarrolladores de PHP PHP a algunos temas que pueden no descubrir hasta que sea demasiado tarde, y tiene como objetivo dar a los profesionales experimentados algunas ideas frescas sobre los temas que han estado haciendo durante años sin reconsiderarlo nunca. Este sitio web tampoco le dirá qué herramientas utilizar, sino que sino que le sugerirá varias opciones y, cuando sea posible, explicará las diferencias de enfoque y uso.
Este es un documento vivo y seguirá actualizándose con más información útil y ejemplos a medida que estén disponibles. y ejemplos útiles a medida que estén disponibles.
PHP: La Manera Correcta está traducido a muchos idiomas:
La versión más reciente de PHP: La Manera Correcta también está disponible en formato PDF, EPUB y MOBI. Ir a Leanpub
¡Ayude a hacer de este sitio web el mejor recurso para los nuevos programadores de PHP! Contribuir en GitHub
Si se está iniciando en PHP, comience con la versión estable actual de PHP 8.3. PHP 8.x añade muchas características nuevas con respecto a las versiones anteriores 7.x y 5.x. El motor se ha reescrito en gran medida, y PHP es ahora incluso más rápido que las versiones anteriores. PHP 8 es una actualización importante del lenguaje y contiene muchas nuevas funciones y optimizaciones.
Deberías intentar actualizar a la última versión estable rápidamente - PHP 7.4 ya ha llegado al final de su vida útil. Actualizar es fácil, ya que no hay muchas diferencias de compatibilidad con versiones anteriores. PHP 8.0, PHP 8.1, PHP 8.2, PHP 8.3. Si no está seguro de en qué versión se encuentra una función o característica, puede consultar la documentación de PHP en el sitio web php.net.
Con PHP 5.4 o posteriores, puede empezar a aprender PHP sin necesidad de instalar y configurar un servidor web completo. Para iniciar el servidor, ejecute el siguiente comando desde su terminal en la raíz web de su proyecto:
macOS 12 (Monterey) y posteriores no vienen preempaquetados con PHP. Las versiones anteriores de macOS incluyen PHP pero no incluyen la última versión estable. Hay varias formas de instalar la última versión de PHP en macOS.
Homebrew es un gestor de paquetes para macOS que te ayuda a instalar fácilmente PHP y varias extensiones. El repositorio central de Homebrew proporciona “fórmulas” para PHP 7.4, 8.0, 8.1, 8.2 y PHP 8.3. Instala la última versión con este comando:
brew install php@8.3
Puede cambiar entre las versiones de PHP de Homebrew modificando su variable PATH
. Alternativamente, puede usar brew-php-switcher para cambiar de versión de PHP automáticamente.
También puede cambiar manualmente entre versiones de PHP desvinculando y vinculando la versión deseada:
brew unlink php
brew link --overwrite php@8.2
brew unlink php
brew link --overwrite php@8.3
El proyecto MacPorts es una iniciativa de código abierto para diseñar un sistema fácil de usar paracompilar, instalar y actualizar software de código abierto basado en línea de comandos, X11 o Aqua en el sistema operativo macOS.
MacPorts soporta binarios pre-compilados, por lo que no necesitas recompilar cada dependencia desde los archivos tarball fuente, esto te salva la vida si no tienes ningún paquete instalado en tu sistema.
En la actualidad, puede instalar php54
, php55
, php56
, php70
, php71
, php72
, php73
, php74
, php80
, php81
, php82
o php83
utilizando el comando port install
, por ejemplo:
sudo port install php74
sudo port install php83
And you can run select
command to switch your active PHP:
sudo port select --set php php83
phpbrew es una herramienta para instalar y gestionar múltiples versiones de PHP. Esto puede ser realmente útil si dos aplicaciones/proyectos requieren diferentes versiones de PHP, y no está utilizando máquinas virtuales.
Otra opción popular es php-osx.liip.ch que proporciona métodos de instalación de una línea para las versiones 5.3 a 7.3. No sobrescribe los binarios PHP instalados por Apple, sino que instala todo en una ubicación separada. (/usr/local/php5).
Otra opción que le da control sobre la versión de PHP que instala, es compilarlo usted mismo. En ese caso asegúrese de tener instalado Xcode o el sustituto de Apple “Command Line Tools for XCode” descargable desde el Centro de Desarrolladores de Apple.
Las soluciones listadas arriba se encargan principalmente del propio PHP, y no suministran cosas como Apache, Nginx o un servidor SQL. Las soluciones “todo en uno” como MAMP y XAMPP instalarán estas otras partes del software por usted y las unirán todas, pero la facilidad de configuración tiene como contrapartida la falta de flexibilidad.
Puede descargar los binarios en windows.php.net/download. Después de la extracción de PHP, se recomienda establecer el PATH a la raíz de su carpeta PHP (donde se encuentra php.exe) para que pueda ejecutar PHP desde cualquier lugar.
Para el aprendizaje y el desarrollo local, puede utilizar el construido en el servidor web con PHP 5.4 + por lo que no necesita preocuparse de configurarlo. Si desea una solución “todo-en-uno” que incluya un servidor web completo y MySQL también entonces herramientas como como XAMPP, EasyPHP, OpenServer y WAMP le ayudará a poner en marcha rápidamente un entorno de desarrollo Windows. Dicho esto, estas herramientas serán un poco diferentes de las de producción, así que ten cuidado con las diferencias de entorno si estás trabajando en Windows y desplegando en Linux.
Si necesita ejecutar su sistema de producción en Windows, IIS7 le proporcionará la mayor estabilidad y el mejor rendimiento. Puedes usar phpmanager (un plugin GUI para IIS7) para que la configuración y gestión de PHP sea más sencilla. IIS7 viene con FastCGI integrado y listo para usar, sólo necesitas configurar PHP como manejador. Para soporte y recursos adicionales existe un área dedicada en iis.net para PHP.
Por lo general, la ejecución de su aplicación en diferentes entornos en el desarrollo y la producción puede dar lugar a errores extraños que aparecen cuando usted va a producción. Si estás desarrollando en Windows y desplegando en Linux (o en cualquier otro sistema que no sea Windows) entonces deberías considerar el uso de una Máquina Virtual.
Chris Tankersley tiene una entrada de blog muy útil sobre qué herramientas utiliza para hacer desarrollo PHP usando Windows.
La mayoría de las distribuciones GNU/Linux vienen con PHP disponible desde los repositorios oficiales, pero esos paquetes usualmente están un poco atrasados con respecto a la versión estable actual. Existen múltiples formas de obtener versiones más recientes de PHP en dichas distribuciones. En las distribuciones GNU/Linux basadas en Ubuntu y Debian, por ejemplo, las mejores alternativas para paquetes nativos las proporcionadas y mantenidas Ondřej Surý, a través de su Archivo Personal de Paquetes (PPA) en Ubuntu y DPA/bikeshed en Debian. Encontrarás las instrucciones para cada uno de ellos más abajo. Dicho esto, siempre puedes usar contenedores, compilar el código fuente PHP, etc.
Para distribuciones Ubuntu, el PPA de Ondřej Surý proporciona versiones de PHP soportadas junto con muchas extensiones PECL. Para añadir este PPA a su sistema, realice los siguientes pasos en su terminal:
En primer lugar, añada el PPA a las fuentes de software de su sistema mediante el comando
sudo add-apt-repository ppa:ondrej/php
Después de añadir el PPA, actualice la lista de paquetes de su sistema:
sudo apt update
Esto asegurará que su sistema pueda acceder e instalar los últimos paquetes PHP disponibles en el PPA.
Para las distribuciones basadas en Debian, Ondřej Surý también proporciona un bikeshed (equivalente en Debian a un PPA). Para añadir el bikeshed a su sistema y actualizarlo, siga estos pasos:
Asegúrese de que tiene acceso de root. Si no es así, es posible que tenga que utilizar sudo
para ejecutar los siguientes comandos.
Actualice la lista de paquetes de su sistema:
sudo apt-get update
Instale lsb-release
, ca-certificates
, y curl
:
sudo apt-get -y install lsb-release ca-certificates curl
Descargue la clave de firma del repositorio:
sudo curl -sSLo /usr/share/keyrings/deb.sury.org-php.gpg https://packages.sury.org/php/apt.gpg
Añada el repositorio a las fuentes de software de su sistema:
sudo sh -c 'echo "deb [signed-by=/usr/share/keyrings/deb.sury.org-php.gpg] https://packages.sury.org/php/ $(lsb_release -sc) main" > /etc/apt/sources.list.d/php.list'
Por último, actualice de nuevo la lista de paquetes de su sistema:
sudo apt-get update
Con estos pasos, su sistema será capaz de instalar los últimos paquetes PHP desde bikeshed.
Una pregunta común entre los que empiezan a escribir programas para la web es: “¿dónde pongo mis archivos?”. A lo largo de los años, la respuesta ha sido consistentemente “donde está el DocumentRoot
”. Aunque esta respuesta no es del todo completa, es un buen punto de partida.
Por razones de seguridad, los archivos de configuración no deben ser accesibles por los visitantes de un sitio; por lo tanto, los scripts públicos se guardan en un directorio público y las configuraciones y datos privados se guardan fuera de ese directorio.
En cada equipo, CMS o framework en el que uno trabaja, cada uno de ellos utiliza una estructura de directorios estándar. Sin embargo, si uno está empezando un proyecto por si mismo, saber qué estructura de sistema de archivos utilizar puede ser intimidante.
Paul M. Jones ha realizado una fantástica investigación sobre las prácticas comunes de decenas de miles de proyectos de github en el ámbito de PHP. Ha compilado una estructura estándar de archivos y directorios, el Standard PHP Package Skeleton, basado en esta investigación. En esta estructura de directorios, DocumentRoot
debe apuntar a public/
, las pruebas unitarias deben estar en el directorio tests/
, y las librerías de terceros, instaladas por composer, deben estar en el directorio vendor/
. Para otros archivos y directorios, seguir el Standard PHP Package Skeleton tendrá más sentido para los contribuidores de un proyecto.
La comunidad PHP es grande y diversa, compuesta por innumerables bibliotecas, frameworks y componentes. Es habitual que los desarrolladores de PHP elijan varios de ellos y los combinen en un único proyecto. Es importante que el código PHP se adhiera (tanto como sea posible) a un estilo de código común para facilitar a los desarrolladores mezclar y combinar varias librerías para sus proyectos.
El Framework Interop Group ha propuesto y aprobado una serie de recomendaciones de estilo. No todas están relacionadas con el estilo del código, pero las que sí lo hacen son PSR-1, PSR-12, PSR-4 y PER Coding Style. Estas recomendaciones no son más que un conjunto de reglas que muchos proyectos como Drupal, Zend, Symfony, Laravel, CakePHP, phpBB, AWS SDK, FuelPHP, Lithium, etc. adoptan. Puedes utilizarlas para tus propios proyectos, o seguir utilizando tu estilo personal.
Lo ideal sería escribir código PHP que se adhiera a un estándar conocido. Esto podría ser cualquier combinación de PSRs, o uno de los estándares de codificación hechos por PEAR o Zend. Esto significa que otros desarrolladores pueden leer y trabajar fácilmente con su código, y las aplicaciones que implementan los componentes pueden tener consistencia incluso cuando se trabaja con mucho código de terceros.
Puedes usar PHP_CodeSniffer para comprobar el código contra cualquiera de estas recomendaciones, y plugins para editores de texto como Sublime Text para recibir feedback en tiempo real.
Puede corregir la estructura del código automáticamente utilizando una de las siguientes herramientas:
Y puedes ejecutar phpcs manualmente desde el shell:
phpcs -sw --standard=PSR1 file.php
Mostrará los errores y describirá cómo solucionarlos.
También puede ser útil incluir el comando phpcs
en un git pre-commit hook con el argumento CLI --filter=GitStaged
.
De este modo, el código que contenga errores contra la norma elegida no podrá entrar en el repositorio hasta que los
errores hayan sido corregidos.
Si tiene PHP_CodeSniffer, puede arreglar los problemas de estructura del código reportados por esta herramienta automáticamente, con PHP Code Beautifier and Fixer.
phpcbf -w --standard=PSR1 file.php
Otra opción es usar el PHP Coding Standards Fixer. Mostrará qué tipo de errores tenía la estructura del código antes de corregirlos.
php-cs-fixer fix -v --rules=@PSR1 file.php
Se prefiere el inglés para todos los nombres de símbolos e infraestructura de códigos. Los comentarios pueden redactarse en cualquier idioma fácilmente legible por todas las partes actuales y futuras que puedan trabajar en el código base.
Por último, un buen recurso complementario para escribir código PHP limpio es Clean Code PHP.
PHP es un lenguaje flexible y dinámico que admite diversas técnicas de programación. A lo largo de los años ha evolucionado de forma espectacular, sobre todo con la incorporación de un sólido modelo orientado a objetos en PHP 5.0 (2004), funciones anónimas y namespaces en PHP 5.3 (2009) y traits en PHP 5.4 (2012).
PHP tiene un conjunto muy completo de características de programación orientada a objetos, incluyendo soporte para clases, clases abstractas, interfaces, herencia, constructores, clonación, excepciones y más.
PHP soporta funciones de primera clase, lo que significa que una función puede ser asignada a una variable. Tanto las funciones definidas por el usuario como las funciones internas pueden referenciarse mediante una variable e invocarse dinámicamente. Las funciones pueden pasarse como argumentos a otras funciones (característica denominada Funciones de orden superior) y las funciones pueden devolver otras funciones.
La recursión, una característica que permite a una función llamarse a sí misma, está soportada por el lenguaje, pero la mayor parte del código PHP se centra en la iteración.
Las nuevas funciones anónimas (con soporte para closures) están presentes desde PHP 5.3 (2009).
PHP 5.4 añadió la capacidad de enlazar closures al ámbito de un objeto y también mejoró el soporte para callables de tal forma que pueden ser usadas indistintamente con funciones anónimas en casi todos los casos.
call_user_func_array()
.PHP soporta varias formas de meta-programación a través de mecanismos como la API Reflection y los Métodos Mágicos.
Hay muchos Métodos Mágicos disponibles tales como __get()
, __set()
, __clone()
, __toString()
, __invoke()
, etc.
que permiten a los desarrolladores conectarse al comportamiento de las clases. Los desarrolladores de Ruby a menudo dicen que PHP carece de method_missing
,
pero esto esta disponible como __call()
y __callStatic()
.
Como se mencionó anteriormente, la comunidad PHP tiene muchos desarrolladores creando mucho código. Esto significa que el código PHP de una biblioteca puede usar el mismo nombre de clase que otra. Cuando ambas bibliotecas son usadas en el mismo espacio de nombres, estas colisionan y causan problemas.
Los espacios de nombres (Namespaces) resuelven este problema. Como se describe en el manual de referencia de PHP, los espacios de nombres pueden compararse con los directorios del sistema operativo que espacian o separan los archivos; dos archivos con el mismo nombre pueden coexistir en directorios separados. Del mismo modo, dos clases PHP con el mismo nombre pueden coexistir en espacios de nombres PHP separados. Así de simple.
Es importante que asigne un espacio de nombres a su código para que pueda ser utilizado por otros desarrolladores sin temor a colisionar con otras bibliotecas.
Una forma recomendada de utilizar los espacios de nombres es la descrita en PSR-4, cuyo objetivo es proporcionar una convención estándar de archivos, clases y espacios de nombres para permitir un código plug-and-play.
En octubre de 2014 el PHP-FIG dejó obsoleto el anterior estándar de autocarga: PSR-0. Tanto PSR-0 como PSR-4 siguen siendo perfectamente utilizables. Este último requiere PHP 5.3, por lo que muchos proyectos que solo usan PHP 5.2 implementan PSR-0.
Si va a utilizar un estándar de autocargador para una nueva aplicación o paquete, considere utilizar PSR-4.
La Biblioteca Estándar de PHP (SPL) viene empaquetada con PHP y proporciona una colección de clases e interfaces. Se compone principalmente de clases de estructura de datos comúnmente necesarias (pila, cola, montón, etc.), e iteradores que pueden recorrer estas estructuras de datos o sus propias clases que implementan interfaces SPL.
PHP fue creado para escribir aplicaciones web, pero también es útil para scripting de programas de interfaz de línea de comandos (CLI). Los programas PHP de línea de comandos pueden ayudar a automatizar tareas comunes como pruebas, despliegue y administración de aplicaciones.
Los programas PHP CLI son poderosos porque puedes usar el código de tu aplicación directamente sin tener que crear y asegurar una web GUI para ella. ¡Solo asegúrate de no poner tus scripts PHP CLI en tu raíz web pública!
Intente ejecutar PHP desde su línea de comandos:
La opción -i
imprimirá su configuración PHP igual que la función phpinfo()
.
La opción -a
proporciona un shell interactivo, similar al IRB de ruby o al shell interactivo de python. También existen
de otras útiles opciones de línea de comandos, también.
Escribamos un simple programa CLI “Hola, $nombre”. Para probarlo, crea un archivo llamado hello.php
, como se muestra a continuación.
PHP establece dos variables especiales basadas en los argumentos con los que se ejecuta el script. $argc
es una variable entera
que contiene el conteo de argumentos y $argv
es una variable array que contiene el valor de cada argumento.
El primer argumento es siempre el nombre de su archivo de script PHP, en este caso hello.php
.
La expresión exit()
se utiliza con un número distinto de cero para hacer saber al shell que el comando ha fallado. Los códigos de salida más comunes se pueden encontrar aquí.
Para ejecutar nuestro script, antes visto, desde la línea de comandos:
Una de las herramientas más útiles en el desarrollo de software es un depurador adecuado. Te permite rastrear la ejecución de tu código y monitorizar el contenido de la pila. Xdebug, el depurador de PHP, puede ser utilizado por varios IDEs para proporcionar puntos de interrupción e inspección de pila. También puede permitir a herramientas como PHPUnit y KCacheGrind realizar análisis de cobertura de código y perfilado de código. y perfiles de código.
Si te encuentras en un aprieto, dispuesto a recurrir a var_dump()
/print_r()
, y sigues sin encontrar la solución - quizás necesites usar el depurador.
Instalar Xdebug puede ser complicado, pero una de sus características más importantes es la “Depuración Remota” - si desarrollar código localmente y luego probarlo dentro de una máquina virtual o en otro servidor, la depuración remota es la característica que usted querrá habilitar de inmediato.
Tradicionalmente, usted modificaría su Apache VHost o archivo .htaccess con estos valores:
El “host remoto” y el “puerto remoto” corresponderán a tu ordenador local y al puerto en el que configures tu IDE para escuchar. Entonces es sólo cuestión de poner tu IDE en modo “escuchar conexiones”, y cargar la URL:
http://your-website.example.com/index.php?XDEBUG_SESSION_START=1
Su IDE interceptará ahora el estado actual mientras se ejecuta el script, permitiéndole establecer puntos de interrupción y explorar los valores en memoria.
Los depuradores gráficos hacen que sea muy fácil recorrer el código, inspeccionar variables y evaluar el código contra el tiempo de ejecución en vivo. Muchos IDEs tienen soporte integrado o basado en plugins para la depuración gráfica con Xdebug. MacGDBp es una GUI de Xdebug gratuita e independiente de código abierto para macOS.
Hay un montón de librerías PHP, frameworks y componentes entre los que elegir. Su proyecto probablemente utilizará varios de ellos - estas son las dependencias del proyecto. Hasta hace poco, PHP no tenía una buena manera de gestionar estas dependencias del proyecto. Incluso si las gestionaba manualmente, aún tenía que preocuparse por los autoloaders. Esto ya no es un problema.
Actualmente existen dos grandes sistemas de gestión de paquetes para PHP - Composer y PEAR. Composer es actualmente el gestor de paquetes más popular para PHP, sin embargo durante mucho tiempo PEAR fue el principal gestor de paquetes en uso. Conocer la historia de PEAR es una buena idea, ya que aún puede encontrar referencias a él aunque nunca lo use.
Composer es el gestor de dependencias recomendado para PHP. Enumera las dependencias de tu proyecto en un archivo composer.json
y,
con unos simples comandos, Composer descargará automáticamente las dependencias de tu proyecto y configurará la carga automática por ti.
Composer es análogo a NPM en el mundo node.js, o Bundler en el mundo Ruby.
Existe una plétora de librerías PHP compatibles con Composer y listas para ser utilizadas en tu proyecto. Estos “paquetes” están listados en Packagist, el repositorio oficial de librerías PHP compatibles con Composer.
La forma más segura de descargar Composer es siguiendo las instrucciones oficiales.
Esto verificará que el instalador no está corrupto o manipulado.
El instalador instala un binario composer.phar
en su directorio de trabajo actual.
Recomendamos instalar Composer globalmente (por ejemplo, una única copia en /usr/local/bin
). Para ello, ejecute este comando a continuación:
Nota: Si lo anterior falla por los permisos, prefijar con sudo
.
Para ejecutar un Composer instalado localmente se usaría php composer.phar
, globalmente es simplemente composer
.
Para los usuarios de Windows la forma más fácil de empezar a funcionar es utilizar el instalador ComposerSetup, que
realiza una instalación global y configura tu $PATH
para que puedas llamar a composer
desde cualquier directorio en tu línea de comandos.
Composer mantiene un registro de las dependencias de tu proyecto en un archivo llamado composer.json
. Puedes gestionarlo
manualmente si lo deseas, o utilizar el propio Composer. El comando composer require
añade una dependencia del proyecto y si no
tienes un archivo composer.json
, se creará uno. Aquí tienes un ejemplo que añade Twig como dependencia de tu proyecto.
Como alternativa, el comando composer init
le guiará a través de la creación de un archivo completo composer.json
para su proyecto.
De cualquier manera, una vez que haya creado su archivo composer.json
puede decirle a Composer que descargue e instale sus dependencias en el directorio vendor/
.
Esto también se aplica a los proyectos que ha descargado que ya proporcionan un archivo composer.json
:
A continuación, añada esta línea al archivo PHP principal de su aplicación; esto le dirá a PHP que utilice el autocargador (del Inglés “autoloader”) de Composer para las dependencias de su proyecto.
Ahora puedes utilizar las dependencias de tu proyecto y se cargarán automáticamente cuando las necesites.
Composer crea un archivo llamado composer.lock
que almacena la versión exacta de cada paquete que descargó
cuando ejecutó por primera vez composer install
. Si comparte su proyecto con otros,
asegúrese de que el archivo composer.lock
esté incluido, de modo que cuando ejecuten composer install
obtengan
las mismas versiones que usted. Para actualizar sus dependencias, ejecute composer update
. No utilice
composer update
al desplegar, sólo composer install
,
de lo contrario puede terminar con diferentes versiones de paquetes en producción.
Ts muy útil cuando se definen los requisitos de versión de forma flexible. Por ejemplo, un requisito de versión de ~1.8
significa
“cualquier cosa más nueva que 1.8.0
, pero menos que 2.0.x-dev
”. También puede utilizar el comodín *
como en 1.8.*
.
Ahora el comando composer update
de Composer actualizará todas tus dependencias a la versión más reciente que se ajuste a las restricciones que definas.
Para recibir notificaciones sobre el lanzamiento de nuevas versiones puede suscribirse a libraries.io, un servicio web que puede supervisar las dependencias y enviarle alertas sobre las actualizaciones.
El Comprobador Local de Seguridad PHP (en Inglés “Local PHP Security Checker”)
es una herramienta de línea de comandos, que examinará su archivo composer.lock
y le dirá si necesita actualizar alguna de sus dependencias.
Composer también puede gestionar dependencias globales y sus binarios. El uso es sencillo, todo lo que necesitas hacer
es anteponer a su comando con global
. Si por ejemplo quieres instalar PHPUnit y tenerlo
disponible globalmente, ejecutarías el siguiente comando:
Esto creará una carpeta ~/.composer
donde residen tus dependencias globales. Para que los binarios de los paquetes instalados,
añada la carpeta ~/.composer/vendor/bin
a la variable $PATH
.
Un veterano gestor de paquetes que algunos desarrolladores PHP disfrutan es PEAR. Se comporta de manera similar a Composer, pero tiene algunas diferencias notables.
PEAR requiere que cada paquete tenga una estructura específica, lo que significa que el autor del paquete debe prepararlo para uso con PEAR. No es posible utilizar un proyecto que no haya sido preparado para funcionar con PEAR.
PEAR instala los paquetes globalmente, lo que significa que después de instalarlos una vez están disponibles para todos los proyectos en ese servidor. Esto puede ser bueno si muchos proyectos dependen del mismo paquete con la misma versión, pero puede llevar a problemas si surgen conflictos de versión entre dos proyectos.
Puede instalar PEAR descargando el instalador .phar
y ejecutándolo. La documentación de PEAR tiene
detalladas instrucciones de instalación para cada sistema operativo.
Si usas Linux, también puedes echar un vistazo al gestor de paquetes de tu distribución.
Debian y Ubuntu, por ejemplo, tienen un paquete apt php-pear
.
Si el paquete aparece en la lista de paquetes de PEAR, puede instalarlo especificando el nombre oficial:
Si el paquete se aloja en otro canal, deberá “descubrir” primero el canal y especificarlo también al instalar. Consulta la documentación sobre el uso de canales para obtener más información sobre este tema.
Si ya está utilizando Composer y desea instalar algún código PEAR también, puede utilizar Composer para manejar sus dependencias PEAR. Los repositorios PEAR ya no son soportados directamente por Composer versión 2, por lo que debes añadir manualmente un repositorio para instalar paquetes PEAR:
La primera sección "repositorios"
se utilizará para que Composer sepa que debe “inicializar” (o “descubrir” en terminología PEAR)
el repositorio pear. Entonces la sección require
prefijará el nombre del paquete así:
pear-channel/package
El prefijo “pear” está codificado para evitar conflictos, ya que un canal pear puede ser el mismo que el nombre de proveedor de otro paquete, por ejemplo, entonces el nombre corto del canal (o URL completa) puede ser usado para referenciar en qué canal está el paquete.
Cuando se instala este código estará disponible en su directorio de proveedores y automáticamente disponible a través del autocargador de Composer:
vendor/pear2/pear2-http-request/pear2/HTTP/Request.php
Para utilizar este paquete PEAR simplemente haga referencia a él de la siguiente manera:
PHP is a vast language that allows coders of all levels the ability to produce code not only quickly, but efficiently. However, while advancing through the language, we often forget the basics that we first learnt (or overlooked) in favor of short cuts and/or bad habits. To help combat this common issue, this section is aimed at reminding coders of the basic coding practices within PHP.
PHP has a class named DateTime to help you when reading, writing, comparing or calculating with date and time. There are many date and time related functions in PHP besides DateTime, but it provides nice object-oriented interface to most common uses. DateTime can handle time zones, but that is outside the scope of this short introduction.
To start working with DateTime, convert raw date and time string to an object with createFromFormat()
factory method
or do new DateTime
to get the current date and time. Use format()
method to convert DateTime back to a string for
output.
Calculating with DateTime is possible with the DateInterval class. DateTime has methods like add()
and sub()
that
take a DateInterval as an argument. Do not write code that expects the same number of seconds in every day. Both daylight
saving and time zone alterations will break that assumption. Use date intervals instead. To calculate date difference
use the diff()
method. It will return new DateInterval, which is super easy to display.
You can use standard comparisons on DateTime objects:
One last example to demonstrate the DatePeriod class. It is used to iterate over recurring events. It can take two DateTime objects, start and end, and the interval for which it will return all events in between.
A popular PHP API extension is Carbon. It inherits everything in the DateTime class, so involves minimal code alterations, but extra features include Localization support, further ways to add, subtract and format a DateTime object, plus a means to test your code by simulating a date and time of your choosing.
When you are building your application it is helpful to use common patterns in your code and common patterns for the overall structure of your project. Using common patterns is helpful because it makes it much easier to manage your code and lets other developers quickly understand how everything fits together.
If you use a framework then most of the higher level code and project structure will be based on that framework, so a lot of the pattern decisions are made for you. But it is still up to you to pick out the best patterns to follow in the code you build on top of the framework. If, on the other hand, you are not using a framework to build your application then you have to find the patterns that best suit the type and size of application that you’re building.
You can learn more about PHP design patterns and see working examples at:
This section was originally written by Alex Cabal over at PHP Best Practices and has been used as the basis for our own UTF-8 advice.
Right now PHP does not support Unicode at a low level. There are ways to ensure that UTF-8 strings are processed OK, but it’s not easy, and it requires digging in to almost all levels of the web app, from HTML to SQL to PHP. We’ll aim for a brief, practical summary.
The basic string operations, like concatenating two strings and assigning strings to variables, don’t need anything
special for UTF-8. However, most string functions, like strpos()
and strlen()
, do need special consideration. These
functions often have an mb_*
counterpart: for example, mb_strpos()
and mb_strlen()
. These mb_*
strings are made
available to you via the Multibyte String Extension, and are specifically designed to operate on Unicode strings.
You must use the mb_*
functions whenever you operate on a Unicode string. For example, if you use substr()
on a
UTF-8 string, there’s a good chance the result will include some garbled half-characters. The correct function to use
would be the multibyte counterpart, mb_substr()
.
The hard part is remembering to use the mb_*
functions at all times. If you forget even just once, your Unicode
string has a chance of being garbled during further processing.
Not all string functions have an mb_*
counterpart. If there isn’t one for what you want to do, then you might be out
of luck.
You should use the mb_internal_encoding()
function at the top of every PHP script you write (or at the top of your
global include script), and the mb_http_output()
function right after it if your script is outputting to a browser.
Explicitly defining the encoding of your strings in every script will save you a lot of headaches down the road.
Additionally, many PHP functions that operate on strings have an optional parameter letting you specify the character
encoding. You should always explicitly indicate UTF-8 when given the option. For example, htmlentities()
has an
option for character encoding, and you should always specify UTF-8 if dealing with such strings. Note that as of PHP 5.4.0, UTF-8 is the default encoding for htmlentities()
and htmlspecialchars()
.
Finally, If you are building a distributed application and cannot be certain that the mbstring
extension will be
enabled, then consider using the symfony/polyfill-mbstring Composer package. This will use mbstring
if it is available, and
fall back to non UTF-8 functions if not.
If your PHP script accesses MySQL, there’s a chance your strings could be stored as non-UTF-8 strings in the database even if you follow all of the precautions above.
To make sure your strings go from PHP to MySQL as UTF-8, make sure your database and tables are all set to the
utf8mb4
character set and collation, and that you use the utf8mb4
character set in the PDO connection string. See
example code below. This is critically important.
Note that you must use the utf8mb4
character set for complete UTF-8 support, not the utf8
character set! See
Further Reading for why.
Use the mb_http_output()
function to ensure that your PHP script outputs UTF-8 strings to your browser.
The browser will then need to be told by the HTTP response that this page should be considered as UTF-8. Today, it is common to set the character set in the HTTP response header like this:
The historic approach to doing that was to include the charset <meta>
tag in your page’s <head>
tag.
Disclaimer for newcomers: i18n and l10n are numeronyms, a kind of abbreviation where numbers are used to shorten words - in our case, internationalization becomes i18n and localization, l10n.
First of all, we need to define those two similar concepts and other related things:
The easiest way to internationalize PHP software is by using array files and using those strings in templates, such as
<h1><?=$TRANS['title_about_page']?></h1>
. This way is, however, hardly recommended for serious projects, as it poses
some maintenance issues along the road - some might appear in the very beginning, such as pluralization. So, please,
don’t try this if your project will contain more than a couple of pages.
The most classic way and often taken as reference for i18n and l10n is a Unix tool called gettext
. It dates
back to 1995 and is still a complete implementation for translating software. It is easy enough to get running, while
still sporting powerful supporting tools. It is about Gettext we will be talking here. Also, to help you not get messy
over the command-line, we will be presenting a great GUI application that can be used to easily update your l10n source.
There are common libraries used that support Gettext and other implementations of i18n. Some of them may seem easier to install or sport additional features or i18n file formats. In this document, we focus on the tools provided with the PHP core, but here we list others for completion:
intl
extension (including pluralized messages).gettext
command), and can also export
to other formats besides .mo/.po
files. Can be useful if you need to integrate your translation files into other
parts of the system, like a JavaScript interface.strtr()
internally.Other frameworks also include i18n modules, but those are not available outside of their codebases:
@lang
helper for template files.Intl
extension, available since PHP 5.3, and based on the ICU project; this enables Yii to run powerful
replacements, like spelling out numbers, formatting dates, times, intervals, currency, and ordinals.If you decide to go for one of the libraries that provide no extractors, you may want to use the gettext formats, so you can use the original gettext toolchain (including Poedit) as described in the rest of the chapter.
You might need to install Gettext and the related PHP library by using your package manager, like apt-get
or yum
.
After installed, enable it by adding extension=gettext.so
(Linux/Unix) or extension=php_gettext.dll
(Windows) to
your php.ini
.
Here we will also be using Poedit to create translation files. You will probably find it in your system’s package manager; it is available for Unix, macOS, and Windows, and can be downloaded for free on their website as well.
There are three files you usually deal with while working with gettext. The main ones are PO (Portable Object) and MO (Machine Object) files, the first being a list of readable “translated objects” and the second, the corresponding binary to be interpreted by gettext when doing localization. There’s also a POT (Template) file, which simply contains all existing keys from your source files, and can be used as a guide to generate and update all PO files. Those template files are not mandatory: depending on the tool you are using to do l10n, you can go just fine with only PO/MO files. You will always have one pair of PO/MO files per language and region, but only one POT per domain.
There are some cases, in big projects, where you might need to separate translations when the same words convey different meaning given a context. In those cases, you split them into different domains. They are, basically, named groups of POT/PO/MO files, where the filename is the said translation domain. Small and medium-sized projects usually, for simplicity, use only one domain; its name is arbitrary, but we will be using “main” for our code samples. In Symfony projects, for example, domains are used to separate the translation for validation messages.
A locale is simply a code that identifies one version of a language. It is defined following the ISO 639-1 and ISO 3166-1 alpha-2 specs: two lower-case letters for the language, optionally followed by an underline and two upper-case letters identifying the country or regional code. For rare languages, three letters are used.
For some speakers, the country part may seem redundant. In fact, some languages have dialects in different
countries, such as Austrian German (de_AT
) or Brazilian Portuguese (pt_BR
). The second part is used to distinguish
between those dialects - when it is not present, it is taken as a “generic” or “hybrid” version of the language.
To use Gettext, we will need to adhere to a specific structure of folders. First, you will need to select an arbitrary
root for your l10n files in your source repository. Inside it, you will have a folder for each needed locale, and a
fixed LC_MESSAGES
folder that will contain all your PO/MO pairs. Example:
As we said in the introduction, different languages might sport different plural rules. However, gettext saves us from
this trouble once again. When creating a new .po
file, you will have to declare the plural rules for that
language, and translated pieces that are plural-sensitive will have a different form for each of those rules. When
calling Gettext in code, you will have to specify the number related to the sentence, and it will work out the correct
form to use - even using string substitution if needed.
Plural rules include the number of plurals available and a boolean test with n
that would define in which rule the
given number falls (starting the count with 0). For example:
nplurals=1; plural=0
- only one rulenplurals=2; plural=(n != 1);
- two rules, first if N is one, second rule otherwisenplurals=2; plural=(n > 1);
- two rules, second if N is bigger than one, first otherwiseNow that you understood the basis of how plural rules works - and if you didn’t, please look at a deeper explanation on the LingoHub tutorial -, you might want to copy the ones you need from a list instead of writing them by hand.
When calling out Gettext to do localization on sentences with counters, you will have to provide it the
related number as well. Gettext will work out what rule should be in effect and use the correct localized version.
You will need to include in the .po
file a different sentence for each plural rule defined.
After all that theory, let’s get a little practical. Here’s an excerpt of a .po
file - don’t mind with its format,
but with the overall content instead; you will learn how to edit it easily later:
The first section works like a header, having the msgid
and msgstr
especially empty. It describes the file encoding,
plural forms and other things that are less relevant.
The second section translates a simple string from English to
Brazilian Portuguese, and the third does the same, but leveraging string replacement from sprintf
so the
translation may contain the user name and visit date.
The last section is a sample of pluralization forms, displaying
the singular and plural version as msgid
in English and their corresponding translations as msgstr
0 and 1
(following the number given by the plural rule). There, string replacement is used as well so the number can be seen
directly in the sentence, by using %d
. The plural forms always have two msgid
(singular and plural), so it is
advised not to use a complex language as the source of translation.
As you might have noticed, we are using as source ID the actual sentence in English. That msgid
is the same used
throughout all your .po
files, meaning other languages will have the same format and the same msgid
fields but
translated msgstr
lines.
Talking about translation keys, there are two main “schools” here:
msgid
as a real sentence.
The main advantages are:
msgid
;msgid
across several language files.msgid
as a unique, structured key.
It would describe the sentence role in the application in a structured way, including the template or part where the
string is located instead of its content.
en.po
file, that
translators would read to understand what to write in fr.po
for instance.top_menu.welcome
instead of Hello there, User!
on the said untranslated French page). That is good it as would force translation to be complete before publishing -
however, bad as translation issues would be remarkably awful in the interface. Some libraries, though, include an
option to specify a given language as “fallback”, having a similar behavior as the other approach.The Gettext manual favors the first approach as, in general, it is easier for translators and users in case of trouble. That is how we will be working here as well. However, the Symfony documentation favors keyword-based translation, to allow for independent changes of all translations without affecting templates as well.
In a typical application, you would use some Gettext functions while writing static text in your pages. Those sentences
would then appear in .po
files, get translated, compiled into .mo
files and then, used by Gettext when rendering
the actual interface. Given that, let’s tie together what we have discussed so far in a step-by-step example:
gettext()
simply translates a msgid
into its corresponding msgstr
for a given language. There’s also
the shorthand function _()
that works the same way;ngettext()
does the same but with plural rules;dgettext()
and dngettext()
, that allow you to override the domain for a single
call. More on domain configuration in the next example.i18n_setup.php
as used above), selecting the correct locale and configuring GettextOne of the great advantages Gettext has over custom framework i18n packages is its extensive and powerful file format. “Oh man, that’s quite hard to understand and edit by hand, a simple array would be easier!” Make no mistake, applications like Poedit are here to help - a lot. You can get the program from their website, it’s free and available for all platforms. It’s a pretty easy tool to get used to, and a very powerful one at the same time - using all features Gettext has available. This guide is based on PoEdit 1.8.
In the first run, you should select “File > New…” from the menu. You’ll be asked straight ahead for the language:
here you can select/filter the language you want to translate to, or use that format we mentioned before, such as
en_US
or pt_BR
.
Now, save the file - using that directory structure we mentioned as well. Then you should click “Extract from sources”, and here you’ll configure various settings for the extraction and translation tasks. You’ll be able to find all those later through “Catalog > Properties”:
gettext()
(and siblings) are called - this
is usually your templates/views folder(s). This is the only mandatory setting;gettext()
and similar function calls look like in several
programming languages, but you might as well create your own translation functions. It will be here you’ll add those
other methods. This will be discussed later in the “Tips” section.After setting those points it will run a scan through your source files to find all the localization calls. After every scan PoEdit will display a summary of what was found and what was removed from the source files. New entries will fed empty into the translation table, and you’ll start typing in the localized versions of those strings. Save it and a .mo file will be (re)compiled into the same folder and ta-dah: your project is internationalized.
As you may have noticed before, there are two main types of localized strings: simple ones and those with plural forms. The first ones have simply two boxes: source and localized string. The source string cannot be modified as Gettext/Poedit do not include the powers to alter your source files - you should change the source itself and rescan the files. Tip: you may right-click a translation line and it will hint you with the source files and lines where that string is being used. On the other hand, plural form strings include two boxes to show the two source strings, and tabs so you can configure the different final forms.
Whenever you change your sources and need to update the translations, just hit Refresh and Poedit will rescan the code, removing non-existent entries, merging the ones that changed and adding new ones. It may also try to guess some translations, based on other ones you did. Those guesses and the changed entries will receive a “Fuzzy” marker, indicating it needs review, appearing golden in the list. It is also useful if you have a translation team and someone tries to write something they are not sure about: just mark Fuzzy, and someone else will review later.
Finally, it is advised to leave “View > Untranslated entries first” marked, as it will help you a lot to not forget any entry. From that menu, you can also open parts of the UI that allow you to leave contextual information for translators if needed.
If you are running PHP as a module on Apache (mod_php
), you might face issues with the .mo
file being cached. It
happens the first time it is read, and then, to update it, you might need to restart the server. On Nginx and PHP5 it
usually takes only a couple of page refreshes to refresh the translation cache, and on PHP7 it is rarely needed.
As preferred by many people, it is easier to use _()
instead of gettext()
. Many custom i18n libraries from
frameworks use something similar to t()
as well, to make translated code shorter. However, that is the only function
that sports a shortcut. You might want to add in your project some others, such as __()
or _n()
for ngettext()
,
or maybe a fancy _r()
that would join gettext()
and sprintf()
calls. Other libraries, such as
php-gettext’s Gettext also provide helper functions like these.
In those cases, you’ll need to instruct the Gettext utility on how to extract the strings from those new functions.
Don’t be afraid; it is very easy. It is just a field in the .po
file, or a Settings screen on Poedit. In the editor,
that option is inside “Catalog > Properties > Source keywords”. Remember: Gettext already knows the default functions
for many languages, so don’t be afraid if that list seems empty. You need to include there the specifications of those
new functions, following a specific format:
t()
that simply returns the translation for a string, you can specify it as t
.
Gettext will know the only function argument is the string to be translated;__('one user', '%d users', $number)
, the
specification would be __:1,2
, meaning the first form is the first argument, and the second form is the second
argument. If your number comes as the first argument instead, the spec would be __:2,3
, indicating the first form is
the second argument, and so on.After including those new rules in the .po
file, a new scan will bring in your new strings just as easy as before.
De Wikipedia:
Inyección de dependencias (Dependency Injection, DI) es un patrón de diseño en el que se suministran objetos a una clase en lugar de ser la propia clase la que cree dichos objetos. Esos objetos cumplen contratos que necesitan nuestras clases para poder funcionar (de ahí el concepto de dependencia).
Esta cita hace que el concepto suene mucho más complejo de lo que es en realidad. La inyección de dependencias consiste en proporcionar a un componente sus dependencias a través de la inyección en constructor, llamadas a métodos o la configuración de propiedades. Es así de simple.
Podemos demostrar el concepto con un simple pero a la vez inofencivo ejemplo.
Tenemos una clase Database
que requiere un adaptador para comunicarse con la base de datos.
Instanciamos el adaptador en el constructor y creamos una dependencia rígida.
Esto dificulta las pruebas y significa que la clase Database
esta fuertemente acoplada al adaptador.
Este código se puede refactorizar para usar Inyección de Dependencia y de esta manera desacoplamos la dependencia. Aquí, inyectamos la dependencia en un constructor haciendo uso de la promoción de propiedades en el constructor y de esta manera estará disponible como una propiedad de la clase:
Ahora le estamos dando a la clase Database
su dependencia en lugar de crearla directamente.
Incluso podríamos crear un método que acepte un argumento de la dependencia y configurarla
de esa manera, o si la propiedad $adapter
fuera public
podríamos configurarla directamente.
Si alguna vez has leído sobre Inyección de Dependencias es probable que hayas visto los términos “Inversión de control” o “Principio de Inversión de Dependencias”. Estos son los problemas complejos que resuelve la Inyección de Dependencias.
Inversión de Control, como su nombre lo indica, es “invertir el control” de un sistema al mantener el control organizacional completamente separado de nuestros objetos. En términos de Inyección de Dependencias, esto significa desacoplar nuestras dependencias al controlarlas e instanciarlas en otras partes del sistema.
Durante años, los frameworks PHP han estado logrando la Inversión de Control, sin embargo, surge la pregunta, ¿qué parte del control estamos invirtiendo y hacia dónde? Por ejemplo, los frameworks MVC generalmente proveen un superobjeto o controlador base que otros controladores deben extender para obtener acceso a sus dependencias. Esto es Inversión de Control, sin embargo, en lugar de desacoplar las dependencias, este método simplemente las mueve.
La Inyección de Dependencia nos permite resolver este problema de una forma mas elegante al inyectar solamente las dependencias que necesitamos, cuando la necesitamos sin la necesidad de tener dependencias en duro.
El Principio de Responsabilidad Única (en inglés Single Responsibility Principle) se refiere a los actores y a la arquitectura de alto nivel. Establece que “Una clase debería tener solo una razón para cambiar”. Esto significa que cada clase debería solo tener responsabilidad sobre una única parte de la funcionalidad proporcionada por el software. El mayor beneficio de este enfoque es que permite una mejor reutilización del código. Al diseñar nuestras clases para que hagan solo una cosa, podemos utilizar (o reutilizarlas) en cualquier otro programa sin cambiarlas.
El Principio abierto/cerrado (Open/Closed Principle) se refiere al diseño de clases y la extensión de funcionalidades. Establece que “Las entidades de software (clases, módulos, funciones, etc.) deben estar abiertas a la extensión, pero cerradas a la modificación”. Esto significa que debemos diseñar nuestros módulos, clases y funciones de manera que cuando se necesite una nueva funcionalidad, no deberíamos modificar nuestro código existente sino que escribamos código nuevo que será utilizado por el código existente. En términos prácticos, esto significa que deberíamos escribir clases que implementen y respeten las interfaces, luego hacer sugerencias de tipos hacía esas interfaces en lugar de clases específicas.
El mayor beneficio de este enfoque es que podemos extender nuestro código muy fácilmente con soporte para algo nuevo sin tener que modificar el código existente, lo que significa que podemos reducir el tiempo de Control de Calidad (QA) y el riesgo de un impacto negativo a la aplicación se reduce considerablemente. Podemos desplegar nuevo código más rápido y con más confianza.
El Principio de Sustitución de Liskov (Liskov Substitution Principle) se refiere a la subtipificación y la herencia. Establece que “Las clases hijas nunca deben romper las definiciones de tipo de la clase padre”. O, en palabras de Robert C. Martin, “Los subtipos deben ser sustituibles por sus tipos base”.
Por ejemplo, si tenemos una interfaz FileInterface
que define un método embed()
, y contamos con las clases Audio
y Video
las cuales implementan esta interfaz FileInterface
, podemos esperar que el uso del método embed()
siempre haga lo que pretendemos.
Si más adelante creamos una clase PDF
o una clase Gist
que también implementen la interfaz FileInterface
, ya sabremos
y entenderemos lo que hará el método embed()
. El mayor beneficio de este enfoque es que tenemos la capacidad de construir
programas flexibles y fácilmente configurables, ya que cuando cambiamos un objeto de un tipo (por ejemplo, FileInterface
)
por otro, no necesitamos modificar más nada en nuestro programa.
El Principio de Segregación de Interfaces (Interface Segregation Principle, ISP por sus siglas en inglés) trata sobre la comunicación entre la lógica de negocio y los clientes. Establece que “Ningún cliente debería verse obligado a depender de métodos que no utiliza”. Esto quiere decir que en lugar de tener una única interfaz monolítica que todas las clases conformantes deben implementar, deberíamos en su lugar proporcionar un conjunto de interfaces más pequeñas y específicas por concepto que una clase conformante implemente una o más de ellas.
Por ejemplo, una clase Car
o Bus
estaría interesada en un método steeringWheel()
, pero una
clase Motorcycle
o Tricycle
no lo estaría. Por otro lado, una clase Motorcycle
o Tricycle
se interesaría en un método handlebars()
, mientras que una clase Car
o Bus
no. No es necesario
que todos estos tipos de vehículos implementen soporte tanto para steeringWheel()
como para handlebars()
,
por lo que deberíamos descomponer la interfaz original.
El Principio de Inversión de Dependencias (Dependency Inversion Principle) trata sobre eliminar los vínculos rígidos entre clases discretas para que se pueda aprovechar nueva funcionalidad al pasar una clase diferente. Establece que se debe “depender de abstracciones. No depender de implementaciones”. En términos simples, esto significa que nuestras dependencias deberían ser interfaces/contratos o clases abstractas en lugar de implementaciones concretas. Podemos fácilmente refactorizar el ejemplo anterior para seguir este principio.
Hay varios beneficios al hacer que la clase Database
ahora dependa de una interfaz en lugar de una implementación concreta.
Consideremos que estamos trabajando en un equipo y el adaptador está siendo desarrollado por un colega. En nuestro primer ejemplo, tendríamos que esperar a que dicho colega termine el adaptador antes de poder simularlo adecuadamente para nuestras pruebas unitarias. Ahora que la dependencia es una interfaz/contrato, podemos simular esa interfaz sin problemas, sabiendo que nuestro colega construirá el adaptador basado en ese contrato.
Un beneficio incluso aún mayor de este enfoque es que nuestro código ahora es mucho más escalable. Si dentro de un año decidimos que queremos migrar a un tipo diferente de base de datos, podemos escribir un adaptador que implemente la interfaz original e inyectar eso en su lugar, no se requeriría más refactorización ya que podemos asegurar que el adaptador sigue el contrato establecido por la interfaz.
Lo primero que deberías entender sobre los Contenedores de Inyección de Dependencias es que no son lo mismo que la Inyección de Dependencias. Un contenedor es una herramienta de conveniencia que nos ayuda a implementar la Inyección de Dependencias; sin embargo, pueden ser y a menudo se usan de forma incorrecta para implementar un anti-patrón, Localización de Servicios. Inyectar un contenedor de DI como Localizador de Servicios en tus clases puede crear una dependencia más fuerte en el contenedor que la dependencia que estás reemplazando. Esto además hace que tu código sea mucho menos transparente y en última instancia más difícil de probar.
La mayoría de los frameworks modernos tienen su propio Contenedor de Inyección de Dependencias que te permite conectar tus dependencias a través de la configuración. Lo que esto significa en la práctica es que puedes escribir código de aplicación que sea tan limpio y desacoplado como el framework en el que se basa.
Muchas veces su código PHP utilizará una base de datos para persistir información. Tiene algunas opciones para conectarse e interactuar con su base de datos. La opción recomendada hasta PHP 5.1.0 era usar controladores nativos como mysqli, pgsql, mssql, etc.
Los drivers nativos son geniales si sólo estás usando una base de datos en tu aplicación, pero si, por ejemplo, estás usando MySQL y un poco de MSSQL, o necesitas conectarte a una base de datos Oracle, entonces no podrás usar los mismos drivers. Tendrás que aprender una API completamente nueva para cada base de datos — y eso puede llegar a ser una tontería.
La extensión mysql para PHP es increíblemente antigua y ha sido reemplazada por otras dos extensiones:
No sólo el desarrollo de mysql se detuvo hace mucho tiempo, sino que además ha sido oficialmente eliminado en PHP 7.0.
Para ahorrarse la búsqueda en su php.ini
para ver qué módulo está utilizando, una opción es buscar mysql_*
en el editor de su elección. Si aparecen funciones como mysql_connect()
y mysql_query()
, entonces está usando mysql
.
Incluso si aún no está utilizando PHP 7.x o posterior, no considerar esta actualización lo antes posible le acarreará mayores dificultades cuando se produzca la actualización de PHP. La mejor opción es reemplazar el uso de mysql por mysqli o PDO en tus aplicaciones dentro de tus propios calendarios de desarrollo para que no te veas apurado más adelante.
Si está actualizando de mysql a mysqli, tenga cuidado con las guías de actualización perezosas que sugieren que simplemente puede encontrar y reemplazar mysql_*
con mysqli_*
. No sólo es una simplificación excesiva, sino que pierde las ventajas que mysqli proporciona, como la vinculación de parámetros, que también se ofrece en PDO.
PDO es una librería de abstracción de conexión a bases de datos — incorporada en PHP desde 5.1.0 — que proporciona una interfaz común común para hablar con muchas bases de datos diferentes. Por ejemplo, puede utilizar código básicamente idéntico para interactuar con MySQL o SQLite:
PDO no traducirá sus consultas SQL o emulará las características que faltan; es puramente para la conexión a múltiples tipos de base de datos con la misma API.
Y lo que es más importante, PDO
le permite inyectar de forma segura entradas ajenas (por ejemplo, IDs) en sus consultas SQL sin preocuparse
por ataques de inyección SQL a bases de datos.
Esto es posible utilizando sentencias PDO y parámetros vinculados.
Supongamos que un script PHP recibe un ID numérico como parámetro de consulta. Este ID debe ser usado para obtener un registro
de usuario de una base de datos. Esta es la forma incorrecta
de hacer esto:
Este código es terrible. Estás insertando un parámetro de consulta sin procesar en una consulta SQL. Esto hará que te hackeen en un santiamén, usando una práctica llamada Inyección SQL. Imagínese si un hacker pasa un parámetro id
inventivo
llamando a una URL como http://domain.com/?id=1%3BDELETE+FROM+users
. Esto establecerá la variable $_GET['id']
a
1;DELETE FROM users
lo que borrará todos los usuarios. En su lugar, debería desinfectar/sanitizar la entrada de ID utilizando
parámetros vinculados a PDO.
Este código es correcto. Utiliza un parámetro vinculado en una sentencia PDO. Esto escapa el ID de entrada externo antes de que sea introducido en la base de datos previniendo potenciales ataques de inyección SQL.
Para escrituras, como INSERT o UPDATE, es especialmente crítico filtrar sus datos primero y sanearlos para otras cosas (eliminación de etiquetas HTML, JavaScript, etc). PDO sólo lo desinfectará para SQL, no para su aplicación.
También hay que tener en cuenta que las conexiones a bases de datos consumen recursos y no era raro que se agotaran los recursos si las conexiones no se cerraban implícitamente, aunque esto era más común en otros lenguajes. Usando PDO puedes cerrar implícitamente la conexión destruyendo el objeto asegurándote de que todas las referencias restantes a él son borradas, es decir, establecidas a NULL. Si no hace esto explícitamente, PHP cerrará automáticamente la conexión cuando su script termine - a menos que esté usando conexiones persistentes.
Cuando los desarrolladores comienzan a aprender PHP, a menudo terminan mezclando su interacción con la base de datos con su lógica de presentación, utilizando código que podría parecerse a esto:
Esta es una mala práctica por todo tipo de razones, principalmente que es difícil de depurar, difícil de probar, difícil de leer y que va a dar salida a un montón de campos si no pones un límite.
Aunque hay muchas otras soluciones para hacer esto - dependiendo de si prefieres POO o programación funcional - debe haber algún elemento de separación.
Considere el paso más básico:
Es un buen comienzo. Pon esos dos elementos en dos archivos diferentes y tendrás una separación limpia.
Crea una clase en la que colocar ese método y tendrás un “Modelo”. Crea un simple archivo .php
para colocar
la lógica de presentación y tendrás una “Vista”, que es muy parecido a MVC - una arquitectura OOP común para
la mayoría de los frameworks.
foo.php
models/FooModel.php
views/foo-list.php
Esto es esencialmente lo mismo que hacen la mayoría de los frameworks modernos, aunque un poco más manual. Puede que no necesites hacer todo eso cada vez, pero mezclar demasiada lógica de presentación e interacción con la base de datos puede ser un verdadero problema si alguna vez quieres hacer test unitarios a tu aplicación.
Muchos frameworks proporcionan su propia capa de abstracción que puede o no sentarse encima de PDO. Estos a menudo emulan características de un sistema de base de datos que falta en otro envolviendo sus consultas en métodos PHP, dándole abstracción de base de datos real en lugar de sólo la abstracción de conexión que PDO proporciona. Esto, por supuesto, añadirá un poco de sobrecarga, pero si usted está construyendo una aplicación portable que necesita trabajar con MySQL, PostgreSQL y SQLite entonces un poco de sobrecarga valdrá la pena por el bien de la limpieza del código.
Algunas capas de abstracción se han construido utilizando los estándares de espacio de nombres PSR-0 o PSR-4, por lo que pueden instalarse en cualquier aplicación que se desee:
Las Plantillas proporcionan una manera conveniente de separar la lógica de tu controlador y dominio de tu lógica de presentación. Las plantillas suelen contener el código HTML de tu aplicación, pero también se pueden utilizar otros formatos, como XML. A menudo se hace referencia a las plantillas como “vistas”, las cuales forman parte del segundo componente del patrón de arquitectura de software modelo-vista-controlador (MVC).
El principal beneficio de utilizar plantillas es la clara separación que crean entre la lógica de presentación y el resto de tu aplicación. Las plantillas tienen la única responsabilidad de mostrar contenido formateado. No son responsables de la búsqueda de datos, la persistencia u otras tareas más complejas. Esto lleva a un código más limpio y más legible, lo cual es especialmente útil en un entorno de equipo donde los desarrolladores trabajan en el código del lado del servidor (controladores, modelos) y los diseñadores trabajan en el código del lado del cliente (maquetado).
Las plantillas también mejoran la organización del código de presentación. Por lo general, las plantillas se colocan en una carpeta de “vistas” (“views”), cada una definida en un solo archivo. Este enfoque fomenta la reutilización del código, donde bloques más grandes de código se dividen en piezas más pequeñas y reutilizables, a menudo llamadas parciales (partials). Por ejemplo, el encabezado y el pie de página de tu sitio pueden definirse como plantillas, las cuales se incluyen antes y después de cada plantilla de página.
Finalmente, dependiendo de la biblioteca que uses, las plantillas pueden ofrecer más seguridad al escapar automáticamente el contenido generado por los usuarios. Algunas bibliotecas incluso ofrecen un sistema de “sand-boxing”, donde los diseñadores de plantillas solo tienen acceso a variables y funciones en una lista blanca.
Las plantillas en PHP simple son simplemente plantillas que utilizan código PHP nativo. Son una opción natural ya que PHP es, de hecho, un lenguaje de plantillas. Esto significa que puedes combinar código PHP con otro código, como HTML. Esto es beneficioso para los desarrolladores de PHP ya que no hay nueva sintaxis que aprender, conocen las funciones disponibles y sus editores de código ya tienen resaltado de sintaxis y autocompletado incorporado. Además, las plantillas en PHP simple tienden a ser muy rápidas, ya que no se requiere una etapa de compilación.
Todos los frameworks modernos de PHP emplean algún tipo de sistema de plantillas, la mayoría de los cuales utilizan PHP simple por defecto. Fuera de los frameworks, bibliotecas como Plates o Aura.View facilitan el trabajo con plantillas en PHP simple al ofrecer funcionalidades modernas de plantillas, como herencia, layouts y extensiones.
Usando la biblioteca Plates.
Haciendo uso de la biblioteca Plates.
Aunque PHP ha evolucionado hasta convertirse en un lenguaje maduro, orientado a objetos, no ha mejorado mucho como lenguaje de plantillas. Las plantillas compiladas, como Twig, Brainy o Smarty*, llenan este vacío al ofrecer una nueva sintaxis diseñada específicamente para la creación de plantillas. Desde el escape automático hasta la herencia y estructuras de control simplificadas, las plantillas compiladas están diseñadas para ser más fáciles de escribir, más legibles y más seguras de usar. Las plantillas compiladas incluso pueden compartirse entre diferentes lenguajes, siendo Mustache un buen ejemplo de esto. Dado que estas plantillas deben ser compiladas, hay una ligera pérdida de rendimiento, sin embargo, esto es muy mínimo cuando se utiliza un sistema de caché apropiado.
*Aunque Smarty ofrece escape automático, NO está habilitado por defecto.
Haciendo uso de Twig.
Usando Twig.
En muchos lenguajes de programación “dependientes de excepciones”, cada vez que algo sale mal, se lanzará una excepción. Esta es una forma viable de manejar errores, pero PHP es un lenguaje “ligero en excepciones”. Aunque tiene excepciones y cada vez más partes del núcleo las usan cuando se trabaja con objetos, la mayoría de PHP intentará seguir procesando sin importar lo que suceda, a menos que ocurra un error fatal.
Por ejemplo:
Esto es solo un aviso, y PHP continuará felizmente. Esto puede ser confuso para aquellos que vienen de lenguajes “dependientes de excepciones”, porque en Python, por ejemplo, hacer referencia a una variable no definida lanzará una excepción:
La única diferencia real es que Python reaccionará a cualquier pequeño problema, de manera que los desarrolladores puedan estar muy seguros de que cualquier posible problema o caso límite sea detectado, mientras que PHP seguirá procesando a menos que suceda algo extremo, en cuyo caso lanzará un error y lo reportará.
PHP tiene varios niveles de gravedad de errores. Los tres tipos más comunes de mensajes son errores, avisos y
advertencias. Estos tienen diferentes niveles de severidad: E_ERROR
, E_NOTICE
, y E_WARNING
.
Los errores son fallos fatales en tiempo de ejecución y usualmente son causados por fallos en tu código que deben ser
corregidos, ya que harán que PHP deje de ejecutarse. Los avisos son mensajes de carácter informativo causados por
código que puede o no causar problemas durante la ejecución del script, pero la ejecución no se detiene.
Las advertencias son errores no fatales, y la ejecución del script no se detendrá.
Otro tipo de mensaje de error reportado en tiempo de compilación son los mensajes E_STRICT
.
Estos mensajes se utilizan para sugerir cambios en tu código para ayudar a garantizar la mejor interoperabilidad y
compatibilidad con futuras versiones de PHP.
El reporte de errores se puede cambiar utilizando configuraciones de PHP y/o llamadas a funciones de PHP.
Usando la función incorporada error_reporting()
, puedes establecer el nivel de errores durante la ejecución del script
pasando una de las constantes predefinidas de nivel de error. Por ejemplo, si solo quieres ver Errores y Advertencias,
pero no Avisos (Notices), puedes configurarlo así:
También puedes controlar si los errores se muestran en pantalla (útil en desarrollo) o si se ocultan y registran (útil en producción). Para más información, revisa la sección de Reporte de Errores.
También puedes decirle a PHP que suprima errores específicos usando el Operador de Control de Errores @
.
Pones este operador al inicio de una expresión, y cualquier error que sea resultado directo de la expresión se silenciará.
Esto imprimirá $foo['bar']
si existe, pero simplemente devolverá nulo y no mostrará nada si la variable $foo
o la
clave 'bar'
no existen. Sin el operador de control de errores, esta expresión podría crear un error
PHP Notice: Undefined variable: foo
o PHP Notice: Undefined index: bar
.
Esto podría parecer una buena idea, pero hay algunas desventajas indeseables. PHP maneja expresiones con un @
de una
manera menos eficiente que expresiones sin el @
. La optimización prematura puede ser la raíz de todas las discusiones
de programación, pero si el rendimiento es particularmente importante para tu aplicación/biblioteca, es importante
entender las implicaciones de rendimiento del operador de control de errores.
En segundo lugar, el operador de control de errores suprime completamente el error. El error no se muestra y no se envía al registro de errores. Además, los sistemas PHP estándar/producción no tienen forma de desactivar el operador de control de errores. Aunque puede que tengas razón al considerar que el error que estás viendo es inofensivo, un error diferente y menos inofensivo será igual de silencioso.
Si hay una forma de evitar el uso del operador de supresión de errores, deberías considerarla. Por ejemplo, nuestro código anterior podría reescribirse de la siguiente manera:
Un caso donde podría tener sentido suprimir un error es cuando fopen()
falla al encontrar un archivo. Podrías
verificar la existencia del archivo antes de intentar cargarlo, pero si el archivo se elimina después de la verificación
y antes de la llamada a fopen()
(lo cual puede parecer imposible, pero puede ocurrir), entonces fopen()
devolverá
falso y lanzará un error. Esto es algo que PHP debería resolver, pero es un caso donde la supresión de errores podría
parecer la única solución válida.
Mencionamos antes que no hay forma en un sistema PHP estándar de desactivar el operador de control de errores. Sin
embargo, Xdebug tiene una configuración xdebug.scream
en el archivo ini
que deshabilitará el operador de control
de errores. Puedes configurarlo en tu archivo php.ini
de la siguiente manera:
También puedes establecer este valor en tiempo de ejecución con la función ini_set
Esto es muy útil cuando estás depurando código y sospechas que un error informativo está siendo suprimido. Usa scream con cuidado y como una herramienta temporal de depuración. Hay mucho código de bibliotecas PHP que puede no funcionar con el operador de control de errores deshabilitado.
PHP es perfectamente capaz de ser un lenguaje de programación “dependiente de excepciones” y solo requiere unas pocas
líneas de código para hacer el cambio. Básicamente, puedes lanzar tus “errores” como “excepciones” usando la clase
ErrorException
, que extiende la clase Exception
.
Esta es una práctica común implementada por un gran número de frameworks modernos como Symfony y Laravel. En modo de depuración (o modo dev), ambos frameworks mostrarán una stack trace limpia y agradable.
También hay algunos paquetes disponibles para un mejor manejo y reporte de errores y excepciones, como Whoops!, que viene con la instalación predeterminada de Laravel y puede usarse en cualquier framework.
Al lanzar errores como excepciones durante el desarrollo, puedes manejarlos mejor que con el resultado habitual, y si ves una excepción durante el desarrollo, puedes envolverla en una declaración de captura con instrucciones específicas sobre cómo manejar la situación. Cada excepción que captures hace que tu aplicación sea un poco más robusta.
Más información sobre esto y detalles sobre cómo usar ErrorException
con el manejo de errores se pueden encontrar en
la Clase ErrorException.
Las excepciones son una parte estándar de la mayoría de los lenguajes de programación populares, pero a menudo son pasadas por alto por los programadores de PHP. Lenguajes como Ruby son extremadamente dependientes de excepciones, así que cada vez que algo sale mal, como una falla en una solicitud HTTP, un error en una consulta a la base de datos, o incluso si no se puede encontrar un recurso de imagen, Ruby (o las gems utilizadas) lanzará una excepción a la pantalla, lo que significa que instantáneamente sabrás que hay un error.
PHP, por su parte, es bastante indulgente con esto, y una llamada a file_get_contents()
generalmente solo te devolverá
un FALSE
y un warning
. Muchos frameworks antiguos de PHP, como CodeIgniter, simplemente devolverán un falso,
registrarán un mensaje en sus registros y tal vez te permitan usar un método como $this->upload->get_error() para ver
qué salió mal. El problema aquí es que tienes que ir a buscar un error y consultar la documentación para ver cuál es
el método de error para esta clase, en lugar de que se te haga extremadamente obvio.
Otro problema es cuando las clases lanzan automáticamente un error en la pantalla y terminan el proceso. Cuando haces esto, detienes a otro desarrollador de poder manejar dinámicamente ese error. Las excepciones deben lanzarse para hacer que un desarrollador sea consciente de un error; luego puede elegir cómo manejarlo. Por ejemplo:
La clase genérica Exception
proporciona muy poco contexto de depuración para el desarrollador; sin embargo,
para remediar esto, es posible crear un tipo de Exception
especializado al sub-clasificar la clase genérica Exception
:
Esto significa que puedes agregar múltiples bloques de captura y manejar diferentes excepciones de manera diferente. Esto puede llevar a la creación de un gran número de Excepciones personalizadas, algunas de las cuales podrían haberse evitado utilizando las excepciones SPL proporcionadas en la extensión SPL.
Si, por ejemplo, utilizas el método mágico __call()
y se solicita un método no válido, en lugar de lanzar una
Excepción estándar que es vaga, o crear una Excepción personalizada solo para eso,
podrías simplemente throw new BadMethodCallException;
.
El mejor recurso que he encontrado sobre seguridad en PHP es The 2018 Guide to Building Secure PHP Software por Paragon Initiative.
Es muy importante que todo desarrollador PHP aprenda los fundamentos de la seguridad de las aplicaciones web, que pueden dividirse en un puñado de temas generales:
Hay gente mala lista y dispuesta a explotar su aplicación web. Es importante que tome las precauciones necesarias para reforzar la seguridad de su aplicación web. Por suerte, la buena gente de The Open Web Application Security Project (OWASP) ha recopilado una lista exhaustiva de problemas de seguridad conocidos y métodos para protegerse contra ellos. Se trata de una lectura obligatoria para los desarrolladores preocupados por la seguridad. Survive The Deep End: PHP Security de Padraic Brady es también otra buena guía de seguridad de aplicaciones web para PHP.
Al final, todo el mundo crea una aplicación PHP que depende del inicio de sesión del usuario. Los nombres de usuario y las contraseñas se almacenan en una base de datos y luego se utilizan para autenticar a los usuarios al iniciar sesión.
Es importante hacer hash correctamente a las contraseñas antes de almacenarlas. Hacer un hash y cifrar son dos cosas muy diferentes que a menudo se confunden.
El hashing es una función irreversible y unidireccional. Produce una cadena de longitud fija que no se puede invertir. Esto significa que se puede comparar un hash con otro para determinar si ambos proceden de la misma cadena de origen, pero no se puede determinar la cadena original a partir del hash. Si las contraseñas no tienen hash y un tercero no autorizado accede a la base de datos, todas las cuentas de usuario estarán en peligro.
A diferencia del hashing, el cifrado es reversible (siempre que se tenga la clave). El cifrado es útil en otros ámbitos, pero es una mala estrategia para almacenar contraseñas de forma segura.
Las contraseñas también deben ser salados (del inglés “salted”) individualmente, añadiendo una cadena aleatoria a cada contraseña antes de aplicar el hash. Así se evitan los ataques de diccionario y el uso de “tablas arco iris” (una lista inversa de hashes criptográficos para contraseñas comunes).
El hashing y el salting son vitales, ya que a menudo los usuarios utilizan la misma contraseña para varios servicios y la calidad de las contraseñas puede ser deficiente.
Además, debe utilizar un algoritmo especializado de password hashing en lugar de una función hash criptográfica rápida de uso general (por ejemplo, SHA256). La lista corta de algoritmos hash de contraseña aceptables (a junio de 2018) para usar son:
Afortunadamente, hoy en día PHP facilita esta tarea.
Hashear contraseñas con password_hash
En PHP 5.5 se introdujo password_hash()
. En este momento usa BCrypt, el algoritmo más fuerte actualmente soportado por PHP.
Sin embargo, será actualizado en el futuro para soportar más algoritmos según sea necesario.
La librería password_compat
fue creada para proporcionar compatibilidad con PHP >= 5.3.7.
A continuación, hacemos un hash de una cadena y lo comparamos con una nueva cadena. Debido a que nuestras dos cadenas de origen son diferentes (‘secret-password’ vs. ‘bad-password’) este login fallará.
password_hash()
se encarga del salado de contraseñas por ti. La sal se almacena, junto con el algoritmo y el “coste”, como parte del hash.
password_verify()
extrae esto para determinar cómo comprobar la contraseña, por lo que no necesitas un campo de base de datos separado para almacenar tus sales.
Nuca (nunca) confíes en la introducción de datos ajenos en tu código PHP. Siempre sanee y valide la entrada ajena antes
de usarla en el código. Las funciones filter_var()
y filter_input()
pueden sanear texto y validar formatos de texto
(por ejemplo, direcciones de correo electrónico).
La entrada ajena puede ser cualquier cosa: datos de formulario $_GET
y $_POST
, algunos valores en el superglobal $_SERVER
,
y el cuerpo de la petición HTTP a través de fopen('php://input', 'r')
. Recuerde, la entrada de datos externos
no se limita a los datos del formulario enviados por el usuario. Los archivos cargados y descargados, los valores de sesión,
los datos de cookies y los datos de servicios web de terceros también son entradas de datos externos.
Aunque la introducción de datos ajenos pueden almacenarse, combinarse y accederse posteriormente, siguen siendo entrada ajena. Cada vez que proceses, des salida, concatenes o incluyas datos en tu código, pregúntate si los datos están filtrados correctamente y si son de confianza.
Los datos pueden filtrarse de forma diferente en función de su finalidad. Por ejemplo, cuando una entrada ajena no filtrada
se pasa a la salida de una página HTML, ¡puede ejecutar HTML y JavaScript en su sitio! Esto se conoce como Cross-Site Scripting (XSS)
y puede ser un ataque muy peligroso. Una forma de evitar XSS es desinfectar todos los datos generados por el usuario antes de enviarlos
a la página eliminando las etiquetas HTML con la función strip_tags()
o escapando caracteres con significado especial
en sus respectivas entidades HTML con las funciones htmlentities()
o htmlspecialchars()
.
Otro ejemplo es pasar opciones para ser ejecutadas en la línea de comandos. Esto puede ser extremadamente peligroso (y suele ser una mala idea),
pero puede utilizar la función integrada escapeshellarg()
para desinfectar los argumentos del comando ejecutado.
Un último ejemplo es aceptar una entrada extraña para determinar un fichero a cargar del sistema de ficheros. Esto puede
ser explotado cambiando el nombre del archivo a una ruta de archivo. Es necesario eliminar "/"
, "../"
,
bytes nulos, u otros caracteres de la ruta del archivo para que no pueda cargar archivos ocultos, no públicos o sensibles.
filter_var
filter_input
La sanitización elimina (o escapa) caracteres ilegales o inseguros de los datos de entrada ajenos.
Por ejemplo, debe desinfectar los datos de entrada ajenos antes de incluirla en HTML o insertarla en una consulta SQL sin procesar. Cuando use parámetros vinculados con PDO, se limpiarán los datos de entrada por usted.
A veces es necesario permitir algunas etiquetas HTML seguras en los datos de entrada al incluirla en la página HTML. Esto es muy difícil de hacer y muchos lo evitan usando otros formatos más restringidos como Markdown o BBCode, aunque para ello existen librerías de filtrado de datos como HTML Purifier.
Es peligroso deserializar datos de usuarios u otras fuentes no confiables utilizando unserialize()
.
Hacerlo puede permitir a usuarios maliciosos instanciar objetos (con propiedades definidas por el usuario) cuyos destructores serán ejecutados,
incluso si los propios objetos no son utilizados. Por lo tanto, debes evitar deserializar datos que no sean de confianza.
Utiliza un formato de intercambio de datos seguro y estándar como JSON (a través de json_decode
y json_encode
) si necesitas pasar datos serializados al usuario.
La validación garantiza que la entrada de datos ajenos es la esperada. Por ejemplo, es posible que desee validar una dirección de correo electrónico, un número de teléfono o la edad al procesar un envío de registro.
Al crear archivos de configuración para sus aplicaciones, las mejores prácticas recomiendan que se siga uno de los siguientes métodos siguientes:
.php
. Esto garantiza que,
aunque se acceda directamente al script, no se mostrará como texto sin formato.NOTA: A partir de PHP 5.4.0 el parámetro register_globals
ha sido eliminado y ya no puede ser usado.
Esto sólo se incluye como una advertencia para cualquier persona en el proceso de actualización de una aplicación de legado.
Cuando está activada, la configuración register_globals
hace que varios tipos de variables (incluyendo las de $_POST
,
$_GET
y $_REQUEST
) estén disponibles en el ámbito global de tu aplicación. Esto puede llevar
fácilmente a problemas de seguridad ya que tu aplicación no puede saber de dónde vienen los datos.
Por ejemplo: $_GET['foo']
estaría disponible a través de $foo
, lo cual puede anular variables que hayan sido declaradas.
Si estás usando PHP < 5.4.0 asegúrate de que register_globals
está desactivado.
El registro de errores puede ser útil para encontrar los puntos problemáticos en su aplicación, pero también puede exponer información sobre la estructura de su aplicación al mundo exterior. Para proteger eficazmente su aplicación de los problemas que podrían ser causados por la salida de estos mensajes, es necesario configurar el servidor de manera diferente en el desarrollo frente a la producción (en vivo).
Para mostrar todos los errores posibles durante el desarrollo, configure los siguientes parámetros en su php.ini
:
Pasando el valor
-1
se mostrarán todos los errores posibles, incluso cuando se añadan nuevos niveles y constantes en futuras versiones de PHP. La constanteE_ALL
también se comporta de esta manera a partir de PHP 5.4. - php.net
La constante de nivel de error E_STRICT
se introdujo en 5.3.0 y no forma parte de E_ALL
, sin embargo pasó a
formar parte de E_ALL
en 5.4.0. ¿Qué significa esto? En términos de informar de todos los errores posibles en la versión 5.3
significa que debe utilizar -1
o E_ALL | E_STRICT
.
Informar de todos los errores posibles por versión de PHP
-1
o E_ALL
-1
o E_ALL | E_STRICT
-1
o E_ALL
Para ocultar los errores en su entorno de producción, configure su php.ini
así:
Con esta configuración en producción, los errores seguirán registrándose en los registros de errores del servidor web, pero no se mostrarán al usuario. Para más información sobre estos ajustes, consulte el manual de PHP:
Escribir pruebas automatizadas para su código PHP se considera una buena práctica y puede conducir a aplicaciones bien construidas. Las pruebas automatizadas son una gran herramienta para asegurarse de que su aplicación no se rompe cuando usted está haciendo cambios o añadiendo nuevas funcionalidades y no debe ser ignorada.
Existen varios tipos de herramientas de pruebas (o frameworks) disponibles para PHP, que utilizan diferentes enfoques - todos los cuales tratan de evitar las pruebas manuales y la necesidad de grandes equipos de Aseguramiento de la Calidad (QA, por sus siglas en inglés), sólo para asegurarse de que los cambios recientes no rompen la funcionalidad existente.
De Wikipedia:
El desarrollo dirigido por pruebas (TDD, por sus siglas en inglés) es un proceso de desarrollo de software que se basa en la repetición de un ciclo de desarrollo muy corto: primero, el desarrollador escribe un caso de prueba automatizado que falla y que define una mejora deseada o una nueva función; después, produce código para superar esa prueba y, por último, refactoriza el nuevo código para que cumpla unos estándares aceptables. Kent Beck, a quien se atribuye haber desarrollado o “redescubierto” la técnica, declaró en 2003 que el TDD fomenta los diseños sencillos e inspira confianza.
Hay varios tipos diferentes de pruebas que puede realizar para su aplicación:
Las pruebas unitarias son un enfoque de programación para garantizar que las funciones, clases y métodos funcionan como se espera, desde el momento en que se construyen hasta el final del ciclo de desarrollo. Comprobando los valores que entran y salen de varias funciones y métodos, puedes asegurarte de que la lógica interna funciona correctamente. Mediante el uso de la inyección de dependencias y la creación de clases y stubs “simulados”, puede comprobar que las dependencias se utilizan correctamente para mejorar aún más la cobertura de las pruebas.
Cuando creas una clase o función deberías crear una prueba unitaria para cada comportamiento que deba tener. A un nivel muy básico
deberías asegurarte de que da error si le envías argumentos erróneos y asegurarte de que funciona si le envías argumentos válidos.
Esto ayudará a asegurar que cuando hagas cambios a esta clase o función más adelante en el ciclo de desarrollo, la funcionalidad antigua
siga funcionando como se esperaba. La única alternativa a esto sería var_dump()
en un test.php, que no es forma de construir
una aplicación - grande o pequeña.
La otra utilidad de las pruebas unitarias es contribuir al código abierto. Si puedes escribir una prueba que muestre una funcionalidad rota (es decir, que falla), luego arreglarla, y mostrar que la prueba pasa, es mucho más probable que los parches sean aceptados. Si diriges un proyecto que acepta pull requests, deberías sugerirlo como requisito.
PHPUnit PHPUnit es el marco de pruebas de facto para escribir pruebas unitarias para aplicaciones PHP, pero existen varias alternativas:
De Wikipedia:
Las pruebas de integración (a veces denominadas integración y pruebas, abreviadas “I&T”) son la fase de las pruebas de software en la que se combinan módulos de software individuales y se prueban como un grupo. Se realiza después de las pruebas unitarias y antes de las de validación. Las pruebas de integración toman como entrada los módulos que se han probado por unidades, los agrupan en conjuntos más grandes, aplican a esos conjuntos las pruebas definidas en un plan de pruebas de integración y entregan como salida el sistema integrado listo para las pruebas del sistema.
Muchas de las mismas herramientas que pueden utilizarse para las pruebas unitarias pueden emplearse para las pruebas de integración, ya que se utilizan muchos de los mismos principios.
A veces también conocidas como pruebas de aceptación, las pruebas funcionales consisten en utilizar herramientas para crear pruebas automatizadas que realmente utilizan la aplicación, en lugar de limitarse a verificar que las unidades individuales de código se comportan correctamente y que las unidades individuales pueden hablar entre sí correctamente. Estas herramientas suelen funcionar utilizando datos reales y simulando usuarios reales de la aplicación.
Existen dos tipos diferentes de Desarrollo Guiado por Comportamiento (BDD): SpecBDD y StoryBDD. SpecBDD se centra en el comportamiento técnico del código, mientras que StoryBDD se centra en los comportamientos o interacciones del negocio o de las características. PHP tiene frameworks para ambos tipos de BDD.
Con StoryBDD, se escriben historias legibles que describen el comportamiento de la aplicación. Estas historias se pueden ejecutar como pruebas reales contra su aplicación. El framework utilizado en aplicaciones PHP para StoryBDD es Behat, que está inspirado en el proyecto Cucumber de Ruby e implementa el DSL Gherkin para describir el comportamiento de las características.
Con SpecBDD, se escriben especificaciones que describen cómo debe comportarse el código real. En lugar de probar una función o método, usted está describiendo cómo esa función o método debe comportarse. PHP ofrece el framework PHPSpec para este propósito. Este framework está inspirado en el proyecto RSpec para Ruby.
Además de las pruebas individuales y los marcos orientados al comportamiento, también hay una serie de marcos genéricos y bibliotecas de ayuda útiles para cualquier enfoque preferido.
Las aplicaciones PHP se pueden desplegar y correr en servidores web de producción de multiples maneras.
Una PaaS (Platform as a Service) proporciona la arquitectura de sistema y de red necesaria para ejecutar aplicaciones PHP en la web. Esto significa que se requiere poca o ninguna configuración para lanzar aplicaciones PHP o frameworks de PHP.
Recientemente, PaaS se ha convertido en un método popular para desplegar, alojar y escalar aplicaciones PHP de todos los tamaños. Puedes encontrar una lista de proveedores PaaS para PHP en nuestra sección de recursos.
Si te sientes cómodo con la administración de sistemas, o estás interesado en aprender, los servidores virtuales o dedicados te permiten tener control total sobre el entorno de producción de tu aplicación.
PHP, con el gestor de procesos FastCGI (FastCGI Process Manager, FPM por sus siglas en inglés) integrado en PHP, se complementa muy bien con nginx, el cual es un servidor web ligero y de alto rendimiento. Utiliza menos memoria que Apache y puede manejar mejor más solicitudes concurrentes. Esto es especialmente importante en servidores virtuales que no tienen mucha memoria disponible.
PHP y Apache tienen una larga historia juntos. Apache es ampliamente configurable y cuenta con muchos módulos disponibles para extender su funcionalidad. Es una elección común para servidores compartidos y una configuración sencilla para frameworks PHP y aplicaciones de código abierto como WordPress. Desafortunadamente, Apache por defecto utiliza más recursos que nginx y no puede manejar tantos visitantes al mismo tiempo.
Apache posee varias configuraciones posibles para ejecutar PHP. La más común y más fácil de configurar es el prefork MPM
con mod_php
. Aunque no es la más eficiente en términos de memoria, es la más sencilla de hacer funcionar y utilizar.
Probablemente sea la mejor opción si no deseas profundizar demasiado en los aspectos de administración del servidor.
Ten en cuenta que si usas mod_php
DEBES usar el prefork MPM.
Alternativamente, si quieres sacar más rendimiento y estabilidad de Apache, puedes aprovechar el mismo sistema FPM que
nginx y ejecutar el worker MPM o el event MPM con mod_fastcgi
o mod_fcgid
. Esta configuración será significativamente
más eficiente en memoria y mucho más rápida, pero requiere más trabajo para configurarla.
Si estás ejecutando Apache 2.4 o posterior, puedes usar mod_proxy_fcgi para obtener un gran rendimiento y es fácil de configurar.
PHP debe su popularidad a los servidores compartidos. Es difícil encontrar un hosting sin PHP instalado, pero asegúrate de que sea la última versión. Los servidores compartidos permiten que tú y otros desarrolladores puedan desplegar sitios web en una sola máquina. La ventaja de esto es que se ha convertido en una mercancía barata. La desventaja es que nunca sabes qué tipo de problemas pueden causar tus vecinos; sobrecargar el servidor o abrir agujeros de seguridad son las principales preocupaciones. Si el presupuesto de tu proyecto puede permitirse evitar los servidores compartidos, deberías hacerlo.
Asegúrate de que tus servidores compartidos ofrezcan las últimas versiones de PHP.
Si te encuentras haciendo cambios manuales en el esquema de la base de datos o ejecutando tus pruebas manualmente antes de actualizar tus archivos (manualmente), ¡piénsalo dos veces! Con cada tarea manual adicional necesaria para desplegar una nueva versión de tu aplicación, las posibilidades de cometer errores potencialmente fatales aumentan. Ya sea que estés lidiando con una actualización simple, un proceso de compilación más complejo o incluso una estrategia de integración continua, la automatización es tu aliada.
Estas son las tareas que podrías querer automatizar:
Las herramientas de despliegue se pueden describir como una colección de scripts que llevan a cabo tareas comunes de despliegue de software. La herramienta de despliegue no es parte de tu software, actúa sobre tu software desde ‘afuera’.
Existen muchas herramientas de código abierto disponibles para ayudarte con la automatización de compilación y despliegue, algunas están escritas en PHP y otras no. Esto no debería impedirte usarlas si son más adecuadas para ese trabajo específico. Aquí tienes algunos ejemplos:
Phing puede controlar tu proceso de empaquetado, despliegue o pruebas desde un archivo XML. Phing (basado en Apache Ant) proporciona un conjunto completo de tareas que usualmente se necesitan para instalar o actualizar una aplicación web y se puede extender con tareas personalizadas adicionales, escritas en PHP. Es una herramienta sólida y robusta que ha estado presente durante mucho tiempo, sin embargo, podría percibirse como una herramienta un poco anticuada debido a la forma en que maneja la configuración (archivos XML).
Capistrano es un sistema para programadores intermedios a avanzados que permite ejecutar comandos de manera estructurada y repetible en una o más máquinas remotas. Está preconfigurado para desplegar aplicaciones Ruby on Rails, sin embargo, también puedes desplegar sistemas PHP sin problemas. El uso exitoso de Capistrano depende de un conocimiento práctico de Ruby y Rake.
Ansistrano es un grupo de roles de Ansible para gestionar fácilmente el proceso de despliegue (despliegue y reversión) de aplicaciones de scripting como PHP, Python y Ruby. Es un port de Ansible para Capistrano. Ya ha sido utilizado por muchas empresas de PHP.
Deployer es una herramienta de despliegue escrita en PHP. Es simple y funcional. Sus características incluyen ejecución de tareas en paralelo, despliegue atómico y mantener de la consistencia entre servidores. Dispone recetas de tareas comunes para Symfony, Laravel, Zend Framework y Yii. El artículo de Younes Rafie, Despliegue Fácil de Aplicaciones PHP con Deployer, es un gran tutorial para desplegar tu aplicación con esta herramienta.
Magallanes es otra herramienta escrita en PHP, con una configuración sencilla con archivos YAML. Soporta múltiples servidores y entornos, despliegue atómico, y tiene algunas tareas integradas que puedes utilizar para herramientas y frameworks comunes.
Gestionar y configurar servidores puede ser una tarea abrumadora cuando se esta trabajando con muchos servidores. Existen herramientas para lidiar con esto, que te permiten automatizar tu infraestructura y asegurarte de que tienes los servidores correctos y que están configurados apropiadamente. A menudo, se integran con los principales proveedores de alojamiento en la nube (Amazon Web Services, Heroku, DigitalOcean, etc.) para gestionar instancias, lo que facilita mucho la escalabilidad de una aplicación.
Ansible es una herramienta que gestiona tu infraestructura a través de archivos YAML. Es fácil para comenzar a usar y puede gestionar aplicaciones complejas y a gran escala. Hay una API para gestionar instancias en la nube y puede administrarlas a través de un inventario dinámico utilizando ciertas herramientas.
Puppet es una herramienta que tiene su propio lenguaje y tipos de archivos para gestionar servidores y configuraciones. Se puede usar en una configuración maestro/cliente o en un modo “sin maestro”. En el modo maestro/cliente, los clientes consultan al maestro(s) central(es) para obtener nuevas configuraciones a intervalos establecidos y se actualizan si es necesario. En el modo sin maestro, puedes enviar cambios a tus nodos.
Chef es un potente marco de integración de sistemas basado en Ruby que puedes utilizar para construir todo tu entorno de servidor o máquinas virtuales. Se integra bien con Amazon Web Services a través de su servicio llamado OpsWorks.
La Integración Continua es una práctica de desarrollo de software en la que los miembros de un equipo integran su trabajo con frecuencia, generalmente cada persona integra al menos una vez al día, lo que conduce a múltiples integraciones por día. Muchos equipos descubren que este enfoque reduce significativamente los problemas de integración y permite desarrollar software cohesivo de manera más rápida.
– Martin Fowler
Existen diferentes maneras de implementar la integración continua para PHP. Travis CI ha hecho un gran trabajo al hacer que la integración continua sea una realidad incluso para proyectos pequeños. Travis CI es un servicio de integración continua hospedado. Se puede integrar con GitHub y ofrece soporte para muchos lenguajes, incluido PHP. GitHub tiene flujos de trabajo de integración continua con GitHub Actions.
Ejecutar tu aplicación en diferentes entornos durante el desarrollo y la producción puede dar lugar a errores extraños cuando la pongas en marcha. También es complicado mantener diferentes entornos de desarrollo actualizados con la misma versión de todas las bibliotecas utilizadas al trabajar con un equipo de desarrolladores.
Si estás desarrollando en Windows y desplegando en Linux (o cualquier sistema que no sea Windows) o si estás desarrollando en equipo, deberías considerar usar una máquina virtual. Esto puede sonar complicado, pero además de los entornos de virtualización ampliamente conocidos como VMware o VirtualBox, hay herramientas adicionales que pueden ayudarte a configurar un entorno virtual en unos pocos pasos sencillos.
Vagrant te ayuda a construir tus máquinas virtuales sobre los entornos virtuales conocidos y configurará estos entornos en base a un único archivo de configuración. Estas máquinas pueden configurarse manualmente, o puedes usar software de “provisión” como Puppet o Chef para hacerlo por ti. Proveer la caja base es una excelente manera de asegurarte de que múltiples máquinas se configuren de manera idéntica y elimina la necesidad de mantener listas de comandos de “configuración” complicadas. También puedes “destruir” tu caja base y recrearla sin muchos pasos manuales, lo que facilita crear una instalación “nueva”.
Vagrant crea carpetas para compartir tu código entre tu máquina host y tu máquina virtual, lo que significa que puedes crear y editar tus archivos en tu máquina host y luego ejecutar el código dentro de tu máquina virtual.
Docker — una alternativa ligera a una máquina virtual completa — se llama así porque se centra en “contenedores”. Un contenedor es un bloque de construcción que, en el caso más simple, realiza una tarea específica, por ejemplo, ejecutar un servidor web. Una “imagen” es el paquete que utilizas para construir el contenedor; Docker tiene un repositorio lleno de ellas.
Una aplicación típica de LAMP podría tener tres contenedores: un servidor web, un proceso de PHP-FPM y MySQL. Al igual que con las carpetas compartidas en Vagrant, puedes dejar tus archivos de aplicación donde están y decirle a Docker dónde encontrarlos.
Puedes generar contenedores desde la línea de comandos (ver ejemplo a continuación) o, para facilitar el mantenimiento, construir un archivo docker-compose.yml
para tu proyecto especificando cuáles crear y cómo se comunican entre sí.
Docker puede ser útil si estás desarrollando múltiples sitios web y deseas la separación que viene de instalar cada uno en su propia máquina virtual, pero no tienes el espacio en disco necesario o el tiempo para mantener todo actualizado. Es eficiente: la instalación y las descargas son más rápidas, solo necesitas almacenar una copia de cada imagen, sin importar cuántas veces se use, los contenedores requieren menos RAM y comparten el mismo núcleo del sistema operativo, por lo que puedes tener más servidores ejecutándose simultáneamente, y lleva solo unos segundos detenerlos y iniciarlos, sin necesidad de esperar a que arranque un servidor completo.
Después de instalar Docker en tu máquina, puedes iniciar un servidor web con un solo comando. Lo siguiente descargará una instalación completamente funcional de Apache con la última versión de PHP, mapear el directorio /path/to/your/php/files
a la raíz del documento, que podrás ver en http://localhost:8080
Esto inicializará y lanzará tu contenedor. -d
hace que se ejecute en segundo plano. Para detenerlo y reiniciarlo, simplemente ejecuta docker stop my-php-webserver
y docker start my-php-webserver
(los otros parámetros no son necesarios nuevamente).
El comando anterior muestra una forma rápida de ejecutar un servidor básico. Hay mucho más que puedes hacer (y miles de imágenes preconstruidas en Docker Hub). Tómate el tiempo para aprender la terminología y leer la Guía del Usuario de Docker para sacarle el máximo provecho, y no ejecutes código aleatorio que hayas descargado sin verificar que sea seguro; las imágenes no oficiales pueden no tener los últimos parches de seguridad. Si tienes dudas, mantente en los repositorios oficiales.
El sitio PHPDocker.io generará automáticamente todos los archivos que necesitas para un stack LAMP/LEMP totalmente funcional, incluyendo tu elección de versión de PHP y extensiones.
PHP es bastante rápido por sí mismo, pero pueden surgir cuellos de botella al hacer conexiones remotas, cargar archivos, etc. Afortunadamente, hay varias herramientas disponibles para acelerar ciertas partes de tu aplicación o reducir la cantidad de veces que estas tareas que consumen tiempo necesitan ejecutarse.
Cuando se ejecuta un archivo PHP, primero debe ser compilado en opcodes (instrucciones en lenguaje de máquina para la CPU). Si el código fuente no ha cambiado, los opcodes serán los mismos, por lo que este paso de compilación se convierte en un desperdicio de recursos de la CPU.
Un caché de opcodes evita la compilación redundante al almacenar los opcodes en la memoria y reutilizarlos en llamadas sucesivas. Normalmente verifica la firma o el tiempo de modificación del archivo primero, en caso de que haya habido algún cambio.
Es probable que un caché de opcodes mejore significativamente la velocidad de tu aplicación. Desde PHP 5.5 hay uno incorporado: Zend OPcache. Dependiendo de tu paquete o distribución de PHP, normalmente está activado por defecto; revisa opcache.enable y la salida de phpinfo()
para asegurarte. Para versiones anteriores, hay una extensión de PECL.
Lee más sobre cachés de opcodes:
A veces puede ser beneficioso almacenar en caché objetos individuales en tu código, como en el caso de datos que son costosos de obtener o llamadas a bases de datos donde el resultado es poco probable que cambie. Puedes usar software de almacenamiento en caché de objetos para mantener estos fragmentos de datos en memoria para un acceso extremadamente rápido más adelante. Si guardas estos elementos en un almacén de datos después de recuperarlos, y luego los obtienes directamente desde la caché para las solicitudes siguientes, puedes obtener una mejora significativa en el rendimiento, así como reducir la carga en tus servidores de bases de datos.
Muchas de las soluciones populares de almacenamiento en caché de bytecode también te permiten almacenar datos personalizados, por lo que hay aún más razones para aprovecharlas. APCu y WinCache proporcionan APIs para guardar datos de tu código PHP en su caché de memoria.
Los sistemas de almacenamiento en caché de objetos en memoria más comúnmente utilizados son APCu y memcached. APCu es una excelente opción para el almacenamiento en caché de objetos, incluye una API simple para agregar tus propios datos a su caché de memoria y es muy fácil de configurar y usar. La única limitación real de APCu es que está vinculado al servidor donde está instalado. Memcached, por otro lado, se instala como un servicio separado y se puede acceder a él a través de la red, lo que significa que puedes almacenar objetos en un almacén de datos de alta velocidad en una ubicación central y muchos sistemas diferentes pueden obtenerlos desde allí.
Ten en cuenta que si la caché se comparte o no entre procesos PHP depende de cómo se utilice PHP. Al ejecutar PHP a través de PHP-FPM, la caché se comparte entre todos los procesos de todos los pools. Al ejecutar PHP como una aplicación (Fast-)CGI dentro de tu servidor web, la caché no se comparte, es decir, cada proceso PHP tendrá sus propios datos APCu. Al ejecutar PHP desde la línea de comandos, la caché no se comparte y solo existirá durante la duración del comando. Por lo tanto, debes ser consciente de tu situación y objetivos. Además, podrías considerar usar memcached en su lugar, ya que no está vinculado a los procesos PHP.
En una configuración en red, APCu generalmente superará a memcached en términos de velocidad de acceso, pero memcached podrá escalar más rápido y en mayor medida. Si no esperas tener varios servidores ejecutando tu aplicación, o no necesitas las características adicionales que ofrece memcached, entonces probablemente APCu sea tu mejor opción para el almacenamiento en caché de objetos.
Ejemplo de lógica usando APCu:
Ten en cuenta que antes de PHP 5.5, existía la extensión APC, que proporcionaba tanto una caché de objetos como una caché de bytecode. El nuevo APCu es un proyecto para llevar la caché de objetos de APC a PHP 5.5+, ya que PHP ahora tiene una caché de bytecode incorporada (OPcache).
PHPDoc es un estándar informal para comentar el código PHP. Hay muchas [etiquetas] diferentes disponibles. La lista completa de etiquetas y ejemplos se puede encontrar en el [manual de PHPDoc].
A continuación se muestra un ejemplo de cómo podrías documentar una clase con algunos métodos:
La documentación de la clase en su conjunto tiene la etiqueta @author y una etiqueta @link. La etiqueta @author se usa para documentar al autor del código y puede repetirse para documentar a varios autores. La etiqueta @link se usa para enlazar a un sitio web que indique una relación entre el sitio web y el código.
Dentro de la clase, el primer método tiene una etiqueta @param que documenta el tipo, nombre y descripción del parámetro que se pasa al método. Además, tiene las etiquetas @return y @throws para documentar el tipo de retorno y cualquier excepción que pueda lanzarse, respectivamente.
Los métodos segundo y tercero son muy similares y tienen una única etiqueta @param, al igual que el primer método. La diferencia importante entre los bloques de documentación de los métodos segundo y tercero es la inclusión/exclusión de la etiqueta @return. @return void
nos informa explícitamente que no hay retorno; históricamente, omitir la declaración @return void
también resulta en la misma acción (sin retorno).
Es difícil encontrar miembros de la comunidad PHP interesantes y bien informados cuando se está empezando. Puedes encontrar una lista abreviada de miembros de la comunidad PHP para empezar en:
En lugar de reinventar la rueda, muchos desarrolladores de PHP utilizan frameworks para crear aplicaciones web. Los frameworks eliminan muchas de las preocupaciones de bajo nivel y proporcionan interfaces útiles y fáciles de usar para completar tareas comunes.
No es necesario utilizar un framework para todos los proyectos. A veces lo mejor es utilizar PHP sin más, pero si necesitas un framework, existen tres tipos principales:
Los micro-frameworks son esencialmente una envoltura para enrutar una petición HTTP a un callback, controlador, método, etc. tan rápido como sea posible, y a veces vienen con algunas bibliotecas adicionales para ayudar al desarrollo, tales como envolturas básicas de bases de datos y similares. Se utilizan principalmente para crear servicios HTTP remotos.
Muchos frameworks añaden un número considerable de funciones además de las disponibles en un microframework; son los llamados Full-Stack Frameworks. Suelen incluir ORM, paquetes de autenticación, etc.
Los frameworks basados en componentes son colecciones de bibliotecas especializadas y de propósito único. Los distintos frameworks basados en componentes pueden utilizarse juntos para crear un microframe o un framework completo.
Como ya se ha mencionado, los “componentes” son otro enfoque del objetivo común de crear, distribuir e implementar código compartido. Existen varios repositorios de componentes, los dos principales de los cuales son:
Ambos repositorios tienen herramientas de línea de comandos asociadas para ayudar en los procesos de instalación y actualización, y se han explicado con más detalle en la sección Gestión de dependencias.
También existen frameworks basados en componentes y proveedores de componentes que no ofrecen ningún tipo de framework. Estos proyectos proporcionan otra fuente de paquetes que idealmente tienen poca o ninguna dependencia de otros paquetes, o frameworks específicos.
Por ejemplo, puede utilizar el Paquete de Validación FuelPHP, sin necesidad de utilizar el propio framework FuelPHP.
Los componentes Illuminate de Laravel se desacoplarán mejor del framework Laravel. Por ahora, sólo los componentes mejor desacoplados del framework Laravel se enumeran más arriba..
Puede suscribirse a boletines semanales para mantenerse informado sobre nuevas bibliotecas, últimas noticias, eventos y anuncios generales, así como sobre los recursos adicionales que se publican de vez en cuando:
También hay semanarios en otras plataformas que podrían interesarte; aquí tienes una lista de algunos.
Existen muchos libros sobre PHP; lamentablemente, algunos son ya bastante antiguos y han dejado de ser precisos. En particular, evite libros sobre “PHP 6”, una versión que ahora nunca existirá. La siguiente versión mayor de PHP después de la 5.6 fue “PHP 7”, en parte debido a esto.
Esta sección pretende ser un documento vivo de libros recomendados sobre desarrollo PHP en general. Si desea que su libro sea añadido, envíe un PR y será revisado para comprobar su relevancia.
The PHP community is as diverse as it is large, and its members are ready and willing to support new PHP programmers. Consider joining your local PHP user group (PUG) or attending larger PHP conferences to learn more about the best practices shown here. You can hang out on IRC in the #phpc channel on irc.freenode.com and follow the @phpc on Twitter or Mastodon. Get out there, meet new developers, learn new topics, and above all, make new friends! Other community resources include StackOverflow.
If you live in a larger city, odds are there’s a PHP user group nearby. You can easily find your local PUG at
PHP.ug. Alternate sources might be Meetup.com or a search for php user group near me
using your favorite search engine (i.e. Google). If you live in a smaller town, there may not be a
local PUG; if that’s the case, start one!
Special mention should be made of two global user groups: NomadPHP and PHPWomen. NomadPHP offers twice monthly online user group meetings with presentations by some of the top speakers in the PHP community. PHPWomen is a non-exclusive user group originally targeted towards the women in the PHP world. Membership is open to everyone who supports a more diverse community. PHPWomen provide a network for support, mentorship and education, and generally promote the creating of a “female friendly” and professional atmosphere.
The PHP community also hosts larger regional and national conferences in many countries around the world. Well-known members of the PHP community usually speak at these larger events, so it’s a great opportunity to learn directly from industry leaders.
ElePHPant is that beautiful mascot of the PHP project with an elephant in its design. It was originally designed for the PHP project in 1998 by Vincent Pontier - spiritual father of thousands of elePHPants around the world - and ten years later adorable plush elephant toys came to birth as well. Now elePHPants are present at many PHP conferences and with many PHP developers at their computers for fun and inspiration.