Entorno de ejecución de PHP

El entorno de ejecución de PHP es la pila de software encargada de instalar el código de tu servicio web y sus dependencias, así como de ejecutar el servicio.

Para especificar PHP o superior en el entorno estándar de App Engine, declara el entorno de ejecución en el archivo app.yaml. Por ejemplo:

runtime: phpVERSION

En el ejemplo anterior, VERSION son los números de versión MAJOR y MINOR de PHP. Por ejemplo, para usar la última versión de PHP, PHP 8.3, especifica 83.

Para otras versiones de PHP compatibles y la versión de Ubuntu correspondiente para tu versión de PHP, consulta el programa de asistencia del entorno de ejecución.

Versión de PHP

El entorno de ejecución de PHP usa la última versión estable de la versión que se especifica en tu archivo app.yaml. App Engine se actualiza de forma automática a las nuevas versiones de actualización de parche, pero no se actualizará automáticamente a las versiones secundarias.

Por ejemplo, tu app podría implementarse en PHP 7.3.0 y, luego, actualizarse de forma automática a la versión 7.3.1, pero no se actualizará de manera automática a la versión PHP 7.4.0.

Inicio de la app

Deberás implementar un controlador frontal para controlar todos los enrutamientos de solicitudes.

En los siguientes ejemplos, se muestran diferentes formas de entregar tu app:

  • Si tu app contiene un archivo public/index.php o index.php, App Engine lo usa para entregarla.

    Te recomendamos usar un framework, como Laravel, Symfony o Slim, ya que proporcionan enrutamiento ligero para implementar apps de PHP y realizar operaciones de escritura en ellas con rapidez. Puedes ver un controlador principal Slim de ejemplo.

    Sin embargo, si migras una app heredada, consulta el siguiente archivo index.php de muestra para importar los archivos PHP que necesitas e implementa el controlador frontal de forma manual:

    switch (@parse_url($_SERVER['REQUEST_URI'])['path']) {
        case '/':
            require 'homepage.php';
            break;
        case '/contact.php':
            require 'contact.php';
            break;
        default:
            http_response_code(404);
            exit('Not Found');
    }
  • Si especificas el elemento entrypoint opcional en el archivo app.yaml, App Engine usa el comando en el elemento entrypoint para entregar tu app en lugar de usar public/index.php o index.php:

        entrypoint: serve path/to/my/front/controller.php
    

    El campo entrypoint usa el comando integrado serve, que es un programa dentro de los entornos de ejecución de PHP que inicia la implementación de php-fpm y un servidor web en segundo plano. Este servidor web enruta todo el tráfico al archivo PHP proporcionado con el patrón de diseño del controlador principal.

    El comando serve tiene dos marcas opcionales:

    • --workers=N: especifica la cantidad N de trabajadores php-fpm. Si no configuras la marca --workers, el comando serve estima la cantidad de trabajadores según la memoria disponible. Si deseas obtener mejores resultados, configura los valores de la marca --workers en el comando serve y el elemento max_concurrent_requests para que sean el mismo número.

    • --enable-dynamic-workers: especifica que deseas que los trabajadores php-fpm se generen solo cuando sea necesario. La opción predeterminada es usar una política estática para los trabajadores php-fpm. Puedes cambiar la cantidad máxima de trabajadores generados mediante la marca --workers=N. De forma predeterminada, se usa la cantidad máxima de trabajadores generados que se indica en la política estática.

    Las marcas opcionales deben estar antes de la ruta del controlador principal:

        entrypoint: serve --workers=2 --enable-dynamic-workers path/to/index.php
    
  • Puedes implementar un proceso de trabajador de larga duración si configuras el elemento entrypoint en la ruta del archivo del proceso de trabajador:

        entrypoint: php long-running-worker-file.php
    

    Si el elemento entrypoint ejecuta una secuencia de comandos con un proceso de larga duración, como un trabajador de Pub/Sub suscrito a un tema, no uses el comando serve.

Para obtener más información, consulta la referencia de app.yaml.

Extensiones habilitadas

Las siguientes extensiones se habilitaron en los entornos de ejecución de PHP para App Engine:

  • BCMath
  • bz2
  • Calendar
  • core
  • cgi
  • ctype
  • cURL
  • date
  • dba
  • dom
  • enchant
  • Exif
  • fcgi
  • fileinfo
  • filter
  • FTP
  • GD
  • gettext
  • GMP
  • hash
  • iconv
  • intl
  • json
  • LDAP
  • libxml
  • mbstring
  • MYSQLi
  • mysqlnd
  • MySQL (PDO)
  • OPcache
  • OpenSSL
  • PCNTL
  • pcre
  • PDO
  • pgsql
  • Phar
  • posix
  • PostgreSQL (PDO)
  • Reflection
  • session
  • Shmop
  • SimpleXML
  • SOAP
  • Sockets
  • sodium (PHP 8.x only, not available for PHP 7.x)
  • SPL
  • SQLite (PDO)
  • SQLite3
  • standard
  • test
  • tidy
  • tokenizer
  • XML
  • XMLreader
  • XMLrpc (PHP 7.x only, not available for PHP 8.x)
  • XMLwriter
  • XSL
  • zend
  • Zip
  • Zlib

