PHPのリネーム関数は上書きする
2020年06月25日 プログラミングTIPS
先日の「ブログのデザインとシステムをリニューアルしました」の時に、「iPhone(iOS6以上)対応画像アップロードプログラム」も自分用に改良したことを書きました。スマホから複数枚の画像をアップロードできるように改良し、画像を削除できる機能も付けました。その後、画像ファイルの名前をリネームできる機能も付けました。この「リネーム」の処理が少し危なかったので、メモとして残しておきます。
PHPの関数では、アップロードされたファイルを移動するときは「move_uploaded_file」関数を使います。一方、既存のファイルを移動するときは「rename」関数を使います。move_uploaded_file()とrename()、この統一感のない関数名がPHPの面白いところだななどと思っていたら、ちょっとした罠が。
自分でファイルのリネーム処理を実装したとき、当初は「自分で名前を変更するわけだから、同じ名前を付けてしまうことはないだろう」などと考えていました。実際に画像ファイルのリネームをやってみたところ、変更後の名前をコピペで貼り付け、そのあと連番を付けようとしていたのに、コピペの段階でリターンキーを押してしまいそうになりました。そのままリターンキーを押していたら、画像を上書きして、元の画像ファイルが上書きされて消失していたというわけです。実際に上書きしてしまったわけではありませんが、このままでは危ないので、確認処理を追加しました。以下のような感じです。
PHPの関数では、アップロードされたファイルを移動するときは「move_uploaded_file」関数を使います。一方、既存のファイルを移動するときは「rename」関数を使います。move_uploaded_file()とrename()、この統一感のない関数名がPHPの面白いところだななどと思っていたら、ちょっとした罠が。
rename ( string $oldname , string $newname [, resource $context ] ) : bool「ファイル名の変更かつ newname が存在する場合、上書きされます」という仕様です。特に警告もなく、いきなり上書きしちゃうんですね。以下のページでも話題になっていました。
oldname を newname にリネームし、必要ならディレクトリを移動しようと試みます。 ファイル名の変更かつ newname が存在する場合、上書きされます。 ディレクトリ名の変更かつ newname が存在する場合、 この関数は警告を発します。
自分でファイルのリネーム処理を実装したとき、当初は「自分で名前を変更するわけだから、同じ名前を付けてしまうことはないだろう」などと考えていました。実際に画像ファイルのリネームをやってみたところ、変更後の名前をコピペで貼り付け、そのあと連番を付けようとしていたのに、コピペの段階でリターンキーを押してしまいそうになりました。そのままリターンキーを押していたら、画像を上書きして、元の画像ファイルが上書きされて消失していたというわけです。実際に上書きしてしまったわけではありませんが、このままでは危ないので、確認処理を追加しました。以下のような感じです。
//同じ名前のファイルがあるかチェック
if( file_exists($newname) ){
//存在する場合
echo "同じ名前のファイルがあります!リネームできません!";
}else{
//リネーム処理
}