PHP-ストリームを開くのに失敗しました:そのようなファイルまたはディレクトリがありません

php require fopen include-path


PHPスクリプトでは、 include()require()fopen() 、または include_oncerequire_once 、さらに move_uploaded_file() などの派生物を呼び出すかどうかに関係なく、多くの場合、エラーまたは警告が発生します。

ストリームを開くことができませんでした:そのようなファイルまたはディレクトリがありません。

根本的な原因を素早く見つけるための良いプロセスとは?




Answer 1 Vic Seedoubleyew


人がこのエラーに陥る理由はたくさんあるので、最初にチェックすべきことの良いチェックリストはかなり役立ちます。

以下のラインのトラブルシューティングをしていると考えてみましょう。

require "/path/to/file"


Checklist


1.ファイルパスに誤字がないかチェックする

  • 手で確認するか
  • または require* または include* によって呼び出されたものを独自の変数に移動し、それをエコーし​​てコピーし、ターミナルからアクセスしてみます。

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

    そして、端末で。

    cat <file path pasted>


2.2.相対パスと絶対パスの考慮事項について、ファイルパスが正しいことを確認してください。

  • もしそれがフォワードスラッシュ「"」で始まっている場合、それはあなたのウェブサイトのフォルダのルート(ドキュメントルート)ではなく、あなたのサーバーのルートを参照しています。
    • たとえば、ウェブサイトのディレクトリは /users/tony/htdocs のようになります。
  • スラッシュで始まっていない場合は、インクルードパスに依存しているか(以下を参照)、またはパスが相対パスです。相対である場合、PHPは現在の作業ディレクトリのパスに対して相対的に計算します。
    • を入力しているファイルとは相対的ではありません。
    • そのため、常に絶対ファイルパスを使用します。

ベストプラクティス .

実行時に絶対パスを生成しながらも、何かを移動させた場合に備えてスクリプトを堅牢にするためには、2つのオプションがあります。

  1. require __DIR__ . "/relative/path/from/current/file" 使用します。"/ relative / path / from / current / file"。 __DIR__ の魔法の定数は、現在のファイルのディレクトリを返します。
  2. SITE_ROOT 定数を自分で定義します。

    • Webサイトのディレクトリのルートに、 config.php などのファイルを作成します。
    • config.php 、書き込み

      define('SITE_ROOT', __DIR__);
    • サイトのルートフォルダーを参照するすべてのファイルに config.php を含め、 SITE_ROOT 定数を好きな場所で使用します。

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

これら2つの方法は、インクルードパスのようなini設定に依存しないので、アプリケーションをより移植性の高いものにします。


3.インクルードパスをチェック

比較的または完全にではなく、ファイルをインクルードする別の方法は、インクルードパスに依存することです。これは、Zendフレームワークなどのライブラリまたはフレームワークの場合によく見られます。

そのようなインクルージョンは次のようになります。

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

その場合は、"Zend "があるフォルダがインクルードパスに含まれていることを確認する必要があります。

インクルードパスを確認するには .

echo get_include_path();

でフォルダを追加することができます。

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


4.サーバーがそのファイルにアクセスできることを確認します。

サーバプロセス(ApacheやPHP)を実行しているユーザが、そのファイルを読み書きする権限を持っていないのかもしれません。

サーバーが実行しているユーザーを確認するには、posix_getpwuidを使用できます。

$user = posix_getpwuid(posix_geteuid());

var_dump($user);

ファイルのパーミッションを調べるには、ターミナルで以下のコマンドを入力します。

ls -l <path/to/file>

許可の記号表記を見てください


5.PHPの設定を確認する

上記のどれもうまくいかなかった場合は、PHPの設定によってそのファイルへのアクセスが禁止されていることが問題なのかもしれません。

3つの設定が関連している可能性があります。

  1. open_basedir
    • これを設定すると、PHP は指定したディレクトリ以外のファイルにはアクセスできなくなります (シンボリックリンクでさえも)。
    • ただし、デフォルトでは設定されないようになっており、その場合は制限はありません。
    • これは、 phpinfo()呼び出すか、 ini_get("open_basedir") を使用して確認できます。
    • php.ini ファイルか httpd.conf ファイルを編集することで設定を変更することができます。
  2. セーフモード
    • これがオンになっている場合、制限が適用される可能性があります。ただし、これはPHP 5.4で削除されました。あなたはサポートセーフモードがされたPHPのバージョンにアップグレードすることをバージョンに残っている場合は、引き続きサポートされています
  3. allow_url_fopen および allow_url_include
    • これは、http:/のようなネットワークプロセスを介してファイルをインクルードしたり開いたりする場合にのみ適用されます。
    • これは、 ini_get("allow_url_include") で確認し、 ini_set("allow_url_include", "1")


