PHP
Siehe auch
Installation
- CentOS 8
Aus dem Remi-Repo:
dnf -y module reset php # PHP 7.4 dnf -y module install php:remi-7.4 # PHP 8.0 dnf -y module install php:remi-8.0 # this is how to additional packages dnf -y install php-mbstring
Alternativ (und älter) aus dem EPEL-Repo:
dnf -y module reset php # PHP 7.3 dnf module enable php:7.3 # this is how to additional packages dnf -y install php-mbstring
- CentOS 7
Aus dem Remi-Repo:
# PHP 7.4 yum-config-manager --disable 'remi-php*' yum-config-manager --enable remi-php74 yum -y install php # this is how to additional packages yum -y install php-mbstring
Der integrierte Webserver
Start:
php -S localhost:8080 path/to/my/project.php
PHP-FPM
PHP-FPM (FastCGI Process Manager) ist eine alternative PHP FastCGI-Implementierung, die eine Reihe zusätzlicher Funktionen enthält.
Statusseite aktivieren:
listen = /run/php-fpm/www.sock
pm.status_path = /fpm-status
<LocationMatch "/fpm-status">
Require local
ProxyPass unix:/run/php-fpm/www.sock|fcgi://localhost/fpm-status
</LocationMatch>
curl 'http://localhost/fpm-status?json&full'
Ping-Seite aktivieren:
ping.path = /fpm-ping
<Location "/fpm-ping">
Require local
ProxyPass unix:/run/php-fpm/www.sock|fcgi://localhost/fpm-ping
</Location>
curl 'http://localhost/fpm-ping'
Test der Konfigurationsdatei:
php-fpm --test
PHP-FPM Process Hintergründe und Calculator:
Composer
Composer ist ein Paketmanager für PHP >= 5.3.2, wird über die Kommandozeile ausgeführt und installiert auch notwendige Abhängigkeiten.
Installation - aus dem remi-Repo (bevorzugt):
yum -y install composer
Installation - manuell von der Composer-Webseite:
wget --output-document=composer https://getcomposer.org/composer.phar
chmod +x composer
Update:
composer update
Paket installieren - direkt per composer
(bevorzugt):
composer require graylog2/gelf-php
Paket installieren - per manuellem Eintrag in der composer.json
:
{
"require": {
"graylog2/gelf-php": "^1.7"
}
}
Paket mit Abhängigkeiten entfernen:
composer remove graylog2/gelf-php --update-with-dependencies
Logging
So loggt man per GELF gegen einen Graylog:
<?php
$graylog_hostname = '10.74.143.6';
$graylog_port = '12201';
$graylog_facility = 'my-facility-name';
require_once __DIR__ . '/vendor/autoload.php';
// We need a transport - UDP via port 12201 is standard.
$transport = new Gelf\Transport\UdpTransport(
$graylog_hostname,
$graylog_port,
Gelf\Transport\UdpTransport::CHUNK_SIZE_LAN
);
$publisher = new Gelf\Publisher();
$publisher->addTransport($transport);
// The implementation of PSR-3 is encapsulated in the Logger-class.
// It provides high-level logging methods, such as alert(), info(), etc.
$logger = new Gelf\Logger($publisher, $graylog_facility);
// Now we can log...
$logger->emergency('My Emergency');
$logger->alert('My Alert');
$logger->critical('My Critical');
$logger->error('My Error');
$logger->warning('My Warning');
$logger->notice('My Notice');
$logger->info('My Info');
$logger->debug('My Debug');
Wie erhält man im Log neben dem Stacktrace auch die Parameter einer Funktion und deren Werte, wenn diese beim Aufruf mit einer Exception abbricht? Dafür gibt es keine php.ini-Einstellung - hier hilft nur die Definition eines eigenen Error-Handlers:
<?php
// user-defined error handler
function myErrorHandler($errno, $errstr, $errfile, $errline)
{
// print all the stacktrace details including function parameters and values
print_r(debug_backtrace());
return false;
}
// function that causes an error
function exampleFunction($param1, $param2)
{
$undefinedVar->callUndefinedFunction();
}
set_error_handler('myErrorHandler');
exampleFunction('linuxfabrik', 2016);
Keycloak (OAuth)
PHP-Applikationen können sich mit Hilfe des PHP League’s OAuth 2.0 Client per OAuth identifizieren. Hier finden sich die offiziellen Provider (Facebook & Co.), hier die Liste der Third-Party Provider.
Keycloak wird durch den Third-Party Provider stevenmaguire/oauth2-keycloak unterstützt, der sich per composer require stevenmaguire/oauth2-keycloak
installieren lässt.
Für die Auswertung in PHP-Applikationen: Apache setzt Umgebungsvariablen, die sich in $_SERVER
finden:
[OIDC_access_token] => eyJhbGciOiJ...Wpb8YpL8J4w
[OIDC_access_token_expires] => 1507893465
[OIDC_CLAIM_acr] => 0
[OIDC_CLAIM_aud] => example
[OIDC_CLAIM_auth_time] => 1507892808
[OIDC_CLAIM_azp] => example
[OIDC_CLAIM_email] => info@linuxfabrik.ch
[OIDC_CLAIM_exp] => 1507893465
[OIDC_CLAIM_family_name] =>
[OIDC_CLAIM_given_name] =>
[OIDC_CLAIM_iat] => 1507893165
[OIDC_CLAIM_iss] => http://192.168.122.235:8080/auth/realms/example
[OIDC_CLAIM_jti] => 1fff1dc8-...5056749451
[OIDC_CLAIM_nbf] => 0
[OIDC_CLAIM_nonce] => XbHe4AZO4Y3mLo1UF1OXfgHiRTuqQ
[OIDC_CLAIM_preferred_username] => ellen.lang
[OIDC_CLAIM_session_state] => cea4da5c-...c106cbb3fefb
[OIDC_CLAIM_sub] => b9c2a39a...b-c84e9382d5bc
[OIDC_CLAIM_typ] => ID
[REDIRECT_OIDC_access_token] => eyJhbGciOiJSUz...8YpL8J4w
[REDIRECT_OIDC_access_token_expires] => 1507893465
[REDIRECT_OIDC_CLAIM_acr] => 0
[REDIRECT_OIDC_CLAIM_aud] => example
[REDIRECT_OIDC_CLAIM_auth_time] => 1507892808
[REDIRECT_OIDC_CLAIM_azp] => example
[REDIRECT_OIDC_CLAIM_email] => info@linuxfabrik.ch
[REDIRECT_OIDC_CLAIM_exp] => 1507893465
[REDIRECT_OIDC_CLAIM_family_name] =>
[REDIRECT_OIDC_CLAIM_given_name] =>
[REDIRECT_OIDC_CLAIM_iat] => 1507893165
[REDIRECT_OIDC_CLAIM_iss] => http://192.168.122.199:8080/auth/realms/example
[REDIRECT_OIDC_CLAIM_jti] => 1fff1dc8-...5056749451
[REDIRECT_OIDC_CLAIM_nbf] => 0
[REDIRECT_OIDC_CLAIM_nonce] => XbHe4AZO4Y3mLo1UF1OXfgHiRTuqQ
[REDIRECT_OIDC_CLAIM_preferred_username] => ellen.lang
[REDIRECT_OIDC_CLAIM_session_state] => cea4da5c-...c106cbb3fefb
[REDIRECT_OIDC_CLAIM_sub] => b9c2a39a...b-c84e9382d5bc
[REDIRECT_OIDC_CLAIM_typ] => ID
[REDIRECT_STATUS] => 200
[REDIRECT_UNIQUE_ID] => WeCgFf0L41OaqnZmBvJ2MQAAAAY
[UNIQUE_ID] => WeCgFf0L41OaqnZmBvJ2MQAAAAY
Caching
Code-Caching mit dem integrirten Zend OPcache.
Abfrage der Statistiken mit php -r 'print_r(json_encode(opcache_get_status(), JSON_PRETTY_PRINT));'
. Wichtig: opcache.memory_consumption=200
legt die Gesamtgrösse fest. Wird beispielsweise opcache.interned_strings_buffer
auf 100 (MB) gesetzt, stehen nur noch 50% des OpCaches für die maximal opcache.max_accelerated_files
compilierten Dateien zur Verfügung.
So funktioniert der Cache anschaulich:
memory_consumption=200 (MB)
davon "wasted" max. 5%
┌─────────────────────────────────┐
│ │
│ interned_string_buffer=50 (MB) │
│ │
│ │
├─────────────────────────────────┤ ------
│ │
│ max_accelerated_files=16229 (#) │ Hit Rate
│ ("Keys") │
│ │
│ │
│ │
│ │
│ │
└─────────────────────────────────┘
Data Caches
APCu: für lokales Caching
Memcached: für verteiltes Caching
Redis: lokal, verteilt, File Lock Caching - aber langsamer als APCu
memory_limit vs. post_max_size vs. upload_max_filesize
Angenommen, man möchte Uploads für 2 GB grosse Dateien erlauben. Welche Settings in der php.ini sind wie anzupassen?
PHP verfügt über verschiedene POST-Readers und -Handler, je nach Inhaltstyp der Anfrage. Im Falle von „multipart/form-data“ (was für das Senden von Dateien verwendet wird), agiert der rfc1867_post_handler
als mixed Reader/Handler. Er füllt sowohl $_POST als auch $_FILES. Beides zählt in Bezug auf memory_limit
. Allerdings enthält $_FILES nur Metadaten über die Dateien, nicht die Dateien selbst. Dateien werden nur auf die Festplatte (auf unter Linux je nach Konfiguration z.B. in /tmp
) geschrieben und zählen daher nicht für memory_limit
.
Generell gilt also:
upload_max_filesize
kann beliebig gesetzt werden.post_max_size
muss grösser alsupload_max_filesize
sein, wenn Formulare mit Datei-Uploads unterstützt werden.memory_limit
muss grösser alspost_max_size
sein.
In obigem Beispiel kann also folgendes genügen:
memory_limit = 128M
post_max_size = 8M ; belongs to sapi_globals
upload_max_filesize = 1G ; belongs to core_globals
Debugging
Damit man unter PHP-FPM mit „print“-Statements debuggen kann, müssen folgende Einstellungen für den PHP-FPM-Worker gesetzt sein:
catch_workers_output = yes
php_admin_value[error_log] = /var/log/php-fpm/www-error.log
php_admin_flag[log_errors] = on
Nun kann so geprintet werden:
error_log("hello world");
error_log(print_r($myArray, true));
// print a stacktrace
error_log(print_r(debug_backtrace(), true));
// with reduced memory usage
error_log(print_r(debug_backtrace(DEBUG_BACKTRACE_IGNORE_ARGS), true));
Built on 2024-09-30