質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.51%
PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

Q&A

解決済

1回答

8387閲覧

[PHP CakePHP]windows環境にて、パスやファイル名に日本語を含む場合のファイル情報の取得について

orange0190

総合スコア1698

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

CakePHP

CakePHPは、PHPで書かれたWebアプリケーション開発用のフレームワークです。 Ruby on Railsの考え方を多く取り入れており、Railsの高速性とPHPの機動性を兼ね備えています。 MVCやORMなどを「規約優先の考え方」で利用するため、コードを書く手間を省くことができます。 外部のライブラリに依存しないので、単体での利用が可能です。

0グッド

1クリップ

投稿2016/01/07 04:16

編集2016/01/07 08:43

###前提・実現したいこと
現在、仕事上でPHP(CakePHP)を用いてwebアプリケーションを作成しています。
そのwebアプリケーションの中で、実行するPHPファイルが置かれているサーバとは、別のサーバに共有フォルダを置き、そのフォルダ内のファイルおよびフォルダを列挙する機能があります。

###発生している問題
共有先はwindowsであり、ファイル名は文字コードがsjis-winとなっているため、ファイル名にいわゆる「ダメ文字」が含まれている場合に、pathinfo()等が正しく取得できません。

ファイル名にダメ文字が含まれている場合でも、正しく情報を取得する方法をご教授願えますでしょうか。

###補足情報(言語/FW/ツール等のバージョンなど)
共有先 windows7
PHP 5.6.12
CakePHP 2.7.7

以上、よろしくお願いします。

###追記 ソースコード

PHP

1$path = SHARED_FOLDER . $no; // SHARED_FOLDERは列挙するフォルダのパス,$noはIDのようなもの 2$sharedFiles = getSharedFiles($path); 3 4function getSharedFiles($path){ 5 setlocale(LC_ALL, 'ja_JP.UTF-8'); 6 $search = str_replace(DS, '/', rtrim($path, DS) . DS . '*'); //DSはDIRECTORY_SEPARATOR 7 $files = glob($search); 8 $info = array (); 9 foreach($files as $file) { 10 $data = array (); 11 $pathInfo = pathinfo($file); 12 if(is_file($file)) { 13 $data['FILE_TYPE'] = 'file'; 14 $data['FILE_NM'] = mb_convert_encoding($pathInfo['basename'], 'utf-8', 'sjis-win'); 15 $data['PARENT_DIR'] = mb_convert_encoding($pathInfo['dirname'], 'utf-8', 'sjis-win'); 16 $data['SUB_FILES'] = ''; 17 } else if(is_dir($file)) { 18 $data['FILE_TYPE'] = 'dir'; 19 $data['FILE_NM'] = mb_convert_encoding($pathInfo['basename'], 'utf-8', 'sjis-win'); 20 $data['PARENT_DIR'] = mb_convert_encoding($pathInfo['dirname'], 'utf-8', 'sjis-win'); 21 $data['SUB_FILES'] = getSharedFiles($file); 22 } 23 $info[] = $data; 24 } 25 return $info; 26} 27

###再追記 具体的な実行例
列挙対象のフォルダ
\hoge\fuga\6

対象フォルダ内には「ソフト」「テスト」という2のフォルダが存在している

実行結果
$sharedFilesの中身

array (size=2) 0 => (ソフトフォルダの情報) array (size=0) empty 1 => (テストフォルダの情報) array (size=4) 'FILE_TYPE' => string 'dir' (length=3) 'FILE_NM' => string 'eスト' (length=7) 'PARENT_DIR' => string '\\hoge\fuga\6' (length=17) 'SUB_FILES' => array (size=0) empty

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答1

0

ベストアンサー

そのフォルダ内のファイルおよびフォルダを列挙する機能

Splを利用する方法や、OSコマンドを利用する方法など様々なケースが想定されます。実際の実装はどうなっているのか、コードを晒してください。

pathinfo() 、および basename() においては PHP7 で日本語ファイル名に関するバグが修正されました。以前のバージョンにおいては正しく動作しません。
「正しく動作しない」ことを前提に設計するしかありません。「列挙」したのちにその値がどう利用されるのかわかりませんので、要件に合わせて設計を見直すのが吉かと思います。


当方、Windows 環境がないため、以下のコードの結果どうなるかをコメントください。

php

