PHP en EGPHP

Todo lo que construimos empieza con PHP.

Nuestro equipo lleva veinticinco años escribiendo y ejecutando PHP, desde PHP 4. Los servidores, el panel de control y los sitios que cuidamos parten de aquí.

Veinticinco años, versión a versión

No leímos sobre estas versiones. Actualizamos sitios reales a través de cada una de ellas, y cada fila de abajo es un cambio que tuvimos que resolver en un servidor en producción.

  1. PHP 4 2000

    Sesiones y búfer de salida, integrados

    Llegó el Zend Engine, y las sesiones y el búfer de salida pasaron a formar parte del lenguaje en lugar de ser complementos. Toda una generación de los primeros sitios dinámicos se escribió sobre él.

    • Zend Engine
    • session_start()
    • ob_start()
    Lo que supuso para nosotros

    Donde empezó nuestro equipo: sitios escritos a mano en servidores compartidos, con register_globals todavía activado.

  2. PHP 5.0 2004

    Un modelo de objetos de verdad

    Zend Engine 2 trajo clases con visibilidad, interfaces y excepciones, objetos pasados por manejador en lugar de copiados, y las extensiones MySQLi y SimpleXML.

    • private
    • interface
    • try / catch
    • mysqli
    Lo que supuso para nosotros

    El código podía organizarse en clases compartidas por todo un equipo, y la base de datos estrenó un driver moderno.

  3. PHP 5.3 2009

    Espacios de nombres y closures

    Espacios de nombres, funciones anónimas y enlace estático en tiempo de ejecución: la base sobre la que después se construyeron Composer y el ecosistema de paquetes compartidos.

    • namespace
    • function () use ()
    • static::
    Lo que supuso para nosotros

    Por fin, bibliotecas de distintos autores podían convivir en un mismo proyecto sin que sus nombres chocaran.

  4. PHP 5.4 2012

    Traits, arrays cortos y una limpieza Rompió código antiguo

    Traits, la sintaxis corta de arrays [] y un servidor de desarrollo integrado, mientras que register_globals, las magic quotes y el safe mode se eliminaron para siempre.

    • trait
    • [ ]
    • php -S
    Lo que supuso para nosotros

    Los sitios antiguos que dependían de register_globals dejaron de funcionar, y actualizarlos obligaba a arreglarlos primero.

  5. PHP 5.5 2013

    OPcache de serie

    OPcache pasó a incluirse en el propio PHP y mantenía en memoria los scripts compilados, junto con los generadores y password_hash().

    • opcache
    • yield
    • password_hash()
    Lo que supuso para nosotros

    Código compilado guardado en memoria en lugar de releerlo en cada petición. Sigue siendo el primer ajuste que revisamos en cualquier servidor PHP.

  6. PHP 6 nunca publicada

    La versión que nunca salió

    PHP 6 se diseñó en torno a cadenas Unicode nativas y se abandonó. La siguiente versión se numeró 7 para que no se confundiera con los libros y planes escritos para la 6.

  7. PHP 7.0 2015

    El salto de velocidad Rompió código antiguo

    Un motor reconstruido que, según el proyecto PHP, era hasta el doble de rápido que la 5.6 y consumía menos memoria, además de declaraciones de tipos escalares y de retorno, ?? y <=>.

    • int $id
    • : string
    • ??
    • <=>
    Lo que supuso para nosotros

    Se eliminaron las antiguas funciones mysql_*, un motivo frecuente por el que un sitio antiguo se rompía con esta actualización.

  8. PHP 7.4 2019

    Propiedades tipadas y precarga

    Propiedades tipadas, funciones flecha, el operador ??=, la precarga de OPcache y FFI.

    • public int $id
    • fn ($x) =>
    • ??=
    Lo que supuso para nosotros

    La última versión 7.x, y en la que muchas aplicaciones antiguas se quedaron más tiempo; por eso seguimos sacando sitios de ella.

  9. PHP 8.0 2020

    JIT, atributos y argumentos con nombre Rompió código antiguo

    Un compilador JIT, atributos, argumentos con nombre, tipos de unión, match, el operador nullsafe ?-> y la promoción de propiedades en el constructor.

    • #[Attribute]
    • match
    • ?->
    • JIT
    Lo que supuso para nosotros

    Muchas advertencias pasaron a ser errores y cambiaron las comparaciones entre cadenas y números, así que un código que funcionaba sin problemas en 7.4 podía detenerse en 8.0.

  10. PHP 8.1 2021

    Enums, readonly y fibers

    Enums nativos, propiedades readonly, fibers, el tipo de retorno never y la sintaxis de callables de primera clase.

    • enum
    • readonly
    • Fiber
    • never
    Lo que supuso para nosotros

    Los fibers abrieron el camino a bibliotecas PHP asíncronas sin cambiar cómo se ejecuta una petición normal.

  11. PHP 8.2 2022

    Clases readonly y un aviso para el código antiguo

    Clases readonly, tipos DNF, true, false y null como tipos independientes, y una nueva extensión Random.

    • readonly class
    • (A&B)|null
    • Random\Randomizer
    Lo que supuso para nosotros

    Las propiedades dinámicas quedaron obsoletas, y los plugins antiguos llenaron los registros de avisos hasta que se actualizaron.

  12. PHP 8.3 2023

    Constantes tipadas y #[\Override]

    Constantes de clase tipadas, el atributo #[\Override], json_validate() y el acceso dinámico a constantes de clase.

    • const string
    • #[\Override]
    • json_validate()
    Lo que supuso para nosotros

    Una versión más tranquila, lo que la convierte en un paso sencillo para los sitios que ya están en 8.2.

  13. PHP 8.4 2024

    Hooks de propiedades

    Hooks de propiedades, visibilidad asimétrica, objetos lazy, un analizador DOM compatible con HTML5 y new MyClass()->method() sin los paréntesis adicionales.

    • get { }
    • public private(set)
    • Dom\HTMLDocument
    Lo que supuso para nosotros

    Los getters y setters que antes necesitaban un método cada uno ahora pertenecen a la propia propiedad, así que hay menos código que mantener.

  14. PHP 8.5 2025

    El operador pipe Actual

    El operador pipe |>, una extensión URI integrada, clone with, el atributo #[\NoDiscard], array_first() y array_last(), y un backtrace en los errores fatales.

    • |>
    • Uri\Rfc3986\Uri
    • clone($o, [ ])
    Lo que supuso para nosotros

    La línea de versiones actual, y con la que empezamos los sitios nuevos cuando su código lo admite.

