Webサイトであれば、アップロードしたファイルをストレージに保存し、ファイルのパスまたはURLをデータベースで管理するといったケースはよく行われるだろう。
とあるBlogエンティティに画像のファイルパスを複数持っているとする。例えばこんな感じ。
- blog_title
- blog_image_path_1
- blog_image_path_2
これを愚直にこのようなフォームにしてしまうとする。
<?= $this->Form->create($blog, ['enctype' => 'multipart/form-data']) ?>
<?= $this->Form->text('blog_title') ?>
<?= $this->Form->file('blog_image_path_1') ?>
<?= $this->Form->file('blog_image_path_2') ?>
<?= $this->Form->end() ?>
このフォームのリクエストを受け取って
$blog = $this->Blogs->get($id); // DBから取得
$blog = $this->Blogs->patchEntity($blog, $this->request->getData()); // 画面の入力を反映
$this->Blogs->save($blog); // DBに保存
としてしまうのは、2つのファイルが両方とも必須項目であればともかく、片方だけ変更するといったケースでは、指定しなかった方のファイルパスがブランクになってしまって都合が悪い。
そういう場合は、イレギュラーな対応かもしれないが、直接コピーすることをせずに、エンティティにはない項目を一時的に使用して、最終的にエンティティに格納するようにする。そもそもファイルアップロードフィールドには初期値は設定できないのだ。
<?= $this->Form->create($blog, ['enctype' => 'multipart/form-data']) ?>
<?= $this->Form->text('blog_title') ?>
<?= $this->Form->file('blog_image_file_1') ?>
<?= $this->Form->file('blog_image_file_2') ?>
<?= $this->Form->end() ?>
$blog = $this->Blogs->get($id);
$blog = $this->Blogs->patchEntity($blog, $this->request->getData());
// 1つ目のファイルが指定されていたら反映
if (isset($this->request->getData('blog_image_file_1')['name'])) {
$blog->blog_image_path_1 = $this->request->getData('blog_image_file_1')['name'];
}
// 2つ目のファイルが指定されていたら反映
if (isset($this->request->getData('blog_image_file_2')['name'])) {
$blog->blog_image_path_2 = $this->request->getData('blog_image_file_2')['name'];
}
$this->Blogs->save($blog);
尚、入力チェックや、基本ディレクトリ名の合成などは省略しているので、各々の状況に合わせてアレンジして欲しい。
ファイルアップロードフォームから渡ってくる項目の詳細については以下を参照のこと。
https://secure.php.net/manual/ja/features.file-upload.post-method.php