סביבת זמן הריצה של PHP

סביבת זמן הריצה של PHP היא מחסנית התוכנה שאחראית להתקנת קוד האפליקציה והתלות שלה, ולאחר מכן להפעלת האפליקציה בסביבה הגמישה.

גרסאות PHP

‫PHP 8.5 משתמש בחבילות buildpack. במאמר הזה מופיעה רשימה מלאה של גרסאות PHP נתמכות וגרסאות Ubuntu התואמות להן.

כדי להשתמש בגרסת PHP נתמכת, צריך:

  • מתקינים את gcloud CLI גרסה 420.0.0 ומעלה. כדי לעדכן את כלי ה-CLI, מריצים את הפקודה gcloud components update. כדי לראות את הגרסה המותקנת, מריצים את הפקודה gcloud version.

  • כדי לציין מערכת הפעלה, צריך לכלול את ההגדרות runtime_config ו-operating_system בקובץ app.yaml.

  • מצהירים על שורש המסמך של האפליקציה בקובץ app.yaml:

      runtime: php
      env: flex
    
      runtime_config:
          operating_system: "ubuntu24"
          document_root: "web"
    

    אפשר לציין את ספריית הבסיס של הפרויקט (.) כספריית הבסיס של המסמך, אבל מומלץ להשתמש בספריית משנה להגדרה document_root.

    קוד המקור נמצא בספרייה /workspace ולא בספריית השורש (/). אם מבטלים את ברירת המחדל של הגדרה כלשהי, התהליכים NGINX או supervisor מפנים לקובץ ההגדרות בספרייה הזו. כדי לעדכן הפניות תואמות, צריך:

    • מעדכנים את כל ההצהרות include בהגדרות של NGINX כך שיהיו יחסיות ל-/workspace במקום ל-/etc/nginx.

    • קבצים מסוימים, כמו gzip_params, לא נכללים. כדי להפנות לקבצים האלה, צריך לכלול קובץ משלכם או להעתיק מ-GitHub. קבצים כמו mime.types ו-fastcgi_params זמינים בספרייה /etc/nginx.

    • חלק מהמודולים של NGINX, כמו nginx-plus-module-ndk, לא מותקנים. מגדירים את הערך $docroot או מוסיפים את הערך באופן ידני לקובץ התצורה NGINX.

  • אפשר גם לציין גרסת זמן ריצה על ידי:

    • כוללים את ההגדרה runtime_version בקובץ app.yaml. כברירת מחדל, נעשה שימוש בגרסת ה-PHP העדכנית ביותר אם ההגדרה runtime_version לא מצוינת.

      • כדי לציין PHP 8.5 ב-Ubuntu 24:

        runtime: php
        env: flex
        
        runtime_config:
            operating_system: "ubuntu24"
            runtime_version: "8.5"
            document_root: .
        
      • כדי לציין את הגרסה העדכנית ביותר של PHP שנתמכת ב-Ubuntu 24:

          runtime: php
          env: flex
        
          runtime_config:
              operating_system: "ubuntu24"
              document_root: .
        
    • כוללים גרסת PHP בקובץ composer.json.

      {
          "require": {
              "php": "8.5.*"
          }
      }
      

    מידע נוסף זמין במאמר בנושא app.yaml.

גרסאות קודמות של זמן הריצה

כדי להשתמש ב-PHP בגרסה 7.3 ומטה, צריך:

  • מגדירים את תיקיית השורש של האפליקציה. אפשר לעשות את זה בקובץ app.yaml:

    runtime: php
    env: flex
    api_version: 1
    
    runtime_config:
      document_root: .
    

    אפשר לציין את ספריית הבסיס של הפרויקט (.) כספריית הבסיס של המסמך, אבל מומלץ להשתמש בספריית משנה להגדרה document_root.

  • כדי למנוע שדרוג אוטומטי של האפליקציה כשגרסה חדשה של PHP תהיה זמינה, צריך לציין גרסת PHP בקובץ composer.json.

    {
        "require": {
            "php": "7.3.*"
        }
    }
    

תמיכה בסביבות זמן ריצה אחרות של PHP

אם אתם צריכים להשתמש בגרסת PHP שלא נתמכת, אתם יכולים ליצור סביבת ריצה בהתאמה אישית ולבחור תמונת בסיס תקינה עם גרסת ה-PHP שאתם צריכים.