コーナーケース

上記のどれもが問題を診断することを有効にした場合は、ここに起こる可能性があるいくつかの特別な状況があります。


1.インクルードパスに依存したライブラリのインクルード

ライブラリをインクルードする際に、例えば Zend Framework のように相対パスや絶対パスを使用してしまうことがあります。例えば .

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

でも、それでも同じようなエラーが出ます。

これは、(正常に)インクルードしたファイルが、それ自体が別のファイルのインクルード文を持っていて、その2番目のインクルード文は、そのライブラリのパスをインクルードパスに追加したと仮定しているために起こる可能性があります。

例えば、先ほどのZendフレームワークのファイルは、次のようにインクルードされているかもしれません。

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

は、相対パスによるインクルードでも絶対パスによるインクルードでもありません。これは、Zend フレームワークディレクトリがインクルードパスに追加されていることを前提としています。

このような場合、実用的な唯一の解決策は、インクルードパスにそのディレクトリを追加することです。


2.SELinux

Security-Enhanced Linuxを実行している場合は、サーバーからのファイルへのアクセスを拒否していることが原因かもしれません。

システムでSELinuxが有効になっているかどうかを確認するには、ターミナルで sestatus コマンドを実行します。コマンドが存在しない場合、SELinuxはシステム上にありません。存在する場合は、強制されているかどうかが表示されます。

SELinuxポリシーが問題の原因であるかどうかを確認するには、一時的にオフにしてみてください。ただし、これにより保護が完全に無効になるため、注意が必要です。本番サーバーではこれを行わないでください。

setenforce 0

SELinuxをオフにしても問題が起こらなくなった場合は、これが根本原因です。

これを解決するにはそれに応じてSELinuxを設定する必要があります。

以下のコンテキストタイプが必要になります。

  • httpd_sys_content_t サーバーが読み取れるようにするファイルのhttpd_sys_content_t
  • httpd_sys_rw_content_t 読み取りおよび書き込みアクセス権が必要なファイルのhttpd_sys_rw_content_t
  • httpd_log_t ログファイルの場合はhttpd_log_t
  • httpd_cache_t キャッシュディレクトリのhttpd_cache_t

たとえば、 httpd_sys_content_t コンテキストタイプをウェブサイトのルートディレクトリに割り当てるには、次のコマンドを実行します。

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

ファイルがホームディレクトリにある場合は、 httpd_enable_homedirs ブール値もオンにする必要があります。

setsebool -P httpd_enable_homedirs 1

いずれの場合でも、ポリシーによっては、SELinuxがファイルへのアクセスを拒否するさまざまな理由が考えられます。だからあなたはそれを調査する必要があります。以下は、Webサーバー用にSELinuxを構成することに関する具体的なチュートリアルです。


3.symfony

Symfonyを使用していて、サーバーにアップロードするときにこのエラーが発生する場合は、 app/cache がアップロードされたか、キャッシュがクリアされていないため、アプリのキャッシュがリセットされていない可能性があります。

以下のコンソールコマンドを実行することで、これをテストして修正することができます。

cache:clear


4.Zipファイル内のACSII以外の文字

このエラーは、zip内の一部のファイルのファイル名に「é」などの非ASCII文字が含まれている場合に、 zip->close() を呼び出したときにも発生する可能性があります。

可能な解決策は、ターゲットファイルを作成する前に、ファイル名を utf8_decode() でラップすることです。

クレジットフランカノ、この問題に対する解決策を特定し、示唆のために




Answer 2 Machavity


既存の(本当に良い)答えに加えて

共有ホスティングソフトウェア

open_basedir は、Webサーバー構成で指定できるため、困惑する可能性があります。独自の専用サーバーを実行すればこれは簡単に修正できますが、ドメインごとに構成ディレクティブを構成する共有ホスティングソフトウェアパッケージ(Plesk、cPanelなど)がいくつかあります。ソフトウェアは構成ファイル(つまり httpd.conf )を構築するため、ホスティングソフトウェアは再起動時にファイルを上書きするだけなので、そのファイルを直接変更することはできません。

