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

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

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

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

CakePHP

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

Q&A

解決済

1回答

799閲覧

【CakePHP3.6】複数ファイルアップロード時のバリデーション

bluezircon

総合スコア14

PHP

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

CakePHP

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

0グッド

0クリップ

投稿2018/10/16 10:18

CakePHP3.6で以下のような仕様の画面を実装しようとしています。

  • itemsテーブルに登録したitemに対して画像を任意で何枚でも登録できる
  • 画像はitem_imagesテーブルに保存される

item_images

iditem_idfilename
11item1_a.png
21item1_b.png
32item2_a.png

画像アップロードはJosegonzalez/Uploadというプラグインを用いて実装しました。
バリデーションを考えなければアップロード自体はできています。
(なおファイルの登録は任意で、1枚も選択しなくてもよく上限枚数もありません)

これに対して以下のバリデーションを実装したいです

  • アップロードする場合はpng形式のみ
  • 同じ商品に対して同じ名前の画像ファイルを登録できない(iItem_idとfilenameの重複を許可しない)

item編集のビューファイルで複数ファイルアップロードのフォーム

php

1// items/edit.ctp 2<?php echo $this->Form->control('item_images[].filename', [ 3 'type' => 'file', 4 'multiple', 5 ]);?>

コントローラー

php

1// itemsController.php 2 public function edit($id = null) 3 { 4 if(!$id){ 5 $item = $this->Items->newEntity(); 6 }else{ 7 $item = $this->Items->get($id, [ 8 'contain' => ['itemImages'] 9 ]); 10 } 11 if ($this->request->is(['patch', 'post', 'put'])) { 12 // ファイルを1つも選択しなかった時にitem_imagesに空のファイル名が保存されるのを防止 13 if(!$request['item_images'][0]['filename']['tmp_name']){ 14 unset($request['item_images']); 15 } 16 17 $item = $this->Items->patchEntity($item, $this->request->getData()); 18 $ret = $this->Items->save($item); 19 if ($ret) { 20 $this->Flash->success(__('詳細画面を保存しました。')); 21 22 return $this->redirect(['action' => 'index']); 23 } 24 $this->Flash->error(__('詳細画面の保存に失敗しました。再度お試しください。')); 25 } 26 }

テーブル

php

1// itemImagesTable.php 2 public function validationDefault(Validator $validator) 3 { 4 $validator->provider('upload', \Josegonzalez\Upload\Validation\DefaultValidation::class); 5 6 $validator 7 ->integer('id') 8 ->allowEmpty('id', 'create'); 9 10 $validator 11 ->allowEmpty('filename') 12 ->add('filename', 'fileSuccessfulWrite', [ 13 'rule' => 'isSuccessfulWrite', 14 'message' => 'アップロードできませんでした', 15 'provider' => 'upload', 16 ]) 17 ->add('filename', 'fileExtension', [ 18 'rule' => ['extension', ['png']], 19 'message' => 'アップロードできるファイル形式はpngのみです', 20 ]); 21 22 return $validator; 23 }

この状態で以下の問題があります

  1. エラーメッセージが出せない
  2. 同じ名前のファイルをアップできないバリデーションができていない

1についてはファイルを複数アップロードするとそれぞれに対してバリデーションが行われ、アップしたファイルそれぞれにエラーが返されるため、$this->Form->controlのデフォルトではエラーが表示されないようです。
「test3.jpg:アップロードできるファイル形式はpngのみです」
のような形でファイルごとにエラーを表示させる方法があればご教授頂けると幸いです。

2については

php

1// itemImagesTable.php 2 public function buildRules(RulesChecker $rules) 3 { 4 $rules->add($rules->isUnique(['item_id', 'filename'], '同名のファイルが既にアップロードされています。')); 5 return $rules; 6 }

のようにやれると公式ドキュメントにありましたが、おそらくプラグインを利用しているためリクエストデータ(画像2枚アップロード時)に

'item_images' => [ (int) 0 => [ 'filename' => [ 'tmp_name' => '/tmp/phpB5Wbc7', 'error' => (int) 0, 'name' => 'test.png', 'type' => 'image/png', 'size' => (int) 20498 ] ], (int) 1 => [ 'filename' => [ 'tmp_name' => '/tmp/phpV6Bnzb', 'error' => (int) 0, 'name' => 'test3.jpg', 'type' => 'image/jpeg', 'size' => (int) 20636 ] ] ]

のようにfilenameに配列が入ってしまい、これではうまくできないようでした。

上記2点についてどちらかでも構いませんので回答いただけるとありがたいです。

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

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

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

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

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

guest

回答1

0

自己解決

あまりスマートではない気がしますが自己解決しました。

1について
保存後コントローラー内で$item->errors()でエラーを取得しviewに渡し、テンプレートファイル内でforeachでエラーを出力

2について
itemImagesTable.phpのbuildRulesにisUniqueを使わずにitem_idと filenameの重複を判定する
独自のバリデーションを記述

php

1public function buildRules(){ 2 $rules->add( 3 function($data){ 4 $table = TableRegistry::get($this->_registryAlias); 5 $where = [ 6 'item_id'=>$data->iitem_id, 7 // ここで$data->filenameでfilenameが取れればisUniqueで行けた? 8 'filename'=>$data->filename['name'], 9 ]; 10 $query = $table->find()->select(['id'])->where($where)->first(); 11 return empty($query) ? true : false; 12 }, 13 'duplication', 14 [ 15 'errorField' => 'filename', 16 'message' => '同名のファイルが既にアップロードされています。' 17 ] 18 ); 19 return $rules; 20}

投稿2018/10/17 07:25

bluezircon

総合スコア14

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問