[解決済み] PHP - ストリームを開くのに失敗しました : そのようなファイルまたはディレクトリがありません。
質問
PHPスクリプトでは
include()
,
require()
,
fopen()
またはその派生物である
include_once
,
require_once
, あるいは
move_uploaded_file()
というエラーや警告に遭遇することがよくあります。
ストリームを開くのに失敗しました:そのようなファイルまたはディレクトリがありません。
問題の根本的な原因を素早く見つけるために、何か良いプロセスはありますか?
どのように解決するのですか?
このエラーに遭遇する理由はさまざまなので、最初に何を確認すべきかのチェックリストが非常に役に立ちます。
次のような行のトラブルシューティングを行う場合を考えてみましょう。
require "/path/to/file"
チェックリスト
1. ファイルパスに誤字がないか確認する
- 手動で確認する(パスを目視で確認する)か
-
で呼び出されたものを移動させるか
require*
またはinclude*
を自分の変数にコピーし、それをechoし、コピーして、ターミナルからアクセスしてみてください。$path = "/path/to/file"; echo "Path : $path"; require "$path";
次に、ターミナルで
cat <file path pasted>
2. ファイルパスが正しいかどうか、相対パスと絶対パスについて考慮すること
-
フォワードスラッシュ "/"で始まっている場合は、ウェブサイトのフォルダーのルート(ドキュメントルート)ではなく、サーバーのルートを指していることになります。
-
例えば、あなたのウェブサイトのディレクトリは、次のようになります。
/users/tony/htdocs
-
例えば、あなたのウェブサイトのディレクトリは、次のようになります。
-
がフォワードスラッシュで始まっていない場合、インクルードパスに依存しているか(下記参照)、パスが相対パスであるかのどちらかです。相対パスである場合、PHP は
現在の作業ディレクトリ
.
- したがって、Web サイトのルートのパスや、入力中のファイルからの相対パスではありません。
- そのため、ファイルパスは常に絶対パスを使用します。
ベストプラクティス:
実行時に絶対パスを生成しつつ、スクリプトを移動した場合に備えて堅牢にするために、2つのオプションがあります。
-
使用
require __DIR__ . "/relative/path/from/current/file"
. その__DIR__
魔法定数 は、現在のファイルのディレクトリを返します。 -
を定義します。
SITE_ROOT
定数を自分で設定します。-
を、あなたのウェブサイトのディレクトリのルートに、例えば、次のようなファイルを作成します。
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つの設定に関連する可能性があります。
-
オープンベースドア
- この設定をすると、PHP は指定されたディレクトリ以外のファイルにはアクセスできなくなります (シンボリックリンクを使ったアクセスもできません)。
- しかし、デフォルトの動作は設定されておらず、この場合、制限はありません。
-
を呼び出すことで確認できます。
phpinfo()
またはini_get("open_basedir")
- php.iniファイルまたはhttpd.confファイルを編集することで設定を変更することができます。
-
セーフモード
- をオンにすると、制限が適用される場合があります。しかし、これは PHP 5.4 で削除されました。セーフモードをサポートしているバージョンを使用している場合は、セーフモードをサポートしているPHPのバージョンにアップグレードしてください。 まだサポートされています .
-
allow_url_fopenとallow_url_includeを使用します。
- これは、http:// のようなネットワークプロセスを通してファイルをインクルードしたり開いたりする場合にのみ適用され、ローカルファイルシステム上のファイルをインクルードしようとする場合には適用されません。
-
で確認することができます。
ini_get("allow_url_include")
で設定しini_set("allow_url_include", "1")
コーナーケース
上記のいずれの方法でも診断ができない場合、以下のような特殊な状況が考えられます。
1. インクルードパスに依存するライブラリのインクルードについて
例えば、Zendフレームワークのようなライブラリを相対パスあるいは絶対パスでインクルードすることがあります。たとえば、次のような場合です。
require "/usr/share/php/libzend-framework-php/Zend/Mail/Protocol/Imap.php"
でも、そうすると、やはり同じようなエラーが出てしまいます。
これは、インクルードが成功したファイル自体に、別のファイルのインクルード文があり、その2番目のインクルード文が、インクルードパスにそのライブラリのパスを追加したものと仮定しているために起こり得ます。
例えば、先ほどのZend frameworkのファイルでは、以下のようなincludeが可能です。
include "Zend/Mail/Protocol/Exception.php"
は相対パスによるインクルージョンでも絶対パスによるインクルージョンでもない。これは、Zend framework ディレクトリがインクルードパスに追加されていることを想定しています。
このような場合、唯一の現実的な解決策は、そのディレクトリをインクルードパスに追加することです。
2. SELinux
Security-Enhanced Linuxを使用している場合、サーバーからのファイルへのアクセスを拒否することで、問題の原因になっている可能性があります。
SELinuxが有効かどうかを確認するには
を実行します。
sestatus
コマンドをターミナルで実行します。このコマンドが存在しない場合、SELinuxはあなたのシステムには存在しないことになります。存在する場合は、SELinuxが実行されているかどうかが表示されるはずです。
SELinuxポリシーが原因かどうかを確認するには を一時的にオフにしてみてください。しかし、これは保護を完全に無効にするので、注意してください。本番サーバーでは行わないでください。
setenforce 0
SELinuxをオフにした状態で問題が発生しなくなった場合は、これが根本的な原因です。
解決するには SELinuxの設定を変更する必要があります。
以下のコンテキストタイプが必要になります。
-
httpd_sys_content_t
サーバーに読み込ませたいファイル用 -
httpd_sys_rw_content_t
読み取りと書き込みが必要なファイル用 -
httpd_log_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がファイルへのアクセスを拒否する理由は、あなたのポリシー次第で様々なものが考えられます。そのため、その点を調査する必要があります。 これ は、ウェブサーバーにSELinuxを設定するための特別なチュートリアルです。
3. シンフォニー
Symfonyを使用していて、サーバーにアップロードするときにこのエラーが発生する場合、アプリのキャッシュがリセットされていない可能性があります。
app/cache
がアップロードされているか、キャッシュがクリアされていない。
以下のコンソールコマンドを実行することで、テストと修正を行うことができます。
cache:clear
4. Zipファイル内の非ACSII文字
どうやら、このエラーは
zip->close()
のような非 ASCII 文字がファイル名に含まれている場合、zip ファイルを作成することができます。
解決策としては、ファイル名を
utf8_decode()
を作成してから、ターゲットファイルを作成します。
クレジット フラン・カノ この問題を特定し、解決策を提案してくれた
関連
-
[解決済み】Weird PHP error: 'Can't use function return value in write context'.
-
[解決済み】move_uploaded_fileは、「failed to open stream: Permission denied" というエラーが出る
-
[解決済み】 libapache2-mod-php7 パッケージが見つからない。
-
[解決済み】未定義の関数mysql_query()をLoginで呼び出す【重複
-
[解決済み] * vchiqインスタンスを開くのに失敗しました。
-
[解決済み】phpMyAdmin: シークレットパスフレーズ?
-
[解決済み] 入力ファイルが指定されていない
-
[解決済み】SSLピア証明書またはSSHリモートキーがOKでなかった
-
phpのAllowed memory size of 134217728 bytes枯渇問題の解決法
-
[解決済み] require(vendor/autoload.php): ストリームを開くのに失敗しました。
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み】PHP - 構文エラー、予期しないT_CONSTANT_ECAPSED_STRING [閉店].
-
[解決済み】phpのob_start()の使い道は?
-
[解決済み】PHP定数「PHP_EOL」はいつ使うの?
-
[解決済み】mysqli_result クラスのオブジェクトを文字列に変換できない
-
[解決済み] SAJAXは死んだか?何を置き換えるべきか?
-
[解決済み】Apache + PHPで「ヘッダの前にスクリプトの出力が終了する」件
-
[解決済み】警告:mysql_fetch_array()はパラメータ1がリソースであることを期待、ブール値は[重複]で与えられる]
-
[解決済み】Netbeans 7.4 for PHPで「スーパーグローバルな$_POST配列に直接アクセスしないでください」という警告が発生する。
-
[解決済み] Uncaught Error: 未定義の関数 mysql_escape_string() の呼び出し。
-
[解決済み] PHP 未定義関数への呼び出し