wiki/HowtoPHP.md

1052 lines
32 KiB
Markdown
Raw Permalink Normal View History

---
categories: web
title: Howto PHP
...
* Documentation : <http://php.net/manual/en/>
* Rôle Ansible : <https://forge.evolix.org/projects/ansible-roles/repository/show/php>
2024-02-07 10:33:44 +01:00
* Statut de cette page : prod / bullseye
2024-02-07 20:26:44 +01:00
[PHP](http://php.net/) est un langage de programmation populaire pour le développement web.
PHP peut s'utiliser en CLI (ligne de commande), via `mod_php` (module intégré à [Apache](HowtoApache)) ou via FPM (FastCGI Process Manager).
Voici les versions de PHP actuellement supportées sous Debian :
2017-09-08 03:46:31 +02:00
2023-06-18 23:17:09 +02:00
* Debian 7 : PHP 5.4
* Debian 8 : PHP 5.6
* Debian 9 : PHP 7.0
* Debian 10 : PHP 7.3
* Debian 11 : PHP 7.4
* Debian 12 : PHP 8.2
2024-02-07 20:26:44 +01:00
Chaque version bénéficie d'un [support par le projet PHP pendant 2 ans seulement](https://www.php.net/supported-versions.php)
Mais le projet Debian assure un support de sécurité pendant plus longtemps, notamment grâce aux projets LTS et ELTS.
On peut voir la durée du support sur notre [page de support des versions de Debian](https://docs.evolix.org/ServeurDedie/versionsOS).
Ainsi, grâce au support ELTS payé par Evolix, PHP 7.4 sous Debian 11 a un support jusqu'en 2028 environ ; et PHP 8.2 sous Debian 12 jusqu'en 2030 environ.
## Installation
Nous installons toujours PHP CLI, certaines dépendances classiques
ainsi que les outils [Composer](https://getcomposer.org/) et
[PHPMailer](https://github.com/PHPMailer/PHPMailer) :
~~~
# apt install php-cli php-curl php-mysql php-pgsql php-ldap php-imap php-gd php-ssh2 php-xml composer libphp-phpmailer
$ php -v
PHP 7.4.25 (cli) (built: Oct 23 2021 21:53:50) ( NTS )
Copyright (c) The PHP Group
Zend Engine v3.4.0, Copyright (c) Zend Technologies
with Zend OPcache v7.4.25, Copyright (c), by Zend Technologies
$ php --ini
Configuration File (php.ini) Path: /etc/php/7.4/cli
Loaded Configuration File: /etc/php/7.4/cli/php.ini
Scan for additional .ini files in: /etc/php/7.4/cli/conf.d
Additional .ini files parsed: /etc/php/7.4/cli/conf.d/10-mysqlnd.ini,
[...]
/etc/php/7.4/cli/conf.d/20-xsl.ini
$ composer -V
Composer 2.0.9 2021-01-27 16:09:27
~~~
> *Note* : Pour Debian 9/10, on installe aussi les paquets `php-mcrypt` et `php-gettext`
> *Note* : Pour Debian 8, on a PHP 5.6 qu'il faut installer ainsi (et il n'y a pas de package pour _composer_) :
>
> ~~~
2017-08-22 23:32:44 +02:00
> # apt install php5 php5-cli php5-curl php5-mysql php5-pgsql php5-mcrypt php5-ldap php5-imap php5-gd php5-ssh2 php-gettext libphp-phpmailer
> ~~~
### PHP avec deb.sury.org
2017-09-20 10:29:02 +02:00
Si l'on a vraiment besoin d'une version de PHP plus récente (par exemple PHP 8.0 ou 8.1),
il est possible de l'installer avec le dépôt [deb.sury.org](https://deb.sury.org/)
2018-11-29 13:04:43 +01:00
d'Ondřej Surý (l'un des mainteneurs officiels des paquets PHP sous Debian).
2017-09-20 10:29:02 +02:00
On peut d'ailleurs ainsi avoir plusieurs versions de PHP en même temps,
que l'on pourra utiliser pour différents sites web, via PHP-FPM par exemple.
2018-01-25 15:00:06 +01:00
2017-09-20 10:29:02 +02:00
~~~
2021-04-26 22:10:24 +02:00
# wget -O /etc/apt/trusted.gpg.d/sury.gpg https://packages.sury.org/php/apt.gpg
# dos2unix /etc/apt/trusted.gpg.d/sury.gpg
2021-04-26 22:10:24 +02:00
# chmod 644 /etc/apt/trusted.gpg.d/sury.gpg
# echo "deb https://packages.sury.org/php/ bullseye main" > /etc/apt/sources.list.d/sury.list
~~~
2018-01-25 15:01:36 +01:00
Attention, vous aurez automatiquement la version la plus récente installée,
car les paquets "php-foo" dépendent de la dernière version de PHP disponible.
2022-07-12 12:09:20 +02:00
Lors d'une mise-à-jour, vous pourrez avoir la surprise de voir
votre ligne de commande `php` passer de PHP 8.0 à 8.1 par exemple.
Pour éviter cela, et avoir strictement une seule version fixe de PHP, nous proposons
des paquets "php-foo" fixes. Ainsi, pour PHP 8.0, vous aurez dans vos sources :
~~~
deb http://pub.evolix.org/evolix bullseye-php80 main
deb https://packages.sury.org/php/ bullseye main
~~~
Et vous installerez PHP normalement (à part les paquets php-igbinary et php-redis que vous devrez forcer en version 8.0) :
~~~
# apt install php-cli php-curl php-mysql php-pgsql php-ldap php-imap php-gd php-xml composer libphp-phpmailer php-ssh2
~~~
2022-08-26 12:01:35 +02:00
Pour PHP 8.1, mettez dans vos sources :
~~~
deb http://pub.evolix.org/evolix bullseye-php81 main
2022-08-26 12:01:35 +02:00
deb https://packages.sury.org/php/ bullseye main
~~~
Puis installez PHP normalement :
2022-08-26 12:01:35 +02:00
~~~
# apt install php-cli php-curl php-mysql php-pgsql php-ldap php-imap php-gd php-xml composer libphp-phpmailer php-ssh2
2022-08-26 12:01:35 +02:00
~~~
2022-07-12 12:14:02 +02:00
**Nettoyage :**
2022-07-12 12:09:20 +02:00
Si des paquets Sury sont déjà installés (par exemple) en PHP 7.4, ils ne seront pas forcément mis à jour en 8.0, il faudra le faire à la main :
2022-07-12 12:09:20 +02:00
1. Lister les paquets non PHP 8.0 restants : `dpkg -l 'php*' | grep -P '^ii.*php\d\.\d' | grep -v php8.0`
2022-07-12 12:12:35 +02:00
2. Vérifier qu'ils sont bien présents comme `php-<module>` ou `php8.0-<module>` : `dpkg -l 'php*' | grep '^ii' | grep -E "php[(8.0)-]"`
2022-07-12 12:09:20 +02:00
3. S'ils manquent, les installer avec le paquet « générique » (`apt install php-<module>`). Si le paquet générique n'existe pas, les installer avec le paquet PHP 8.0 (`apt install php8.0-<module>`)
4. Purger les paquets des anciennes versions (exemple avec PHP 7.4, à adapter) : dpkg -l php7.4* | awk '/php7.4/ {print $2}' | xargs apt purge -y
Idem pour PHP 8.1 :
~~~
deb http://pub.evolix.org/evolix bullseye-php81 main
deb https://packages.sury.org/php/ bullseye main
~~~
~~~
# apt install php php-cli php-curl php-mysql php-pgsql php-ldap php-imap php-gd php-xml composer libphp-phpmailer php-ssh2
~~~
2022-07-12 12:14:02 +02:00
**Nettoyage :** voir si dessus comme pour PHP 8.0.
2022-07-12 12:09:20 +02:00
### PHP-FPM
PHP-FPM (FastCGI Process Manager) est une façon alternative d'utiliser
PHP avec [Apache](HowtoApache) ou [Nginx](HowtoNginx).
~~~
# apt install php php-fpm
# systemctl status php7.4-fpm
● php7.4-fpm.service - The PHP 7.4 FastCGI Process Manager
Loaded: loaded (/lib/systemd/system/php7.4-fpm.service; enabled; vendor preset: enabled)
Active: active (running) since Wed 2024-02-07 21:21:49 CET; 38s ago
Docs: man:php-fpm7.4(8)
Process: 241270 ExecStartPost=/usr/lib/php/php-fpm-socket-helper install /run/php/php-fpm.sock /etc/php/7.4/fpm/pool.d/www.conf 74 (code=exited, status=0/SUCCESS)
Main PID: 241267 (php-fpm7.4)
Status: "Processes active: 0, idle: 2, Requests: 0, slow: 0, Traffic: 0req/sec"
Tasks: 3 (limit: 18761)
Memory: 11.2M
CPU: 37ms
CGroup: /system.slice/php7.4-fpm.service
├─241267 php-fpm: master process (/etc/php/7.4/fpm/php-fpm.conf)
├─241268 php-fpm: pool www
└─241269 php-fpm: pool www
~~~
> *Note* : Pour Debian 8, il faut installer ainsi :
>
> ~~~
> # apt install php5-fpm
> ~~~
### mod_php
~~~
# apt install php libapache2-mod-php
~~~
> *Note* : Pour Debian 8, il faut installer ainsi :
>
> ~~~
> # apt install libapache2-mod-php5
> ~~~
## Configuration
2017-09-10 16:51:36 +02:00
<https://secure.php.net/manual/en/install.fpm.configuration.php>
Fichiers de configuration :
~~~
/etc/php/7.4/
├── apache2
│   ├── conf.d
│   │   ├── [...]
│   │   └── 20-xsl.ini -> /etc/php/7.4/mods-available/xsl.ini
│   └── php.ini
├── cli
│   ├── conf.d
│   │   ├── [...]
│   │   └── 20-xsl.ini -> /etc/php/7.4/mods-available/xsl.ini
│   └── php.ini
├── fpm
│   ├── conf.d
│   │   ├── [...]
│   │   └── 20-xsl.ini -> /etc/php/7.4/mods-available/xsl.ini
│   ├── php-fpm.conf
│   ├── php.ini
│   └── pool.d
│   └── www.conf
└── mods-available
├── [...]
└── xsl.ini
~~~
2023-06-27 21:45:42 +02:00
On peut valider une configuration ainsi :
~~~
# php-fpm7.4 -t
[07-Feb-2024 21:24:54] NOTICE: configuration file /etc/php/7.4/fpm/php-fpm.conf test is successful
~~~
### Configuration de base (php.ini)
Il existe un fichier `php.ini` distinct suivant lutilisation de
PHP : cli, mod_php et FPM.
Par exemple `/etc/php/7.4/fpm/php.ini` pour FPM.
Le fichier `/etc/php/7.4/fpm/conf.d/z-evolinux-defaults.ini` contient
nos optimisations basiques :
~~~
short_open_tag = Off
expose_php = Off
display_errors = Off
log_errors = On
html_errors = Off
allow_url_fopen = Off
memory_limit = 128M
max_execution_time = 10
open_basedir = /home
disable_functions = exec, shell-exec, system, passthru, putenv, popen
~~~
Le fichier `/etc/php/7.4/fpm/conf.d/zzz-evolinux-custom.ini` contient nos optimisations spécifiques.
2023-11-08 16:57:17 +01:00
### Configuration FPM
Voici les directives de base :
~~~
[global]
pid = /run/php/php7.4-fpm.pid
error_log = /var/log/php7.4-fpm.log
2023-06-27 21:45:42 +02:00
rlimit_files = 65536
~~~
On définit ensuite un ou plusieurs *pools* FPM via
`/etc/php/7.4/fpm/pool.d/*.conf` du type :
~~~
[www]
listen = /run/php/php7.4-fpm.sock
;listen = 127.0.0.1:9000
user = www-data
group = www-data
pm = dynamic
2023-06-27 21:45:42 +02:00
rlimit_files = 4096
php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f return-path@example.com
php_flag[display_errors] = off
php_admin_value[error_log] = /var/log/fpm-php.www.log
php_admin_flag[log_errors] = on
php_admin_value[memory_limit] = 32M
~~~
L'option **pm** (process manager) permet de choisir comment seront
contrôlés les process fils : static, ondemand ou dynamic.
Le mode standard est **dynamic** : FPM va préparer des process en
attente (au minimum 1) et les faire varier en fonction de la demande
(de façon similaire à ce que peut faire
[Apache](HowtoApache#configuration-de-base)).
~~~
pm = dynamic
pm.max_children = 100
pm.start_servers = 25
pm.min_spare_servers = 20
pm.max_spare_servers = 30
pm.max_requests = 100
~~~
Avec de nombreux pools, on optera pour le mode **ondemand** qui ne
prépare pas de process mais les crée à chaque demande. D'après nos
tests, les performances restent étonnamment tout à fait
acceptables.
~~~
pm = ondemand
pm.max_children = 100
pm.process_idle_timeout = 10s
~~~
D'autres options de FPM sont intéressantes :
~~~
2019-11-05 23:30:51 +01:00
slowlog = /var/log/php-fpm_$pool.log.slow
request_slowlog_timeout = 5s
2017-08-22 23:32:44 +02:00
pm.status_path = /fpm_status
request_terminate_timeout = 60s
chroot = /home/foo
access.log = log/$pool.access.log
~~~
2019-11-05 23:46:59 +01:00
Pour slowlog, lire <https://serverpilot.io/docs/how-to-read-the-php-slow-request-log>
#### Configuration FPM avec Nginx
2017-09-10 16:38:04 +02:00
On configure FPM avec Nginx, par exemple dans un Virtualhost :
~~~
server {
listen 80;
server_name www.example.com example.com;
root /home/foo/www;
index index.php;
location ~ \.php$ {
try_files $uri =404;
#fastcgi_pass 127.0.0.1:9000;
2017-09-10 16:38:04 +02:00
fastcgi_pass unix:/var/run/php/php7.0-fpm.sock;
fastcgi_param SCRIPT_FILENAME /home/foo/www$fastcgi_script_name;
include fastcgi_params;
}
}
~~~
L'utilisateur `www-data` doit accéder en lecture aux fichiers, il sera donc ajouté au groupe auquel ils appartiennent.
Ainsi pour un cloisonnement avec `/home/foo` appartenent à l'utilisateur `foo` et le groupe `foo`, on fera :
~~~
# adduser www-data foo
~~~
#### Configuration FPM avec Apache
Cela nécessite le module proxy_fcgi :
~~~
# a2enmod proxy_fcgi
Considering dependency proxy for proxy_fcgi:
Enabling module proxy.
Enabling module proxy_fcgi.
~~~
2017-09-10 16:38:04 +02:00
On configure FPM avec Apache, par exemple dans un VirtualHost :
~~~{.apache}
DocumentRoot /home/bench/www/
#ProxyPassMatch "^/(.*\.php(/.*)?)$" "fcgi://127.0.0.1:9000//home/foo/www/$1"
ProxyPassMatch "^/(.*\.php(/.*)?)$" "unix:/var/run/php/php7.4-fpm.sock|fcgi://localhost/home/foo/www/"
~~~
2017-08-22 18:38:14 +02:00
2017-09-08 03:46:31 +02:00
### Configuration mod_php
Avec mod_php on peut forcer la plupart des options du php.ini dans
la configuration Apache.
2017-09-08 03:46:31 +02:00
Par exemple, au sein d'un VirtualHost on peut mettre les paramètres
suivants :
2017-09-08 03:46:31 +02:00
~~~
<VirtualHost *:80>
#php_admin_flag engine off
#AddType text/html .html
#php_admin_flag display_errors On
#php_flag short_open_tag On
#php_flag register_globals On
#php_admin_value memory_limit 256M
#php_admin_value max_execution_time 60
#php_admin_value upload_max_filesize 8M
#php_admin_flag allow_url_fopen Off
php_admin_value sendmail_path "/usr/sbin/sendmail -t -i -f www-XXX"
php_admin_value open_basedir "/usr/share/php:HOME_DIR/XXX:/tmp"
~~~
## Sessions PHP
<http://php.net/manual/en/book.session.php>
Lorsque des sessions PHP sont utilisées (fonctions session_XXX()
dans le code), des informations sont stockées côté serveur. Le
navigateur conserve uniquement l'identifiant pour accéder à ces
informations, stockés dans un cookie ou une variable du type PHPSESSID
dans l'URL (cela tend à être obsolète).
Par défaut, ces informations sont conservées dans des fichiers sur
le disque (un fichier par session) mais il est conseillé d'utiliser
une méthode plus performante si vous avez un serveur dédié. Évidemment
il est fortement déconseillé de stocker les sessions dans une base
de données SQL…
2017-09-08 03:46:31 +02:00
2017-09-10 16:38:04 +02:00
* La méthode la plus simple si votre site web est en mono-serveur ou en mode sticky est de monter le répertoire qui stocker les fichiers en *TMPFS*. Cela se fait par exemple en ajoutant la ligne suivante dans votre _fstab_ :
2017-09-08 03:46:31 +02:00
~~~
2017-09-10 16:38:04 +02:00
tmpfs /var/lib/php/sessions tmpfs defaults,noexec,nosuid,nodev,size=256m 0 0
2017-09-08 03:46:31 +02:00
~~~
2017-09-10 16:38:04 +02:00
> *Note* : Pour Debian 8 :
>
> ~~~
> tmpfs /var/lib/php5 tmpfs defaults,noexec,nosuid,nodev,size=256m 0 0
> ~~~
2017-09-08 03:46:31 +02:00
* Les sessions peuvent être stockées dans un ou plusieurs serveurs *Memcached* avec les paramètres suivants :
~~~
session.save_handler = memcached
2017-09-10 16:53:31 +02:00
session.save_path = "192.0.2.10:11211,192.0.2.11:11211"
2017-09-08 03:46:31 +02:00
~~~
Par contre, contrairement aux idées reçues, ce n'est pas conseillé.
Memcached est fait pour « cacher » et non « stocker ». Voir le
blog d'un développeur de Memcached à ce sujet :
<http://dormando.livejournal.com/495593.html>
2017-09-08 03:46:31 +02:00
* Les sessions peuvent être stockées dans un ou plusieurs serveurs *Redis* avec les paramètres suivants :
~~~
session.save_handler = redis
2017-09-10 16:53:31 +02:00
session.save_path = "tcp://192.0.2.10:6379?auth=PASSWORD,tcp://192.0.2.11:6379?auth=PASSWORD"
2017-09-08 03:46:31 +02:00
~~~
* Les sessions peuvent être stockées dans [Sharedance](http://www.pureftpd.org/project/sharedance), un petit logiciel spécialement conçu pour stocker les sessions PHP. Il n'est plus maintenu, mais très simple, il est toujours fonctionnel. Voici un exemple d'utilisation :
2017-09-08 03:46:31 +02:00
~~~
auto_prepend_file = /usr/local/etc/sharedance.php
;session.save_handler = user
;session.save_handler = files
~~~
* Les sessions peuvent être stockées dans *Tokyo Tyrant/Tycoon* avec les paramètres suivants :
~~~
tokyo_tyrant.session_salt="randomlongstring"
session.save_handler=tokyo_tyrant
2017-09-10 16:53:31 +02:00
session.save_path="tcp://192.0.2.10:1978,tcp://192.0.2.10:1978"
2017-09-08 03:46:31 +02:00
~~~
2017-08-22 23:32:44 +02:00
2017-08-22 18:38:14 +02:00
## Composer
* Documentation : <https://getcomposer.org/doc/>
[Composer](https://getcomposer.org/) est un outil moderne de gestion
des bibliothèques PHP, qui tend à remplacer le vieil outil
[PEAR](https://pear.php.net/). Il est disponible à partir de Debian
9.
2017-08-22 18:38:14 +02:00
Composer s'utilise sans les droits _root_. Il s'appuie sur la
présence d'un fichier `composer.json` qui déclare les bibliothèques
à installer.
2017-08-22 18:38:14 +02:00
~~~
$ composer about
2017-09-10 18:32:14 +02:00
Composer Package Management for PHP
2017-08-22 18:38:14 +02:00
Composer is a dependency manager tracking local dependencies of your projects and libraries.
See https://getcomposer.org/ for more information.
2017-09-06 15:43:19 +02:00
$ echo '{"require": {"twig/extensions": "~1.0"}}' > composer.json
2017-08-22 18:38:14 +02:00
$ composer update
Loading composer repositories with package information
Updating dependencies (including require-dev)
- Installing symfony/polyfill-mbstring (v1.5.0)
Loading from cache
- Installing twig/twig (v2.4.3)
Loading from cache
- Installing twig/extensions (v1.5.1)
Loading from cache
twig/extensions suggests installing symfony/translation (Allow the time_diff output to be translated)
Writing lock file
Generating autoload files
$ composer show
symfony/polyfill-mbstring v1.5.0 Symfony polyfill for the Mbstring extension
twig/extensions v1.5.1 Common additional features for Twig that do not directly belong in core
twig/twig v2.4.3 Twig, the flexible, fast, and secure template language for PHP
~~~
2023-03-31 11:44:40 +02:00
### Installer la dernière version de Composer
Documentation officicelle :
* [Installation](https://getcomposer.org/doc/00-intro.md)
* [Installer programmatiquement](https://getcomposer.org/doc/faqs/how-to-install-composer-programmatically.md)
Si on veut une version de Composer plus récente que celle fournie par la distribution Debian, on peut l'installer à partir du site de composer.
On peut installer Composer localement pour un utilisateur, ou globalement sur le sytème.
Evolix recommande des installations locales spécifiques pour chaque utilisateur.
Nous déconseillons une installation globale pour plusieurs raions de sécurité : exécution en tant que root, exécutable global sans les mises-à-jour de sécurité…
2023-03-31 11:44:40 +02:00
Télécharger Composer :
2017-08-22 18:38:14 +02:00
~~~
# su - <USER>
2017-10-05 18:16:00 +02:00
$ wget -q -O setup-composer.php https://getcomposer.org/installer
2023-03-31 11:44:40 +02:00
~~~
Vérifier la somme de contrôle :
~~~
2017-10-05 18:16:00 +02:00
$ sha384sum setup-composer.php
2023-03-31 11:44:40 +02:00
$ curl https://composer.github.io/installer.sig; echo
~~~
Installer Composer pour l'utilisateur :
2023-03-31 11:44:40 +02:00
~~~
2017-08-22 18:38:14 +02:00
$ mkdir bin
$ php setup-composer.php --install-dir=./bin --filename=composer
$ rm setup-composer.php
2023-03-31 11:44:40 +02:00
$ bin/composer --version
~~~
Exceptionnellement, s'il est nécessaire d'installer Composer globalement :
2023-03-31 11:44:40 +02:00
~~~
# php setup-composer.php --install-dir=/usr/local/bin --filename=composer
# rm setup-composer.php
# composer --version
2017-08-22 18:38:14 +02:00
~~~
2017-08-22 23:32:44 +02:00
2017-09-08 03:49:28 +02:00
## Module du framework phalcon
<https://docs.phalconphp.com/fr/latest/reference/install.html>
<https://github.com/phalcon/phalcon-devtools>
2021-09-03 15:24:16 +02:00
### Installation à partir des dépot
``` shell
# echo "deb https://packagecloud.io/phalcon/stable/debian/ $(awk -F= '/VERSION_CODENAME/{print$2}' /etc/os-release) main" \
> /etc/apt/sources.list.d/php-phalcon.list
# curl -Lo /etc/apt/trusted.gpg.d/php-phalcon.asc https://packagecloud.io/phalcon/stable/gpgkey
# chmod 644 /etc/apt/trusted.gpg.d/php-phalcon.asc
# apt update
# apt install php7.4-psr php7.4-phalcon
2021-09-03 15:24:16 +02:00
# php -m | grep phalcon
phalcon
```
### Instllation à partir de git (obsolète)
2017-09-08 03:49:28 +02:00
Installer les dépendances suivantes :
~~~
2023-06-27 21:45:42 +02:00
# apt install php7.3-dev libpcre3-dev gcc make php7.3-mysql
2017-09-08 03:49:28 +02:00
~~~
2017-09-10 16:38:04 +02:00
> *Note* : Pour Debian 8 :
>
> ~~~
> # apt install php5-dev libpcre3-dev gcc make php5-mysql
> ~~~
Cloner la dernière version stable :
2017-09-08 03:49:28 +02:00
~~~
2021-09-03 14:35:05 +02:00
$ git clone --depth=1 https://github.com/phalcon/cphalcon.git
2017-09-08 03:49:28 +02:00
~~~
Compiler et installer le module :
~~~
$ cd cphalcon/build
# ./install
~~~
Configurer PHP et Apache :
2017-09-10 16:38:04 +02:00
Ajouter un fichier `phalcon.ini` :
2017-09-08 03:49:28 +02:00
~~~
extension=phalcon.so
~~~
Puis activer la configuration :
~~~
2017-09-10 16:38:04 +02:00
# ln -s mods-available/phalcon.ini cli/conf.d/30-phalcon.ini
# ln -s mods-available/phalcon.ini apache2/conf.d/30-phalcon.ini
2017-09-08 03:49:28 +02:00
# systemctl reload apache2
~~~
Pour installer les phalcon devtools :
~~~
2017-09-10 16:38:04 +02:00
$ git clone https://github.com/phalcon/phalcon-devtools.git
# cp phalcon-devtools/phalcon.php /usr/local/bin/phalcon
# chmod 755 /usr/local/bin/phalcon
2017-09-08 03:49:28 +02:00
~~~
2017-09-10 16:38:04 +02:00
## Debug
### strace
Au niveau système, on peut utilise `strace` pour voir exactement
ce qui est fait (ouvertures de fichiers, connexions distantes,
requêtes MySQL).
2017-09-10 16:38:04 +02:00
Exemple d'utilisations :
~~~
# Affiche les fichiers ouverts.
$ strace -ff -e trace=open php index.php
# Affiche les appels réseaux.
$ strace -ff -e trace=network php index.php
# Compte les appels systèmes et le temps passé.
$ strace -c php index.php
# Calcul du temps d'exécution d'un appel.
$ strace -T php index.php
# Affichage d'un timestamp devant chaque appel.
$ strace -ttt php index.php
# Strace verbeux.
$ strace -s 65535 -ff php index.php
~~~
Dans certains cas, des CMS gèrent mal le fait qu'on exécute le code
via PHP-CLI. On pourra utiliser PHP-CGI pour le tromper, c'est
notamment le cas de Magento.
~~~
$ HTTP_HOST="www.monsite.com" strace php-cgi index.php
~~~
2017-09-10 16:57:53 +02:00
Par exemple, on peut récupérer les requêtes MySQL ainsi.
~~~
$ strace -s65535 -e trace=write -ff -o strace php-cgi index.php
$ grep SELECT strace.*
~~~
### xdebug
<https://xdebug.org/docs/>
[Xdebug](https://xdebug.org/) est un débogueur PHP.
~~~
2017-09-10 16:38:04 +02:00
# aptitude install php-xdebug
~~~
2017-09-10 16:38:04 +02:00
> *Note* : Pour Debian 8 :
>
> ~~~
> # aptitude install php5-xdebug
> ~~~
On aura ainsi un fichier `xdebug.ini` que l'on pourra compléter
ainsi :
~~~
zend_extension=/usr/lib/php5/20090626/xdebug.so
;xdebug.auto_trace=On
;xdebug.profiler_enable=1
xdebug.profiler_output_dir=/home/xdebug
xdebug.trace_output_dir=/home/xdebug
~~~
Pour activer dans un vhost Apache :
~~~
php_admin_value xdebug.profiler_enable 1
~~~
Attention, bien mettre les bons droits sur le répertoire _/home/xdebug_.
Notez qu'il peut se remplir très vite une fois activé !
2017-09-10 16:38:04 +02:00
On obtient des fichiers `trace.XXX.xt` et `cachegrind.out.XXXX`
Les fichiers `trace.XXX.xt` sont des traces de tous les appels aux
fonctions PHP du code préfixé par le temps d'exécution. Idéal pour
trouver une fonction anormalement longue. La seconde colonne contient
l'empreinte mémoire, idéal aussi pour repérer une fonction qui
utilise trop de mémoire.
Les fichiers `cachegrind.out.XXXX` peuvent être lus avec l'outil
_kcachegrind_ (pour Linux) ou _wincachegrind_ (sous Windows), cela
permet de schématiser les appels aux fonctions PHP et de voir le
temps passé en % et le nombre d'appels.
2017-11-23 14:38:00 +01:00
2017-11-23 14:37:17 +01:00
Voici un exemple :
![Ici, 30% du temps est passé dans php::uasort, appelé par Mage_Core_Model_Layout->getOutput.](/call141f0.png)
Webgrind en PHP permet de faire comme kcachegrind mais via un
navigateur :
~~~
2017-09-10 16:38:04 +02:00
$ git clone https://github.com/jokkedk/webgrind.git
~~~
2017-09-10 16:38:04 +02:00
Il faut mettre _profilerDir_ à _/home/xdebug_ dans `config.php`
Pour profiter du graphique « call graph » il faut installer le
package _graphviz_ et mettre dotExecutable à /usr/bin/dot.
### coredump
<https://bugs.php.net/bugs-generating-backtrace.php>
Installation :
~~~
2017-09-10 16:38:04 +02:00
# echo 'deb http://deb.debian.org/debian-debug/ stretch-debug main' > /etc/apt/sources.list.d/debug.list
# apt update
# apt install php7.0-common-dbgsym php7.0-cli-dbgsym
~~~
2017-09-10 16:38:04 +02:00
> *Note* : Pour Debian 8 :
>
2017-09-10 16:59:42 +02:00
> ~~~
2017-09-10 16:38:04 +02:00
> # aptitude install gdb php5-dbg
> ~~~
Pour activer :
~~~
2017-09-10 16:38:04 +02:00
# echo 1 > /proc/sys/kernel/core_uses_pid
# mkdir /home/coredump
# chmod 1777 /home/coredump
# echo '/home/coredump/core-%e-%p' > /proc/sys/kernel/core_pattern
# echo "* soft core unlimited" >> /etc/security/limits.conf
# ulimit -c unlimited
# echo "ulimit -c unlimited" >> /etc/default/apache2
# /etc/init.d/apache2 restart
~~~
Pour désactiver :
~~~
# echo '' > /proc/sys/kernel/core_pattern
~~~
2017-09-10 16:38:04 +02:00
Pour lire les traces de FPM :
~~~
$ gdb /usr/sbin/php-fpm core-php5-fpm.7409
(gdb) bt
(gdb) bt -100
~~~
2017-09-10 16:38:04 +02:00
Message typique, des erreurs de mémoire (souvent des boucles) :
~~~
#0 xbuf_format_converter (xbuf=0x77a812cee810, fmt=0xa6d5a1 "%ld", ap=Cannot access memory at address 0x77a812cedf10)
#0 0x00007ffd348abe53 in _zend_mm_free_canary_int (heap=0x7ffd39b11130, p=0x21143c453bb97f0f) at /build/buildd/php5-5.3.2/Zend/zend_alloc_canary.c:2090
2090 /build/buildd/php5-5.3.2/Zend/zend_alloc_canary.c: No such file or directory.
in /build/buildd/php5-5.3.2/Zend/zend_alloc_canary.c
#0 0x00000000007e10b1 in zend_mm_free_cache ()
~~~
Astuce : utiliser xdebug pour en savoir plus sur la boucle (xdebug
étant limité à 100 récursions, il affichera les infos via une PHP
Fatal Error :
~~~
Fatal error: Maximum function nesting level of '100' reached, aborting! in [...]
~~~
2017-09-13 18:44:55 +02:00
## Performance
### mod_php VS Apache/FPM VS Nginx/FPM
Fin 2016, voici nos résultats d'un test sur un serveur physique «
standard » avec une [application Symfony de
test](https://github.com/acseo/symfony-perf).
Nous avons utilisé `ab -n 1000 -c 100` (1000 requêtes dont 100 en
parallèle) avec nos configurations système par défaut :
2017-09-13 18:44:55 +02:00
~~~
* Apache prefork FPM :
Symfony hello ~105ms
Symfony form ~168ms
* Apache prefork mod_php :
Symfony hello ~106ms
Symfony form ~170ms
* Nginx FPM :
Symfony hello ~102ms
Symfony form ~164ms
~~~
2018-02-13 14:58:59 +01:00
### OpCache
OpCache est un module PHP qui réduit le temps d'exécution du code PHP. Il pré-compile le code PHP en byte-code et le stocke en cache.
Il remplace les « accélérateurs » comme APC, eAccelerator, etc. utilisés dans les versions précédentes de PHP.
2022-07-08 11:45:42 +02:00
~~~
# apt install phpX.X-opcache
~~~
2023-04-12 16:14:59 +02:00
La configuration se fait dans /etc/php/X.X/apache2/php.ini, `/etc/php/X.X/mods-available/opcache.ini`, mais on préfère mettre la configuration personnalisée dans `/etc/php/X.X/apache2/conf.d/*`.
Principaux paramètres :
* `opcache.memory_consumption` : Taille du cache, valeur par défaut : `128M`.
* `opcache.max_accelerated_files` : Nombre maximum de scripts cachés, valeur par défaut : `10000`. Attention [la valeur utilisée par OpCache](https://www.php.net/manual/fr/opcache.configuration.php#ini.opcache.max-accelerated-files) n'est pas exactement celle spécifiée).
2018-02-13 14:58:59 +01:00
2022-07-08 11:45:42 +02:00
Pour surveiller OpCache, on peut utiliser :
2018-02-13 14:58:59 +01:00
* <https://github.com/amnuts/opcache-gui>
2022-07-08 11:45:42 +02:00
* Plugins Munin : <https://github.com/munin-monitoring/contrib/blob/master/plugins/php/php_opcache> + <https://github.com/munin-monitoring/contrib/blob/master/plugins/php/php_opcache.php>
2023-04-12 16:14:59 +02:00
2022-07-08 11:45:42 +02:00
#### Reset du cache d'OpCache
2022-07-08 11:45:42 +02:00
OpCache ne détecte pas les changements dans le code PHP lorsque les déploiements sont fait avec des liens symboliques. Il existe une solution « automatique » seulement pour Nginx :
Dans le vhost, dans le bloc indiquant le chemin du socket PHP, ajouter après la dernière directive :
~~~
fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;
fastcgi_param DOCUMENT_ROOT $realpath_root;
~~~
2022-07-08 11:45:42 +02:00
**Attention :** Ces paramètres doivent être ajoutés après les inclusions (par exemple `include snippets/fastcgi-php.conf;`), car sinon les paramètres contenus dans la configuration inclue risqueraient d'écraser ceux que l'on vient d'ajouter.
Les autres possibilités, notamment dans le cas Apache, sont de reset le cache à la main.
On peut :
* Appeler la fonction PHP opcache_reset() (solution applicative)
2023-03-29 12:07:08 +02:00
* Note : dans le workflow de déploiement, cette fonction doit être appelée par le serveur web, et non par PHP en CLI.
* Recharger le service PHP-FPM (solution radicale).
2022-07-08 11:45:42 +02:00
* Utiliser CacheTool (solution CLI) :
~~~
php bin/cachetool.phar --fcgi=php-fpm73.sock opcache:reset --cli
~~~
2018-02-13 14:58:59 +01:00
2022-07-08 11:45:42 +02:00
**Attention :** Si l'on oublie l'option `--cli`, on rencontrera l'erreur suivante : `Error: Access denied`.
2022-01-12 17:31:39 +01:00
2017-09-13 18:44:55 +02:00
## HHVM
<https://github.com/facebook/hhvm/wiki/Prebuilt-Packages-on-Debian-8>
<https://github.com/facebook/hhvm/wiki/FastCGI>
~~~
# cd /etc/apt/trusted.gpg.d
# wget 'https://keyserver.ubuntu.com/pks/lookup?op=get&search=0x36aef64d0207e7eee352d4875a16e7281be7a449' -O hhvm.asc
# chmod 644 hhvm.asc
2017-09-10 16:38:04 +02:00
# echo deb http://dl.hhvm.com/debian jessie main > /etc/apt/sources.list.d/hhvm.list
# apt update
# install hhvm
~~~
Configuration via le fichier `/etc/hhvm/server.ini`, on pourra
passer en mode socket plutôt que sur un port TCP :
~~~
;hhvm.server.port = 9000
hhvm.server.file_socket=/var/run/hhvm/sock
~~~
Mise en place avec Nginx :
~~~
# /usr/share/hhvm/install_fastcgi.sh
# /etc/init.d/nginx restart
~~~
2017-09-10 16:38:04 +02:00
Cela crée le fichier `/etc/nginx/hhvm.conf` :
~~~
location ~ \.(hh|php)$ {
fastcgi_keep_conn on;
#fastcgi_pass 127.0.0.1:9000;
fastcgi_pass unix:/var/run/hhvm/sock
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
include fastcgi_params;
}
~~~
HHVM écoute par défaut sur le port 9000 (attention si vous avez une
configuration FPM qui écoute aussi sur ce port-là). Il faudra
inclure ce fichier de configuration dans votre vhost qui a besoin
de HHVM.
~~~
include /etc/nginx/hhvm.conf;
~~~
2017-09-08 03:49:28 +02:00
2017-09-08 03:46:31 +02:00
## FAQ
### Utiliser locale fr_FR.utf-8
PHP utilise les locales situés dans le dossier /usr/lib/locale/fr_FR/. Si le dossier est vide alors on peut le completer avec le paquet `locales-all`.
### J'ai un message d'erreur du type : _/usr/lib/php5/20090626/xcache.so doesn't appear to be a valid Zend extension_
2017-09-08 03:46:31 +02:00
Remplacer `zend_extension=` par `extension=` pour le chargement du
module PHP.
2017-09-08 03:46:31 +02:00
### Certaines fonctions GD n'existent pas : imagerotate(), imageantialias(), etc.
2017-09-08 03:46:31 +02:00
Pour des raisons de sécurité et de maintenabilité, la version de
PHP de Debian n'embarque par le GD modifié par PHP. Ces fonctions
ne sont pas disponibles. Pour contourner ce problème, nous conseillons
d'écrire vos propres fonctions (il y a des exemples sur
<https://secure.php.net/>). Cela peut éventuellement être mis dans
un fichier partagé qui sera ensuite inclus systématiquement dans
votre code lorsque l'utilisation est nécessaire.
### Site avec accents en ISO-8859 cassés
Si vous avez des fichiers PHP en ISO-8859, on peut forcer son
utilisation via `default_charset ISO-8859-15`. À noter que pour les
fichiers HTML ou TXT, on peut utiliser l'option Apache `AddDefaultCharset
ISO-8859-15`.
### Mes fonctions mysql_connect, mysql_pconnect, etc. ne fonctionnent plus en PHP 7
Il est conseillé d'utiliser PDO_MySQL, mais une méthode rapide est
d'utiliser l'extension mysqli : <http://php.net/manual/fr/book.mysqli.php>
La plupart des fonctions sont identiques avec mysqli... il suffit
de remplacer `mysql_` par `mysqli_` !
Quelques exceptions :
* mysql_pconnect() doit être remplacé par mysqli_connect()
* mysqli_error() doit avoir un argument : le résultat de mysqli_connect()
* mysqli_select_db(), mysqli_query() doivent avoir le résultat de mysqli_connect() en 1er argument et non plus en second
### Erreurs avec le module php5-mysql
2018-03-26 21:19:42 +02:00
Si vous avez des erreurs avec le module php5-mysql de Debian 7 (PHP
5.4) du type _ ERROR 1148 : The used command is not allowed with
this MySQL version_ une solution peut être d'utiliser le module
alternatif php5-mysqlnd
2018-04-25 15:24:14 +02:00
### Connaître les codes d'Error Reporting php :
2018-04-25 15:24:14 +02:00
Pour calculer le nombre d'error reporting php dans la configuration
php, dans un vhost ou un .htacccess ce lien les répertories :
2018-04-25 15:24:14 +02:00
<https://maximivanov.github.io/php-error-reporting-calculator/>
### Désactiver l'envoi de mail()
2018-06-06 14:36:18 +02:00
Si l'on veut empêcher l'envoi d'email avec la fonction `mail()` (en cas d'abus par exemple),
on peut configurer la variable *sendmail_path* ainsi :
2018-06-06 14:36:18 +02:00
~~~
sendmail_path "/bin/true"
2018-06-06 14:36:18 +02:00
~~~
Si l'on utilise mod_php, on pourra ainsi le faire via le VirtualHost :
2018-06-11 15:33:23 +02:00
~~~
php_admin_value sendmail_path "/bin/true"
~~~
### `allow_url_fopen = Off` empêche dutiliser file_get_contents
La solution est dutiliser
2018-11-26 19:04:25 +01:00
[fsockopen()](https://secure.php.net/manual/fr/function.fsockopen.php)
plutôt que
2018-11-26 19:04:25 +01:00
[file_get_contents()](https://secure.php.net/manual/fr/function.file-get-contents.php).
Il faut faire attention parce que cette API est aussi vulnérable a
2018-11-26 19:04:25 +01:00
[certaines attaques](https://www.owasp.org/index.php/PHP_Top_5).
2018-11-26 19:04:25 +01:00
Exemple pour [Google Recaptcha](http://www.google.com/recaptcha/intro/v3.html):
2023-06-27 21:45:42 +02:00
Remplacer :
2023-06-27 21:45:42 +02:00
~~~
$recaptcha = new \ReCaptcha\ReCaptcha($secret);
2023-06-27 21:45:42 +02:00
~~~
2023-06-27 21:45:42 +02:00
Par :
2023-06-27 21:45:42 +02:00
~~~
$recaptcha = new \ReCaptcha\ReCaptcha($secret, new \ReCaptcha\RequestMethod\SocketPost());
2023-06-27 21:45:42 +02:00
~~~
2021-11-12 12:08:31 +01:00
### Répertoire temporaire pour ImageMagick
Par défaut ImageMagick met ses données temporaires dans `/tmp`. Dans le cas où le volume monté sur `/tmp` est trop petit, on peut modifier le répertoire temporaire dans le fichier `/etc/ImageMagick-6/policy.xml`:
2023-06-27 21:45:42 +02:00
~~~{.xml}
<policymap>
<policy domain="resource" name="temporary-path" value="/home/imagicktmp"/>
</policymap>
2023-06-27 21:45:42 +02:00
~~~
2021-11-12 12:08:31 +01:00
### Erreur opendir /var/lib/php/sessions failed Permission denied
Contrairement à ce qui est affirmé sur certains forums, il ne faut pas changer les permissions sur ce dossier, au risque de s'exposer à des usurpations de sessions.
Sur Debian, les sessions sont nettoyées automatiquement par le service systemd `phpsessionclean` déclenché par un timer. C'est pour cette raison que la variable PHP session.gc_probability est mise à 0 dans la configuration par défaut de Debian.
Certaines applications comme Symfony outrepassent cette configuration et tentent d'effectuer elles-mêmes le nettoyage de sesssion. Il faut le désactiver explicitement au niveau de l'application.
Le service systemd `phpsessionclean` est parfois en erreur dans les conteneurs LXC Debian 10 et 11 à cause de AppArmor. Pour résoudre le problème, il faut ajouter `lxc.apparmor.profile = unconfined` à la configuration du conteneur et le redémarrer. On peut ensuite vérifier le bon fonctionnement du service `phpsessionclean`.
2023-06-27 21:45:42 +02:00
### Erreur Too many open files
Si vous obtenez des erreurs du type :
~~~
failed to open stream: Too many open files
failed to open dir: Too many open files
PHP Fatal error: date_default_timezone_get(): Timezone database is corrupt - this should *never* happen!
~~~
Vous devez augmenter le nombre maximum de fichiers ouverts par process.
Avec Apache/mod_php, voir [/HowtoApache#too-many-open-files]()
Avec PHP-FPM, il faut modifier la directive `rlimit_files` dans la section `[global]` et le(s) pool(s) concerné(s).
2021-11-12 12:08:31 +01:00