228 votes

PHP - Impossible d'ouvrir le flux : aucun fichier ou répertoire de ce type.

Dans les scripts de PHP, que l'on appelle include() , require() , fopen() ou leurs dérivés tels que include_once , require_once ou même, move_uploaded_file() on se heurte souvent à une erreur ou à un avertissement :

Impossible d'ouvrir le flux : aucun fichier ou répertoire de ce type.

Quel est le bon processus pour trouver rapidement la cause première du problème ?

5 votes

J'ai nettoyé les commentaires hors-sujet de ce post. Veuillez garder les discussions méta dans les méta. Cependant, veuillez noter que la discussion sur la viabilité des questions canoniques a été faite encore et encore et encore. Voir exemple aquí .

1 votes

J'ai le même problème, la seule solution qui a toujours fonctionné est la suivante : -1 Allez sur le fichier à inclure, cliquez à droite, propriétés, copiez le chemin complet. Par exemple : C:/......../file.php 2- Incluez-le. En fait, j'ai vu que cette question est répondue , et la réponse est validée , mais pour moi dans certains cas ne fonctionne pas , jusqu'à ce que je trouve la façon décrite ci-dessus .

0 votes

@Rash merci pour votre contribution. Malheureusement, votre solution est erronée, car elle mentionne le nom du chemin absolu, ce qui est faux. La raison pour laquelle c'est faux, c'est qu'au moment où vous copiez votre projet ailleurs, ou que vous le déplacez dans votre ordinateur, tout se casse.

340voto

Vic Seedoubleyew Points 35

Il y a de nombreuses raisons pour lesquelles on peut rencontrer cette erreur et une bonne liste de ce qu'il faut vérifier en premier est donc très utile.

Considérons que nous sommes en train de dépanner la ligne suivante :

require "/path/to/file"

Liste de contrôle

1. Vérifiez l'absence de fautes de frappe dans le chemin du fichier

  • soit vérifier manuellement (en contrôlant visuellement le chemin)
  • ou déplacer ce qui est appelé par require* o include* dans sa propre variable, faites un écho, copiez-le, et essayez d'y accéder depuis un terminal :

    $path = "/path/to/file";
    
    echo "Path : $path";
    
    require "$path";

    Puis, dans un terminal :

    cat <file path pasted>

2. Vérifiez que le chemin d'accès au fichier est correct en ce qui concerne les considérations de chemin relatif et absolu.

  • s'il commence par une barre oblique "/", il ne s'agit pas de la racine du dossier de votre site web (la racine du document), mais de la racine de votre serveur.
    • par exemple, le répertoire de votre site web pourrait être /users/tony/htdocs
  • s'il ne commence pas par une barre oblique, il s'appuie sur le chemin d'inclusion (voir ci-dessous) ou le chemin est relatif. S'il est relatif, alors PHP calculera relativement au chemin de l'objet le répertoire de travail actuel .
    • donc, pas relative au chemin du Root de votre site web, ou au fichier où vous tapez
    • pour cette raison, utilisez toujours des chemins de fichiers absolus

Meilleures pratiques :

Afin de rendre votre script robuste au cas où vous déplaceriez des choses, tout en générant un chemin absolu au moment de l'exécution, vous avez 2 options :

  1. utilice require __DIR__ . "/relative/path/from/current/file" . Le site __DIR__ constante magique renvoie le répertoire du fichier courant.
  2. définir un SITE_ROOT constant vous-même :

    • à la racine du répertoire de votre site web, créez un fichier, par ex. config.php

    • sur config.php , écrivez

      define('SITE_ROOT', __DIR__);
    • dans chaque fichier où vous voulez faire référence au dossier racine du site, incluez config.php et ensuite utiliser le SITE_ROOT constant où vous le souhaitez :

      require_once __DIR__."/../config.php";
      ...
      require_once SITE_ROOT."/other/file.php";

Ces deux pratiques rendent également votre application plus portable car elle ne dépend pas des paramètres ini comme le chemin d'inclusion.

3. Vérifiez votre chemin d'inclusion

Une autre façon d'inclure des fichiers, ni de manière relative ni de manière purement absolue, est de s'appuyer sur la fonction inclure le chemin . C'est souvent le cas pour les bibliothèques ou les frameworks tels que le framework Zend.

Une telle inclusion ressemblera à ceci :