Extensiones de carga dinámica

Si se configura php.ini, las siguientes extensiones se pueden cargar de forma dinámica:

Para habilitar estas extensiones, agrégales directivas en tu archivo php.ini en extension, por ejemplo:

extension=memcached.so
extension=grpc.so
extension=protobuf.so
extension=mongodb.so
extension=imagick.so
extension=opencensus.so
extension=redis.so

[opentelemetry]
extension=opentelemetry.so

Variables de entorno

El entorno de ejecución configura las siguientes variables del entorno:

Variable de entorno Descripción
GAE_APPLICATION ID de tu aplicación de App Engine. Este ID tiene el prefijo “region code~”, como “e~”, para aplicaciones implementadas en Europa.
GAE_DEPLOYMENT_ID ID de la implementación actual.
GAE_ENV Entorno de App Engine. Se define en standard.
GAE_INSTANCE ID de la instancia en la que se está ejecutando tu servicio.
GAE_MEMORY_MB Cantidad de memoria disponible para el proceso de la aplicación, en MB.
GAE_RUNTIME Entorno de ejecución especificado en el archivo app.yaml.
GAE_SERVICE Nombre de servicio especificado en el archivo app.yaml. Si no se especifica un nombre de servicio, se asigna default.
GAE_VERSION Etiqueta de la versión actual de tu servicio.
GOOGLE_CLOUD_PROJECT ID del proyecto de Google Cloud asociado a tu aplicación.
PORT Puerto que recibe las solicitudes HTTP.
NODE_ENV (solo disponible en el entorno de ejecución de Node.js) Se establece en production cuando se implementa tu servicio.

Puedes definir variables de entorno adicionales en tu archivo app.yaml, pero no es posible anular los valores anteriores, excepto NODE_ENV.

Proxies HTTPS y de reenvío

App Engine finaliza las conexiones HTTPS en el balanceador de cargas y reenvía las solicitudes a tu aplicación. Algunas aplicaciones deben determinar la IP y el protocolo de la solicitud original. La dirección IP del usuario está disponible en el encabezado X-Forwarded-For estándar. Las aplicaciones que necesitan esta información deben configurar sus frameworks web para que confíen en el proxy.

Sistema de archivos

El entorno de ejecución incluye un directorio /tmp que admite escritura, y todos los demás directorios tienen acceso de solo lectura. Escribir en /tmp ocupa memoria del sistema. Si deseas obtener más información, consulta Asistencia para tempnam() y sys_get_temp_dir().

Servidor de metadatos

Cada instancia de tu aplicación puede usar el servidor de metadatos de App Engine para consultar información acerca de la instancia y del proyecto.

Puedes acceder al servidor de metadatos a través de los siguientes extremos:

  • http://metadata
  • http://metadata.google.internal

Las solicitudes enviadas al servidor de metadatos deben incluir el encabezado de solicitud Metadata-Flavor: Google. Este encabezado indica que la solicitud se envió con la intención de recuperar valores de metadatos.

La siguiente tabla enumera los extremos en los que puedes realizar solicitudes HTTP para metadatos específicos:

Extremo de metadatos Descripción
/computeMetadata/v1/project/numeric-project-id El número de proyecto asignado a tu proyecto.
/computeMetadata/v1/project/project-id ID del proyecto asignado a tu proyecto.
/computeMetadata/v1/instance/region La región en la que se está ejecutando la instancia.
/computeMetadata/v1/instance/service-accounts/default/aliases
/computeMetadata/v1/instance/service-accounts/default/email Correo electrónico de la cuenta de servicio predeterminada asignado a tu proyecto.
/computeMetadata/v1/instance/service-accounts/default/ Enumera todas las cuentas de servicio predeterminadas para tu proyecto.
/computeMetadata/v1/instance/service-accounts/default/scopes Enumera todos los alcances compatibles para las cuentas de servicio predeterminadas.
/computeMetadata/v1/instance/service-accounts/default/token Muestra el token de autenticación que puede usarse para autenticar tu aplicación en otras APIs de Google Cloud.

Por ejemplo, para recuperar tu ID del proyecto, envía una solicitud a http://metadata.google.internal/computeMetadata/v1/project/project-id.

El siguiente es un ejemplo de cómo llamar a los extremos de metadatos con cURL o con la biblioteca cliente de Google Cloud:

/**
 * Requests a key from the Metadata server using the Google Cloud SDK. Install
 * the Google Cloud SDK by running "composer install google/cloud"
 *
 * @param $metadataKey the key for the metadata server
 */
function request_metadata_using_google_cloud($metadataKey)
{
    $metadata = new Google\Cloud\Core\Compute\Metadata();
    $metadataValue = $metadata->get($metadataKey);

    return $metadataValue;
}

/**
 * Requests a key from the Metadata server using cURL.
 *
 * @param $metadataKey the key for the metadata server
 */
