# WP_Filesystem plutôt que file_put_contents dans une extension

> Un plugin qui écrit un fichier de configuration avec les fonctions PHP natives fonctionne partout, jusqu'au jour où il tombe sur un hébergeur qui exige FTP ou SSH pour toute écriture disque.

- Auteur : Clément Hadrot
- Publié le : 2022-09-20
- Mis à jour le : 2022-09-20
- Catégorie : Extensions
- URL : https://wpmoderne.dev.wordpress-developpement.fr/extensions/wp-filesystem-plutot-file-put-contents-extension/

## L’essentiel

- WP_Filesystem abstrait trois méthodes d'accès, direct, FTP, SSH
- Ignorer cette abstraction casse silencieusement l'écriture chez certains hébergeurs
- Le formulaire d'identifiants FTP apparaît automatiquement si nécessaire

Une extension de génération de flux de produits pour comparateurs de prix écrit un fichier XML statique dans le dossier uploads du site, régénéré chaque nuit via une tâche planifiée. Le code initial, écrit avec la simplicité des fonctions PHP natives, utilise directement `file_put_contents()`. Tout fonctionne sans accroc pendant des mois, jusqu'à ce qu'un nouveau client migre son site chez un hébergeur mutualisé dont la configuration serveur impose que le processus PHP tourne avec un utilisateur système différent du propriétaire des fichiers, une configuration de sécurité assez répandue chez certains hébergeurs qui cherchent à isoler strictement chaque site hébergé.

Sur cet hébergement précis, `file_put_contents()` échoue silencieusement, ou plus exactement retourne `false` sans lever d'exception, faute des permissions nécessaires pour écrire directement dans le dossier concerné avec l'utilisateur système du processus PHP. Le flux XML ne se régénère plus, le comparateur de prix affiche des données obsolètes pendant plusieurs jours avant que quelqu'un ne remarque le problème.

## Ce que WordPress propose pour ce cas précis

WordPress fournit depuis longtemps une abstraction dédiée à l'écriture sur le système de fichiers, `WP_Filesystem`, précisément pour gérer cette hétérogénéité entre hébergeurs. Cette abstraction sait s'adapter à trois grandes familles de méthodes d'accès : l'accès direct quand les permissions le permettent, l'accès via FTP quand le processus PHP n'a pas les droits suffisants et qu'un compte FTP est configuré, ou l'accès via SSH2 sur les configurations qui le supportent.

## Utiliser l'abstraction correctement

> L'essentiel à retenir : WP_Filesystem abstrait trois méthodes d'accès, direct, FTP, SSH ; Ignorer cette abstraction casse silencieusement l'écriture chez certains hébergeurs ; Le formulaire d'identifiants FTP apparaît automatiquement si nécessaire

```
function ecrire_flux_produits_xml( string $chemin, string $contenu ): bool {
    global $wp_filesystem;

    if ( empty( $wp_filesystem ) ) {
        require_once ABSPATH . 'wp-admin/includes/file.php';
        WP_Filesystem();
    }

    if ( ! $wp_filesystem ) {
        error_log( 'Impossible d\'initialiser WP_Filesystem pour l\'écriture du flux produits.' );
        return false;
    }

    return $wp_filesystem->put_contents( $chemin, $contenu, FS_CHMOD_FILE );
}
```

Cette version fonctionne de façon identique sur un hébergement qui permet l'écriture directe et sur un hébergement qui l'interdit. Sur ce dernier cas, si aucune méthode d'accès n'a été préalablement configurée par l'administrateur du site via les constantes `FTP_HOST`, `FTP_USER` et `FTP_PASS` dans `wp-config.php`, WordPress affiche automatiquement, lors d'une action déclenchée depuis l'administration, un formulaire de saisie des identifiants FTP nécessaires, le même que celui utilisé nativement pour les mises à jour de plugin ou de thème.

### Un point important pour les tâches automatisées

Ce formulaire de saisie d'identifiants ne peut évidemment pas s'afficher dans le contexte d'une tâche cron exécutée sans interaction humaine, comme dans l'exemple de notre flux XML nocturne. Pour ce cas précis, la constante `FTP_HOST` et les identifiants associés doivent être définis une bonne fois dans `wp-config.php` pour que `WP_Filesystem()` puisse s'initialiser sans intervention, sans quoi le traitement automatisé échouera de la même façon qu'avec `file_put_contents()`, mais cette fois avec un message d'erreur explicite dans les journaux plutôt qu'un échec silencieux.

```
// Dans wp-config.php, sur les hébergements qui l'exigent :
define( 'FTP_HOST', 'ftp.hebergeur-exemple.fr' );
define( 'FTP_USER', 'compte_ftp' );
define( 'FTP_PASS', 'mot-de-passe-en-lieu-sur' );
define( 'FS_METHOD', 'ftpext' );
```

## Ce qu'il ne faut jamais faire malgré tout

- Ne jamais forcer `FS_METHOD` à `direct` par défaut dans le code d'une extension distribuée : ce choix relève de l'administrateur du site ou de son hébergeur, pas de l'extension elle-même.
- Ne pas ignorer la valeur de retour de `put_contents()`, qui peut échouer aussi bien que `file_put_contents()`, pour des raisons différentes cette fois liées à des permissions FTP mal configurées.
- Éviter de stocker les identifiants FTP en dur dans le code d'une extension distribuée : ils doivent toujours provenir de `wp-config.php` ou d'un réglage saisi par l'administrateur, jamais codés en clair dans un fichier de plugin partagé publiquement.

## Quand file_put_contents reste acceptable

Il existe des cas où l'usage direct des fonctions PHP natives reste défendable : l'écriture dans un fichier de log temporaire propre à l'exécution en cours, situé dans un dossier dont on maîtrise entièrement les permissions dès l'installation, ou un contexte purement interne à une agence qui contrôle la totalité de son parc d'hébergement et sait par avance que l'accès direct fonctionnera toujours. Pour une extension distribuée à un public plus large, dont l'environnement d'hébergement est par nature inconnu, l'abstraction reste le choix le plus prudent.

> Une écriture disque qui fonctionne sur son propre serveur de développement ne prouve rien sur son comportement chez un hébergeur qu'on n'a jamais testé.

## En résumé

WP_Filesystem existe précisément pour absorber l'hétérogénéité des configurations d'hébergement rencontrées dans l'écosystème WordPress, entre accès direct, FTP et SSH. Une extension distribuée qui écrit sur le disque sans passer par cette abstraction fonctionnera très bien chez la majorité des hébergeurs, jusqu'au jour où elle rencontrera celui qui l'oblige à passer par un autre chemin, et ce jour-là, l'échec sera silencieux si l'abstraction n'a pas été anticipée dès le départ.