לגבי תמונות בסיס שסופקו על ידי Google או תמונות בסיס של Docker PHP, אפשר לעיין במאמר בנושא יצירת סביבות ריצה בהתאמה אישית.

התאמה אישית של NGINX

כדי להגדיר קובץ תצורה בהתאמה אישית, כוללים את הקובץ nginx-app.conf בספריית הבסיס של הפרויקט.

כברירת מחדל, בקר ה-front של המסגרת משתמש בקובץ index.php. יכול להיות שתצטרכו לשנות את זה למשהו אחר בפרויקט שלכם. לדוגמה, ב-framework של Symfony נעשה שימוש ב-app.php במקום ב-index.php. אפשר לשנות את שם הקובץ בקטע runtime_config בקובץ app.yaml:

runtime: php
env: flex

runtime_config:
  operating_system: "ubuntu24"
  document_root: .
  front_controller_file: app.php

בגרסה 7.3 ובגרסאות קודמות, קובץ התצורה nginx-app.conf נכלל בקטע השרת של קובץ התצורה הראשי NGINX. לדוגמה, קובץ ברירת המחדל של ההגדרות php-app.conf מכיל את השורות הבאות:

location / {
# try to serve files directly, fallback to the front controller
try_files $uri /$front_controller_file$is_args$args;
}

כדי להגדיר קובץ תצורה בהתאמה אישית, יוצרים את הקובץ nginx-app.conf בספריית השורש של הפרויקט. סביבת זמן הריצה מחליפה את קובץ ברירת המחדל בקובץ שאתם מספקים.

כברירת מחדל, בקר ה-front של המסגרת משתמש בקובץ index.php. יכול להיות שתצטרכו לשנות את זה למשהו אחר בפרויקט שלכם. לדוגמה, ב-framework של Symfony נעשה שימוש ב-app.php במקום ב-index.php. אפשר לשנות את שם הקובץ בקטע runtime_config בקובץ app.yaml:

runtime: php
env: flex

runtime_config:
  document_root: .
  front_controller_file: app.php

OPcache

מפעילים את OPcache בקובץ php.ini. במסמך הרשמי מוסבר איך להגדיר את OPcache.

כדי להשבית את OPcache, יוצרים או עורכים את הקובץ php.ini עם השורה הבאה:

opcache.enable=0

תלויות

סביבת זמן הריצה מחפשת קובץ composer.json בספריית קובצי המקור של האפליקציה ומשתמשת ב-composer כדי להתקין תלות לפני הפעלת האפליקציה. מידע נוסף על הצהרה וניהול של חבילות זמין במאמר שימוש בספריות PHP.

שימוש בתוספי PHP

התוספים הבאים של PHP מותקנים מראש ומופעלים במערכת:

גרסאות PHP נתמכות

אפשר להפעיל את התוספים הבאים באמצעות קובץ php.ini:

גרסה 7.3 וגרסאות קודמות

התוספים הבאים של PHP מושבתים כברירת מחדל. אפשר להפעיל את התוספים הבאים באמצעות הקובץ php.ini:

כדי להפעיל תוסף, מוסיפים קובץ php.ini לשורש של האפליקציה עם ההנחיה extension:

; Enable the Redis extension
extension=redis.so

; Enable the OpenTelemetry extension (must be in an opentelemetry section)
[opentelemetry]
extension=opentelemetry.so

אפשר גם להוסיף require ל-composer.json כדי להפעיל תוסף:

{
    "require": {
        "ext-redis": "*"
    }
}

החבילות האלה מאפשרות להתקין את רוב התוספים הפופולריים של PHP. אם האפליקציה שלכם דורשת תלות נוספת ברמת מערכת ההפעלה, אתם צריכים להרחיב את זמן הריצה של PHP או להשתמש בזמן ריצה בהתאמה אישית כדי להתקין את החבילות המתאימות.

פרוטוקול HTTPS ושרתי proxy להעברה

‫App Engine מפסיק את חיבור ה-HTTPS במאזן העומסים ומעביר את הבקשה לאפליקציה. שרת NGINX מוגדר להגדיר את משתנה הסביבה של HTTPS‏ ($_SERVER["HTTPS"]) ל-on כשהבקשה מתבצעת באמצעות HTTPS.

יש גם אפליקציות שצריכות לזהות את כתובת ה-IP של המשתמש. האפשרות הזו זמינה בכותרת הרגילה X-Forwarded-For.

פונקציות מושבתות