include "Zend/Mail/Protocol/Imap.php"

Dans ce cas, vous devrez vous assurer que le dossier où se trouve "Zend" fait partie du chemin d'inclusion.

Vous pouvez vérifier le chemin d'inclusion avec :

echo get_include_path();

Vous pouvez y ajouter un dossier avec :

set_include_path(get_include_path().":"."/path/to/new/folder");

4. Vérifiez que votre serveur a accès à ce fichier

Il se peut que l'utilisateur qui exécute le processus serveur (Apache ou PHP) n'ait tout simplement pas le droit de lire ou d'écrire dans ce fichier.

Pour vérifier sous quel utilisateur le serveur est exécuté, vous pouvez utiliser posix_getpwuid :

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

Pour connaître les permissions sur le fichier, tapez la commande suivante dans le terminal :

ls -l <path/to/file>

et regarder notation symbolique de la permission

5. Vérifiez les paramètres PHP

Si rien de ce qui précède n'a fonctionné, le problème est probablement que certains paramètres de PHP lui interdisent d'accéder à ce fichier.

Trois paramètres pourraient être pertinents :

  1. open_basedir
    • Si cette option est activée, PHP ne pourra pas accéder à un fichier situé en dehors du répertoire spécifié (pas même via un lien symbolique).
    • Cependant, le comportement par défaut est qu'il n'est pas défini, auquel cas il n'y a pas de restriction.
    • Cela peut être vérifié soit en appelant phpinfo() ou en utilisant ini_get("open_basedir")
    • Vous pouvez modifier ce paramètre en éditant votre fichier php.ini ou votre fichier httpd.conf.
  2. mode sans échec
    • si cette option est activée, des restrictions peuvent s'appliquer. Cependant, cela a été supprimé dans PHP 5.4. Si vous utilisez toujours une version qui supporte le mode sans échec, mettez à jour votre version de PHP avec le mode sans échec. toujours soutenu .
  3. allow_url_fopen et allow_url_include
    • cela ne s'applique qu'à l'inclusion ou à l'ouverture de fichiers par le biais d'un processus réseau tel que http:// et non pas lorsqu'on essaie d'inclure des fichiers sur le système de fichiers local
    • cela peut être vérifié avec ini_get("allow_url_include") et fixé avec ini_set("allow_url_include", "1")

Cas d'angle

Si aucune des méthodes ci-dessus n'a permis de diagnostiquer le problème, voici quelques situations particulières qui peuvent se produire :

1. L'inclusion de la bibliothèque s'appuyant sur le chemin d'inclusion

Il peut arriver que vous incluiez une bibliothèque, par exemple, le framework Zend, en utilisant un chemin relatif ou absolu. Par exemple :

require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"

Mais vous obtenez toujours le même type d'erreur.

Cela peut se produire parce que le fichier que vous avez inclus (avec succès) a lui-même une déclaration d'inclusion pour un autre fichier, et cette deuxième déclaration d'inclusion suppose que vous avez ajouté le chemin de cette bibliothèque au chemin d'inclusion.

Par exemple, le fichier du framework Zend mentionné précédemment pourrait avoir l'include suivant :

include "Zend/Mail/Protocol/Exception.php" 

qui n'est ni une inclusion par chemin relatif, ni par chemin absolu. Elle suppose que le répertoire du framework Zend a été ajouté au chemin d'inclusion.

Dans ce cas, la seule solution pratique est d'ajouter le répertoire à votre chemin d'inclusion.

2. SELinux

Si vous utilisez un système Linux à sécurité renforcée, cela peut être la raison du problème, en refusant l'accès au fichier depuis le serveur.

Pour vérifier si SELinux est activé sur votre système, exécutez le sestatus dans un terminal. Si la commande n'existe pas, alors SELinux n'est pas présent sur votre système. Si elle existe, elle devrait vous indiquer si elle est appliquée ou non.

Pour vérifier si les politiques SELinux en sont la cause pour le problème, vous pouvez essayer de l'éteindre temporairement. Cependant, soyez PRUDENT, car cela désactivera entièrement la protection. Ne faites pas cela sur votre serveur de production.

setenforce 0

Si vous ne rencontrez plus le problème lorsque SELinux est désactivé, il s'agit de la cause première.

Pour le résoudre vous devrez configurer SELinux en conséquence.