1function getSharedFiles($path){ 2 setlocale(LC_ALL, 'ja_JP.UTF-8'); 3 $search = str_replace(DS, '/', rtrim($path, DS) . DS . '*'); //DSはDIRECTORY_SEPARATOR 4 $files = glob($search); 5 $info = array (); 6 foreach($files as $file) { 7 //まずはこれで確認しては? 8 var_dump($file); 9 var_dump(mb_convert_encoding($file, 'UTF-8', 'SJIS-win')); 10 } 11 return $info; 12}

投稿2016/01/07 06:16

編集2016/01/07 07:58
退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

orange0190

2016/01/07 06:46

回答ありがとうございます。 現在のコードを追記しました。 現在は「列挙」した後、表示しそれらのファイルをクリックすることによって、ダウンロードできるようにしようと考えています。 また、共有先のフォルダはお客様が用意し、基本何でも追加できるものとなっているので、日本語ファイル名の対応は必須となります。
退会済みユーザー

退会済みユーザー

2016/01/07 07:06 編集

表示のために mb_convert_encoding は必須ですが、ファイルを引っ張ってくるためには エンコードしちゃダメですよ。それに、 sjis ではなく sjis-win です。utf-8 , utf8 で表記がぶれているし。
orange0190

2016/01/07 07:13

ご指摘ありがとうございます。 >sjis ではなく sjis-win です。utf-8 , utf8 で表記がぶれている こちらはコードの記述ミスです。修正しました。 >ファイルを引っ張ってくるためには エンコードしちゃダメ こちらは行っていないと思いますが、どこがエンコードしてはいけない箇所になりますでしょうか。
退会済みユーザー

退会済みユーザー

2016/01/07 07:17

提示のコードの中ではないです。 ダウンロードするときに、readfile だったり、file_get_contents に渡すパスのことです。
orange0190

2016/01/07 07:21

>提示のコードの中ではないです。 >ダウンロードするときに、readfile だったり、file_get_contents に渡すパスのことです。 分かりました。 最後に確認なのですが、現在の私の環境では、ファイル名にダメ文字が含まれている場合に、fileinfo()等の情報を正しく取得することはできないのでしょうか?
退会済みユーザー

退会済みユーザー

2016/01/07 07:23

具体的に「どういうファイル名のときに」「どのような結果になるか」を補足してください。
orange0190

2016/01/07 07:33

具体的な実行結果を追記しました。 「ソフト」というフォルダに関しては、フォルダともファイルとも判定されずに困っています。 また、「テスト」というフォルダに関して、ファイル名がおかしくなっているのは、仰っていたとおりPHPのバグなのかなと考えています。
退会済みユーザー

退会済みユーザー

2016/01/07 07:39

> 仰っていたとおりPHPのバグなのかな 既知のバグです。すでにコミュニティで共有されています。
orange0190

2016/01/07 08:04

提示していただいたコードの実行結果です。 string '\\hoge\fuga\6\�\�t�g' (length=24) string '\\hoge\fuga\6\ソフト' (length=27) string '\\hoge\fuga\6\�e�X�g' (length=24) string '\\hoge\fuga\6\テスト' (length=27)
退会済みユーザー

退会済みユーザー

2016/01/07 08:23

$file には問題なくセットされているようですね。pathinfo 相当の機能を自前で実装しちゃえば、対応できるのでは?
orange0190

2016/01/07 08:31

>pathinfo 相当の機能を自前で実装 そうですね。自前で実装してしまえば、pathinfoに関しては問題ないですね。 そうしようと思います。 ただ、フォルダ名が「ソフト」となっている場合には、ファイルの種類の判定すらできない状態です。 原因はSJISのダメ文字(ソフトの「ソ」)だと考えているのですが、こちらは回避方法はございますでしょうか?
退会済みユーザー

退会済みユーザー

2016/01/07 08:39 編集

> 原因はSJISのダメ文字(ソフトの「ソ」)だと考えているのですが、こちらは回避方法はございますでしょうか? いいえ、違います。あくまで pathinfo のバグであって、いわゆるエンコードの問題とは切り離して考えてください。 > ファイルの種類の判定すらできない is_dir , is_file があるでしょう。 なんか、混乱して思考が凝り固まってませんか???
orange0190

2016/01/07 08:40

>あくまで pathinfo のバグ is_file()およびis_dir()がfalseになるのも、pathinfoのバグが原因ということでしょうか?
退会済みユーザー

退会済みユーザー

2016/01/07 08:50 編集

> is_file()およびis_dir()がfalseになる まさか、エンコードされたパスを渡してません? ああ、そうか… \�\�t�g' (length=24) 本来 basename の部分に \ が入ってしまうのが原因でしょうね。
orange0190

2016/01/07 08:49

>まさか、エンコードされたパスを渡してません? エンコードはファイル名やパスを取得しているときに行っています。 ですので、 is_file()およびis_dir()を実行している時点ではエンコードをしていません。 実行結果を少々補足しましたが、実行結果の配列の1番目が「ソフトフォルダ」の情報、2番目が「テストフォルダ」の情報となります。
退会済みユーザー

退会済みユーザー

2016/01/07 08:54 編集

\�\�t�g' (length=24) 本来 basename の部分に \ が入ってしまうのが原因でしょうね。 RecursiveIteratorIterator() と RecursiveDirectoryIterator() を使った方法 http://php-archive.net/php/file-tree/ これを試しても、ダメかもしれませんが一考かも。
退会済みユーザー

退会済みユーザー

2016/01/07 09:10

別の方法 Windows 側に FTP サーバーを立て、phpからはFTPプロトコルでアクセスするという方法もあるかな…
orange0190

2016/01/07 09:14

情報を教えていただきありがとうございます。 しかし、せっかく教えて頂いたのですが、残念ながらダメでした。 SplFileInfoオブジェクトで情報を取得するか思うのですが、isFile()およびisDir()はともにfalseを返し、getType()ではRuntimeExceptionとなってしまいました。
退会済みユーザー

退会済みユーザー

2016/01/07 09:19

PHPでなんとかするというアプローチは無理でしょうね。 先に行ったように、設計から見直しが必要だと思います。誤解しているようですが「日本語ファイルを作成してはいけない」ということではありません。「日本語ファイルであっても正しく動作する」インフラを含めた設計の見直しです。
orange0190

2016/01/07 09:33

>PHPでなんとかするというアプローチは無理 ということは分かりました。 それでは、仰る通り >「日本語ファイルであっても正しく動作する」インフラを含めた設計の見直し を行うことにします。 ご協力ありがとうございました。 これで解決とさせていただきます。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.51%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問