הפונקציות הבאות מושבתות באמצעות ההוראה disable_functions ב-php.ini:

  • exec
  • passthru
  • proc_open
  • proc_close
  • shell_exec
  • show_source
  • symlink
  • system

אם אתם צריכים להשתמש באחת מהפונקציות שלמעלה, אתם יכולים להוסיף קובץ php.ini לשורש של האפליקציה ולשנות את ההנחיה disable_functions. לחלופין, אתם יכולים להגדיר את whitelist_functions בקטע runtime_config ב-app.yaml לרשימה של פונקציות שמופרדות בפסיקים.

ב-PHP מגרסה 7.3 ומגרסאות קודמות, תוסף האבטחה suhosin מותקן ומוגדר כברירת מחדל להפעלה במצב סימולציה. במצב סימולציה, המערכת רושמת ביומן את השימוש בפונקציות שעלולות להיות מסוכנות, והרישום הזה יופיע בממשק המשתמש של Cloud Logging. השבתת מצב הסימולציה תגרום ליציאה מהאפליקציה כשנעשה שימוש בפונקציה שעלולה להיות מסוכנת. כדי להפעיל את תכונת האבטחה הנוספת הזו, מוסיפים php.ini בספריית הבסיס של הפרויקט עם האפשרות הבאה:

; Prevent the use of potentially dangerous functions rather than logging them
suhosin.simulation = Off

פונקציות שעברו תיקון

הפונקציה parse_str עודכנה והפרמטר השני הוא חובה. אם קוראים לפונקציה parse_str עם פרמטר אחד בלבד, תוצג אזהרה והפונקציה לא תופעל.

הגדרות זמינות

אפשר לכלול את ההגדרות הבאות בקטע runtime_config:

שםתיאורערך ברירת המחדל
document_root מציינים את DOCUMENT_ROOT עבור nginx ו-PHP. חובה להשתמש בנתיב יחסי מתיקיית הבסיס של הפרויקט. שדה חובה
composer_flags אפשר להשתמש במפתח הזה כדי לבטל חלק מההגדרות של כלי ההלחנה. --no-dev --prefer-dist
enable_stackdriver_integration האפשרות נתמכת רק בגרסה 7.3 ובגרסאות קודמות. אם המדיניות מוגדרת כ-True, סביבת זמן הריצה תפעיל אוטומטית את השילוב של Google Cloud Observability. כדי להשתמש בהגדרה הזו, צריך google/cloud package v0.33 ומעלה. FALSE
skip_lockdown_document_root האפשרות נתמכת רק בגרסה 7.3 ובגרסאות קודמות. כברירת מחדל, סביבת זמן הריצה תגדיר הרשאת קריאה בלבד לכל הקבצים והספריות בתיקייה document_root. אם ההגדרה היא true, זמן הריצה ידלג על שינוי ההרשאה. FALSE
whitelist_functions התמיכה היא רק בגרסה 7.3 ואילך. רשימה מופרדת בפסיקים של שמות פונקציות שרוצים להוסיף לרשימת ההיתרים. מחרוזת ריקה
front_controller_file שם קובץ ה-PHP שמוגדר כברירת מחדל לגישה לספרייה. index.php
nginx_conf_http_include שם הקובץ של הגדרת nginx חלקית, שתיכלל בקטע http בקובץ ההגדרות הראשי של nginx. nginx-http.conf
nginx_conf_include שם הקובץ של הגדרת nginx חלקית, שתיכלל בקטע server בקובץ ההגדרות הראשי של nginx. nginx-app.conf
nginx_conf_override שם הקובץ של קובץ ההגדרות של nginx שסופק על ידי המשתמש, שישמש כקובץ ההגדרות הראשי של nginx. nginx.conf
php_fpm_conf_override שם הקובץ של קובץ ההגדרות של php-fpm שסופק על ידי המשתמש, שייכלל בחלק התחתון של הקטע [app] כדי שיחליף את ההגדרות הקיימות. php-fpm.conf
php_ini_override שם הקובץ של קובץ הגדרות PHP שסופק על ידי המשתמש. php.ini
supervisord_conf_addition שם הקובץ של קובץ ההגדרות של supervisord שסופק על ידי המשתמש, שייכלל בקובץ ההגדרות הראשי של supervisord. additional-supervisord.conf
supervisord_conf_override שם הקובץ של קובץ התצורה של supervisord שסופק על ידי המשתמש, שיחליף את קובץ התצורה הראשי של supervisord. supervisord.conf