Les types de contexte suivants seront nécessaires :

  • httpd_sys_content_t pour les fichiers que vous voulez que votre serveur puisse lire.
  • httpd_sys_rw_content_t pour les fichiers sur lesquels vous voulez un accès en lecture et écriture
  • httpd_log_t pour les fichiers journaux
  • httpd_cache_t pour le répertoire de cache

Par exemple, pour attribuer le httpd_sys_content_t dans le répertoire racine de votre site web, exécutez :

semanage fcontext -a -t httpd_sys_content_t "/path/to/root(/.*)?"
restorecon -Rv /path/to/root

Si votre fichier se trouve dans un répertoire personnel, vous devrez également activer l'option d'accès à l'information. httpd_enable_homedirs boolean :

setsebool -P httpd_enable_homedirs 1

Dans tous les cas, SELinux peut refuser l'accès à un fichier pour diverses raisons, en fonction de vos politiques. Vous devrez donc vous renseigner à ce sujet. Aquí est un tutoriel portant spécifiquement sur la configuration de SELinux pour un serveur web.

3. Symfony

Si vous utilisez Symfony et que vous rencontrez cette erreur lors du téléchargement vers un serveur, il est possible que le cache de l'application n'ait pas été réinitialisé, soit parce que app/cache a été téléchargé, ou que le cache n'a pas été vidé.

Vous pouvez tester et corriger ce problème en exécutant la commande console suivante :

cache:clear

4. Caractères non ACSII dans le fichier Zip

Apparemment, cette erreur peut également se produire en appelant zip->close() lorsque certains fichiers du zip contiennent des caractères non ASCII dans leur nom de fichier, comme "é".

Une solution potentielle est d'envelopper le nom du fichier dans un fichier utf8_decode() avant de créer le fichier cible.

Crédits pour Fran Cano pour avoir identifié et suggéré une solution à ce problème

4 votes

Je pense que la mention de selinux peut être une bonne idée ici. vous aurez au moins besoin de httpd_sys_content_t (Répertoires et fichiers en lecture seule utilisés par Apache) permission sur les fichiers inclus.

0 votes

Merci beaucoup pour cette suggestion. Comme je ne suis pas familier avec SELinux, j'ai fait quelques lectures et j'ai essayé de répondre à ce cas. N'hésitez pas à faire des commentaires ou à suggérer des modifications si ce n'est pas correct. Merci encore pour le commentaire !

0 votes

chcon est temporaire et ne survivra pas à une restorecon ou un redémarrage. vous devrez peut-être utiliser semanage pour changer le contexte du fichier. Voici une bonne tutoriel simple pour site web

17voto

Machavity Points 7587

Pour ajouter à la (très bonne) réponse existante

Logiciel d'hébergement partagé

open_basedir est un élément qui peut vous laisser perplexe car il peut être spécifié dans la configuration d'un serveur web. Bien qu'il soit facile de remédier à ce problème si vous utilisez votre propre serveur dédié, certains logiciels d'hébergement partagé (comme Plesk, cPanel, etc.) permettent de configurer une directive de configuration pour chaque domaine. Étant donné que le logiciel construit le fichier de configuration (c.-à-d. httpd.conf ), vous ne pouvez pas modifier ce fichier directement car le logiciel d'hébergement l'écrasera lorsqu'il redémarrera.

Dans le cas de Plesk, il est possible de remplacer l'option fournie par l'utilisateur. httpd.conf appelé vhost.conf . Seul l'administrateur du serveur peut écrire ce fichier. La configuration d'Apache ressemble à ceci

<Directory /var/www/vhosts/domain.com>
    <IfModule mod_php5.c>
        php_admin_flag engine on
        php_admin_flag safe_mode off
        php_admin_value open_basedir "/var/www/vhosts/domain.com:/tmp:/usr/share/pear:/local/PEAR"
    </IfModule>
</Directory>

Demandez à l'administrateur de votre serveur de consulter le manuel du logiciel d'hébergement et de serveur web qu'il utilise.

Autorisations de fichiers

Il est important de noter que l'exécution d'un fichier via votre serveur Web est très différente de l'exécution d'une ligne de commande ou d'un travail cron. La grande différence est que votre serveur web a son propre utilisateur et ses propres autorisations. Pour des raisons de sécurité, cet utilisateur est assez restreint. Apache, par exemple, est souvent apache , www-data o httpd (en fonction de votre serveur). Une tâche cron ou une exécution CLI dispose des autorisations de l'utilisateur qui l'exécute (c'est-à-dire que l'exécution d'un script PHP en tant que Root s'exécutera avec les autorisations de Root).