Pleskでは、 vhost.conf と呼ばれる提供された httpd.conf を上書きする場所を提供します。サーバー管理者のみがこのファイルを書き込むことができます。Apacheの設定は次のようになります

<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>

サーバー管理者が使用しているホスティングやウェブサーバーソフトウェアのマニュアルを参照してください。

ファイルの許可

ウェブサーバーを介したファイルの実行は、コマンドラインやcronジョブの実行とは大きく異なることに注意することが重要です。大きな違いは、Webサーバーには独自のユーザーと権限があることです。セキュリティ上の理由から、そのユーザーはかなり制限されています。たとえば、Apacheはしばしば apachewww-data または httpd (サーバーによって異なります)です。cronジョブまたはCLIの実行には、それを実行しているユーザーが持つすべての権限があります(つまり、PHPスクリプトをrootとして実行すると、rootの権限で実行されます)。

多くの場合、パーミッションの問題を解決するには、次のようにします (Linux の例)。

chmod 777 /path/to/file

これはスマートな考えではありません。あなたがサーバーを所有していて、唯一のユーザーであれば、これはそれほど大きな問題ではありませんが、もしあなたが共有ホスティング環境を利用しているのであれば、あなたのサーバー上の全員にアクセス権を与えてしまったことになります。

必要なのは、アクセスを必要とするユーザーを決定し、そのユーザーだけにアクセス権を与えることです。アクセスを必要とするユーザーがわかったら、次のことを確認してください。

  1. そのユーザーはファイル所有し、場合によっては親ディレクトリー(特に、ファイルを書き込みたい場合は親ディレクトリー)を所有します。ほとんどの共有ホスティング環境では、ユーザーはルートの下にあるすべてのファイルを所有する必要があるため、これは問題になりません。Linuxの例を以下に示します

    chown apache:apache /path/to/file
  2. ユーザーは、そのユーザーのみがアクセスできます。Linuxでは、 chmod 600 (所有者のみが読み取りと書き込みを実行できます)または chmod 644 (所有者は書き込み可能ですが、すべてのユーザーが読み取り可能)が適切です。

あなたはできるのLinux / Unixの権限とユーザーのより拡張された議論をここで読みます




Answer 3 Hammad Khan


  1. 正確なエラーを見てください

私のコードはすべてのマシンで正常に動作していましたが、このマシンでのみ問題が発生しました (以前は動作していたと思います)。デバッグのために echo "document_root" パスを使用し、エラーをよく見てみると、以下のようになっていました。

警告:include(D:/MyProjects/testproject//functions/connections.php):ストリームを開けませんでした:

どこに問題があるのかがすぐにわかります。問題点は/機能の前に

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

ですから、単にインクルードから船荷を削除するだけで、問題なく動作するはずです。面白いのは、バージョンによって挙動が違うことです。私はラップトップ、Macbook ProとこのPCで同じコードを実行したが、すべては今までうまくいっていた。これは誰かを助けることを願っています。

  1. ブラウザでファイルの場所をコピーペーストして、ファイルが存在することを確認してください。時々ファイルが突然削除されることがあります(私の場合はそうでした)、それは私の場合の問題でもありました。



Answer 4 Paul Lynn


クエリパラメータを持つスクリプトを追加

それは私の場合でした。実際には質問#4485874にリンクしていますが、ここで簡単に説明します。
path/to/script.php?parameter=value を要求しようとすると、UNIXではこのようなパスを使用できるため、PHPは script.php?parameter=value という名前のファイルを探します。
含まれているスクリプトにデータを渡す必要がある場合は、 $variable=... または $GLOBALS[]=... またはその他の方法で宣言してください。




Answer 5 Stephan Brunker


Sambaシェア

Linuxテストサーバーがあり、Windowsクライアントから作業している場合、Samba共有はchmodコマンドを妨害します。だから、たとえあなたが使ったとしても:

chmod -R 777 myfolder

Linux側では、Unix Group\www-dataがまだ書き込みアクセスを持っていない可能性があります。Windowsの管理者がrootにマップされるように設定されている場合、一つの解決策があります。Windowsの管理者がrootにマップされている共有を設定している場合、一つの解決策は、Windowsの管理者がrootにマップされている共有を設定することです。