כדי לקבוע אם Nginx יציג קבצים סטטיים עבור כתובות URI תואמות, מגדירים את משתנה הסביבה NGINX_SERVES_STATIC_FILES בקטע build_env_variables בקובץ app.yaml:

runtime: php
env: flex

runtime_config:
  document_root: "web"
  operating_system: "ubuntu24"

build_env_variables:
  NGINX_SERVES_STATIC_FILES: true

הגדרת supervisord בסביבת זמן הריצה של PHP

הסביבה הגמישה של App Engine משתמשת ב-supervisord כדי לנהל תהליכים. כברירת מחדל, supervisord מפעיל את nginx ואת php-fpm כדי להפעיל אפליקציות אינטרנט של PHP. עם זאת, חלק מהאפליקציות צריכות להפעיל תהליכים חיצוניים. בנוסף, לפעמים אפליקציות כאלה לא צריכות nginx ולא php-fpm.

אם רוצים להוסיף תהליך שמנוהל על ידי supervisord, מוסיפים קובץ בשם additional-supervisord.conf לתיקיית השורש של הפרויקט. התוכן של קובץ התצורה לדוגמה במקרה הזה:

[program:quote-updater]
command = php %(ENV_APP_DIR)s/worker.php
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes=0
user = www-data
autostart = true
autorestart = true
priority = 5
stopwaitsecs = 20

אם רוצים להחליף את nginx ואת php-fpm בתהליך שלכם, מוסיפים קובץ בשם supervisord.conf לתיקיית השורש של הפרויקט. בהמשך מופיע תוכן לדוגמה של קובץ הגדרות למקרה הזה:

[supervisord]
nodaemon = true
logfile = /dev/null
logfile_maxbytes = 0
pidfile = /var/run/supervisord.pid

[program:react-server]
command = php %(ENV_APP_DIR)s/index.php
stdout_logfile = /dev/stdout
stdout_logfile_maxbytes=0
stderr_logfile = /dev/stderr
stderr_logfile_maxbytes=0
user = www-data
autostart = true
autorestart = true
priority = 5
stopwaitsecs = 20

הארכת זמן הריצה

אפשר להשתמש בסביבת זמן הריצה של PHP בסביבה הגמישה של App Engine כדי ליצור סביבת זמן ריצה בהתאמה אישית. מידע נוסף זמין במאמר בנושא התאמה אישית של סביבת הריצה של PHP.

משתני סביבה

משתני הסביבה הבאים מוגדרים על ידי סביבת זמן הריצה:

משתנה הסביבה תיאור
GAE_INSTANCE השם של המכונה הנוכחית.
GAE_MEMORY_MB נפח הזיכרון שזמין לתהליך האפליקציה.
GAE_SERVICE שם השירות שצוין בקובץ app.yaml של האפליקציה, או אם לא צוין שם שירות, הוא מוגדר כ-default.
GAE_VERSION תווית הגרסה של האפליקציה הנוכחית.
GOOGLE_CLOUD_PROJECT מזהה הפרויקט שמשויך לאפליקציה, שמופיע במסוף Google Cloud
PORT היציאה שתקבל בקשות HTTP.

אפשר להגדיר משתני סביבה נוספים באמצעות app.yaml.

שרת מטא-נתונים

כל מופע של האפליקציה יכול להשתמש בשרת המטא-נתונים של Compute Engine כדי לשלוח שאילתות לגבי מידע על המופע, כולל שם המארח, כתובת ה-IP החיצונית, מזהה המופע, מטא-נתונים מותאמים אישית ופרטי חשבון השירות. ב-App Engine אי אפשר להגדיר מטא-נתונים מותאמים אישית לכל מופע, אבל אפשר להגדיר מטא-נתונים מותאמים אישית ברמת הפרויקט ולקרוא אותם מהמופעים של App Engine ו-Compute Engine.

פונקציית הדוגמה הזו משתמשת בשרת המטא-נתונים כדי לקבל את כתובת ה-IP החיצונית של מכונה:

function get_external_ip_using_google_cloud()
{
    $metadata = new Google\Cloud\Core\Compute\Metadata();
    $externalIp = $metadata->get(
        'instance/network-interfaces/0/access-configs/0/external-ip');

    return $externalIp;
}

function get_external_ip_using_curl()
{
    $url = 'http://metadata.google.internal/computeMetadata/v1/' .
        'instance/network-interfaces/0/access-configs/0/external-ip';

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