function request_metadata_using_curl($metadataKey)
{
    $url = 'http://metadata/computeMetadata/v1/' . $metadataKey;

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Metadata-Flavor: Google'));
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
    curl_setopt($ch, CURLOPT_FOLLOWLOCATION, true);
    return curl_exec($ch);
}

Sesiones

PHP proporciona una capa de administración de sesión que permite que las aplicaciones web preserven la información del estado del usuario entre las solicitudes. Las sesiones en App Engine funcionan de forma similar a las sesiones en cualquier otra app de PHP.

Para definir una variable en la sesión de un usuario, puedes usar el siguiente código:

session_start();
$_SESSION['Foo'] = 'Bar';

Con el siguiente código, se imprimirá Bar en una solicitud posterior del mismo usuario:

session_start();
print $_SESSION['Foo']; // prints Bar

Para las sesiones de mayor duración, usa un servicio de almacenamiento alternativo, como Cloud SQL.

Claves $_SERVER especiales

En PHP, se encuentra disponible el arreglo $_SERVER[] especial en el permiso de la solicitud. Además de los parámetros CGI estándar, App Engine agrega algunas claves útiles:

  • GAE_APPLICATION: Es el ID del proyecto de Google Cloud de la app actual.
  • GAE_DEPLOYMENT_ID: Es el ID del código fuente implementado.
  • GAE_ENV: Es el entorno de App Engine (estándar o flexible) en el que se ejecuta tu app.
  • GAE_INSTANCE: Es el nombre de la instancia en ejecución actual.
  • GAE_MEMORY_MB: Es la cantidad de memoria disponible para el proceso de la app, en MB.
  • GAE_RUNTIME: Es el entorno de ejecución especificado en tu archivo app.yaml, como php72.
  • GAE_SERVICE: Es el nombre del servicio implementado actualmente.
  • GAE_VERSION: Es el nombre de la versión implementada actualmente.
  • GOOGLE_CLOUD_PROJECT: Es el ID del proyecto de Google Cloud.
  • HTTP_X_APPENGINE_CITY: Es el nombre de la ciudad donde se originó la solicitud. Por ejemplo, una solicitud de la ciudad de Mountain View podría tener el valor de encabezado de Mountain View.
  • HTTP_X_APPENGINE_CITYLATLONG: la latitud y longitud de la ciudad donde se originó la solicitud. La string podría ser “37.386051,-122.083851” para una solicitud de Mountain View.
  • HTTP_X_APPENGINE_COUNTRY: país donde se originó la solicitud, como un código de país ISO 3166-1 Alfa-2. App Engine determina este código a partir de la dirección IP del cliente.
  • HTTP_X_APPENGINE_HTTPS: Verifica el uso de HTTPS.
  • HTTP_X_APPENGINE_REGION: Es el nombre de la región donde se originó la solicitud. Este valor solo tiene sentido en el contexto del país en X-Appengine-Country. Por ejemplo, si el país es “EE.UU.” y la región es “ca”, significa “California”, no Canadá.
  • HTTP_X_APPENGINE_USER_IP: Es la dirección IP del cliente. Ten en cuenta que $_SERVER['HTTP_X_APPENGINE_USER_IP'] es la única forma en que la app puede recuperar la dirección IP del cliente. La variable $_SERVER['REMOTE_ADDR'] no está disponible en App Engine.

Directivas con nuevos valores predeterminados de inicialización

En la siguiente tabla, se especifican las directivas cuyos valores predeterminados de inicialización son distintos a los suministrados con el intérprete de PHP estándar disponible de php.net. Para encontrar los valores predeterminados de las directivas no especificadas en la siguiente tabla, haz referencia a las directivas de php.ini.

Directiva Valor predeterminado en App Engine
expose_php Off
memory_limit -1
max_execution_time 0
error_reporting E_ALL & ~E_DEPRECATED & ~E_STRICT
display_errors Off
display_startup_errors Off
log_errors On
log_errors_max_len 0
ignore_repeated_errors Off
ignore_repeated_source Off
html_errors Off
opcache.enable On
opcache.validate_timestamps Off
opcache.memory_consumption 32

Incluye estas directivas predeterminadas en un archivo php.ini para la app a fin de anularlas.

Compatibilidad con tempnam() y sys_get_temp_dir()

Las apps de App Engine se ejecutan en una zona de pruebas de seguridad en la que solo se puede escribir en el directorio /tmp y solo se puede almacenar este directorio en la RAM de la instancia. Por este motivo, la versión de tempnam() de App Engine muestra un archivo temporal en la memoria que se puede escribir en una solución de almacenamiento permanente, como buckets de Cloud Storage.

El siguiente es un ejemplo de cómo realizar operaciones de escritura en el archivo temporal en la memoria mediante file_put_contents() y fwrite().

<?php
$dir = sys_get_temp_dir();
$tmp = tempnam($dir, "foo");
file_put_contents($tmp, "hello");
$f = fopen($tmp, "a");
fwrite($f, " world");
fclose($f);
echo file_get_contents($tmp);

El resultado esperado del ejemplo sería el siguiente:

hello world

Administra dependencias con Composer

Para obtener más información, consulta la página Especifica dependencias.