Souvent, les gens résolvent un problème de permissions en faisant ce qui suit (exemple Linux)

chmod 777 /path/to/file

Ce n'est pas une bonne idée, car le fichier ou le répertoire est maintenant accessible en écriture dans le monde entier. Si vous possédez le serveur et que vous êtes le seul utilisateur, ce n'est pas très grave, mais si vous êtes dans un environnement d'hébergement partagé, vous venez de donner accès à tous les utilisateurs de votre serveur.

Ce que vous devez faire, c'est déterminer le ou les utilisateurs qui ont besoin d'un accès et ne donner accès qu'à ces derniers. Une fois que vous savez quels utilisateurs ont besoin d'accès, vous devez vous assurer que

  1. Cet utilisateur possède le fichier et éventuellement le répertoire parent (en particulier le répertoire parent si vous voulez écrire des fichiers). Dans la plupart des environnements d'hébergement partagé, ce n'est pas un problème, car votre utilisateur devrait posséder tous les fichiers sous votre Root. Un exemple pour Linux est présenté ci-dessous

     chown apache:apache /path/to/file
  2. L'utilisateur, et lui seul, y a accès. Sous Linux, une bonne pratique serait chmod 600 (seul le propriétaire peut lire et écrire) ou chmod 644 (le propriétaire peut écrire mais tout le monde peut lire)

Vous pouvez Pour une discussion plus approfondie sur les permissions et les utilisateurs Linux/Unix, cliquez ici.

10voto

Nick Points 2689
  1. Regardez le exact erreur

Mon code a fonctionné correctement sur toutes les machines, mais ce n'est que sur celle-ci qu'il a commencé à poser problème (alors qu'il fonctionnait auparavant, je suppose). J'ai utilisé le chemin echo "document_root" pour déboguer et j'ai aussi regardé de près l'erreur, j'ai trouvé ceci

Attention : include( D:/MyProjects/testproject//functions/connections.php ) : failed to open stream :

Vous pouvez facilement voir où sont les problèmes. Les problèmes sont // avant les fonctions

$document_root = $_SERVER['DOCUMENT_ROOT'];
echo "root: $document_root";
include($document_root.'/functions/connections.php');

Il suffit donc d'enlever le lading / de l'inclusion et cela devrait fonctionner correctement. Ce qui est intéressant, c'est que ce comportement est différent sur les différentes versions. J'ai exécuté le même code sur un ordinateur portable, un Macbook Pro et ce PC, tout fonctionnait bien jusqu'à présent. J'espère que cela aidera quelqu'un.

  1. Copiez l'emplacement du fichier dans le navigateur pour vous assurer que le fichier existe. Parfois, les fichiers sont supprimés de manière inattendue (cela m'est arrivé) et c'était également le problème dans mon cas.

0 votes

En quoi cela diffère-t-il de l'étape 1 de la liste de contrôle ci-dessous ?

0 votes

L'étape 2 est un contrôle supplémentaire, sans rapport avec l'étape 1. Il suffit de naviguer vers le chemin proposé dans le navigateur et de voir si le fichier s'y trouve (pas dans l'explorateur Windows mais dans le navigateur).

2voto

Paul Lynn Points 11

Ajouter script avec des paramètres de requête

C'était mon cas. En fait, il y a un lien vers question #4485874 mais je vais l'expliquer ici brièvement.
Lorsque vous essayez d'exiger path/to/script.php?parameter=value PHP recherche le fichier nommé script.php?parameter=value car UNIX vous permet d'avoir des chemins comme celui-ci.
Si vous avez vraiment besoin de passer des données à un script inclus, il suffit de le déclarer en tant que $variable=... o $GLOBALS[]=... ou d'une autre manière que vous souhaitez.

1voto

zMeadz Points 19

Une autre cause possible : Renommer et/ou déplacer des fichiers dans un éditeur de texte. J'ai suivi toutes les étapes ci-dessus sans succès jusqu'à ce que je supprime le fichier qui provoquait cette erreur et en crée un nouveau, ce qui a réglé le problème.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X