webプログラム制作の際に、様々な機能を盛り込むことがあります。
今回行った機能制作は「記事複製処理」です。
以前の記事を利用して、再投稿するための機能です。
テキストデータの複製は、元データからコピーするだけなので簡単にできます。
今回頭を悩ませたのは、「画像の複製」です。
記事再編集、再投稿目的であるため、元記事の画像と同じでも別画像として保存しなければいけません。
なぜならば、複製した記事を削除したときに、元記事の画像まで消えてはいけないためです。
そこでどうやれば実現できるかを考え調べました。
やりたいこと:PHPで画像を複製する
photoフォルダにある01.jpgをPHPだけで別名で複製保存をします。
おそらく、画像投稿処理と同等の手間がかかるのではないかと考えました。
画像投稿処理を構築した際に、GD関数(画像処理関数)を多数使用しました。
その経験から画像複製も同様にGD関数を多数使用して構築する必要があるのではないかと考えました。
実際はそうでもなかったです
少々身構えしながらやり方を調べたところ、たった1行で実現できることがわかりました。
少々拍子抜けな感じでしたが、PHPには簡単に画像を複製コピーできる関数が用意されていました。
それがこちらです。
copy("photo/01.jpg", "photo/01_copy.jpg");
MS-DOSを知っておられる方ならばイメージが付きやすいと思います。
MS-DOSのコピーコマンドと同じことがPHPでもできました。
copy(“コピー元パス+ファイル名”,”コピー先パス+ファイル名”);
コピー元と、コピー先を指定するだけでPHPで画像ファイルがコピーできました。
ここで疑問:コピー先ファイル名を自動で上書きされないファイル名にしたい
1行あれば画像ファイルをPHPで複製できることがわかりました。
ただこの方法には欠点があります。
同じ名称のままだと、常に上書きされてしまうという点です。
そこでファイル名称が同じにならない手軽な方法も考えてみました。
手堅い方法として、ランダム数値取得→重複確認、NGならば再度ランダム数値取得という方法があります。
ただ、構築が手間な場合は「タイムスタンプ」を利用します。
少なくとも年・月・日・時・分・秒を使用すれば、重複は1秒以内に限定されます。
これを何とかするために、「1秒未満の単位」を使用します。
1000分の1秒ならば、サーバーで連続コピーを実行しても同じにはなりません。
かなり高速なサーバーであれば、もしかしたら同じになることはあるかもしれませんが、通常のレンタルサーバーであれば、まず同じ値にはなりません。
参考までにそのやり方を以下に記載します。
// 現時点での1秒未満の値を取得する
list($micro, $Unixtime) = explode(" ", microtime());
// 小数点を削除し8桁にする
$micro_time = substr($micro, 2, 8);
// 年・月・日・時・分・秒に1秒未満の値を
名称としてセット
$file_name = date("Ymdhis") . "${micro_time}.jpg";
// 画像をコピーする
copy("photo/01.jpg", "photo/${file_name}");
ミリ単位の秒を組み込むことで秒単位まで同じ値になったとしても、完全に同じになる可能性は限りなく低くなります。
どうしても不安な場合は重複確認ループ方式併用で
ミリ単位秒でも同じ値が発生するかもしれない!
とご不安の場合は、この処理にループ重複確認処理を合わせれば、ほぼ重複名称を防ぐことができます。
なぜならば、重複確認処理を行っている間に1000分の1秒以上経過するためです。
「ほぼ」という表現なのは、重複確認処理をいれても「同時平行処理(マルチタスク)」であった場合に偶然一致があり得るためにです。
ただPHPで、CMSを構築するようなケースはマルチタスクでないため、これで重複を発生させることのほうが難題です。
いずれにせよ、2重、3重の対策を盛り込んでおくに越したことはありません。
何事も調べると大抵解決します
今回は、なまじGD関数(画像処理関数)を知っていたため、とても手間のかかる記述が必要になるものと思いましたが、ふたを開いてみると1行で事足りました。
課題に当たった時は、どうやって解決しようと思うものですが、案ずるよりも実践してみると、解決できるものです。
また本記事がお役に立てば幸いです。