Los años son los de la primera versión de cada una, según el propio historial de versiones del proyecto PHP.

Sigue una petición a través de la pila

Una página de un sitio PHP atraviesa cinco capas al entrar y vuelve a subir por esas mismas cinco al salir. Nos encargamos de todas ellas, y cada una tiene su propia página.

  1. El visitante

    Un navegador pide una página por HTTPS. El certificado, el firewall y las reglas que protegen el servidor deciden si la petición entra o no.

  2. El servidor web

    Nginx o LiteSpeed recibe la conexión, sirve por sí mismo las imágenes y los archivos, y pasa solo el trabajo de PHP al pool que tiene detrás.

  3. El entorno de ejecución de PHP

    Pools de PHP-FPM, uno por sitio, cada uno con la versión de PHP que necesita su código, con OPcache en caliente y procesos dimensionados para el tráfico.

  4. Tu código

    Un framework o una plataforma ya hecha convierte la petición en una página: tu propia aplicación Laravel, o WordPress, Magento, Moodle y los demás.

  5. Los datos

    MySQL o MariaDB guarda los registros, y Redis mantiene en memoria lo que se pide una y otra vez.

Debajo de las cinco

El propio servidor

Nuestros propios servidores, gestionados por el mismo equipo, con nuestro propio panel de control encima.

Pasar a un PHP más nuevo sin una mañana de sustos

Cada sitio tiene su propio pool, así que un servidor puede ejecutar varias versiones de PHP a la vez y cada sitio da el paso cuando su código está listo, no cuando lo está el servidor.

  1. Anotamos lo que ejecuta cada sitio

    Su versión de PHP, sus extensiones y los plugins o paquetes que lo frenan.

  2. Una copia prueba la nueva versión

    El sitio se copia y se ejecuta en la siguiente versión de PHP, y su registro de errores se lee línea por línea.

  3. Arreglamos lo que se rompe

    Las funciones eliminadas, las llamadas obsoletas y los plugins sin actualización se corrigen o se sustituyen.

  4. Un sitio cada vez

    Cada sitio pasa a su nuevo pool por separado, y puede volver atrás al instante si se pasó algo por alto.

php-fpmUn servidor, varias versiones
SitioPHPPoolEstado
shop.example.com 8.4 fpm-shop en vivo
blog.example.com 8.3 fpm-blog en vivo
crm.example.com 7.4 → 8.3 fpm-crm en una copia
learn.example.com 8.3 fpm-learn en vivo
Un servidor de ejemplo

Tráenos tu PHP

Un sitio antiguo que necesita un PHP más nuevo, una plataforma que instalar o un servidor donde ejecutarlo todo. Cada trabajo se presupuesta tras una breve conversación.