【cakephp3】DB登録処理がうまくできない(newentityした際、入力フォームのセレクトボックスの値が取得できない)
解決済
回答 1
投稿
- 評価
- クリップ 0
- VIEW 5,795
前提・実現したいこと
cakephp3 勉強中の初心者です。
入力フォームからデータを取得し、DBへの登録処理(register)を作成しているのですが、エラーとなりうまくいきません。
どこが誤っていてエラーとなっているのか、どのように実現すればいいのかご教示ください。よろしくお願いいたします。
自分で調べた限りでは、コントローラ内のregister()でnewEntityした際に、$memberに入力フォームのjoinyearの値が設定されていないことまではわかったのですが、なぜ値が設定されていないのか、そもそもやり方がおかしいのか、理解できていない状況です。
何卒、ご教示いただけますようよろしくお願いいたします。
コントローラー
<?php
namespace App\Controller;
//use Cake\Event\Event;
use Cake\ORM\Query;
use \Exception;
use Cake\Log\Log;
use Cake\Datasource\ConnectionManager;
class MembersController extends AppController{
~~~~ 中略 ~~~~
public function register(){
if ($this->request->is('post')) {
$member = $this->Members->newEntity($this->request->data);
if($this->Members->save($member)){
$this->Flash->success('データの登録が完了しました');
return $this->redirect('\members\index');//一覧へ戻る
}else{
$this->Flash->error('データの登録に失敗しました');
}
}
$this->set('entity',$this->Members->newEntity());
}
~~~~ 中略 ~~~~
}
ビュー
<h1>Edit screen</h1>
<?=$this->Form->create($entity,['type'=>'post','url'=>['action'=>'register']]) ?>
<fieldset>
<?=$this->Form->input('familyname',['type'=>'text'])?>
<?=$this->Form->input('firstname',['type'=>'text'])?>
<?=$this->Form->input('sex',
[
"type" => "radio",
"options" => [ "1" => "男性",
"2" => "女性"]
]
);
?>
<?=$this->Form->input('dept',
[
"type" => "radio",
"options" => [ "1" => "総務部",
"2" => "営業部"]
]
);
?>
<?=$this->Form->input('joinyear',['type'=>'year',"minYear" => 2000,"maxYear"=>date( "Y" ) ])?>
<?=$this->Form->input('profile',
[
"type" => "textarea",
"label" => "profile"
]
);
?>
</fieldset>
<?=$this->Form->button("register") ?>
<?=$this->Form->end()?>
テーブル関係
<?php
namespace App\Model\Table;
use Cake\ORM\Query;
use Cake\ORM\RulesChecker;
use Cake\ORM\Table;
use Cake\Validation\Validator;
class MembersTable extends Table {
public function validationDefault(Validator $validator)
{
$validator
//->allowEmpty('id')
->notEmpty('id')
->integer('id');
$validator
->notEmpty('familyname')
->ascii('familyname')
->minLength('familyname',2,'2文字以上入力ください。')
->maxLength('familyname',10,'10文字以下で入力ください。');
$validator
->notEmpty('firstname')
->ascii('firstname')
->minLength('firstname',2,'2文字以上入力ください。')
->maxLength('firstname',10,'10文字以下で入力ください。');
$validator
->notEmpty('sex')
->integer('sex')
->inlist('sex',['1','2']);
$validator
->notEmpty('dept')
->integer('dept')
->inlist('dept',['1','2']);
$validator
->notEmpty('joinyear');
$validator
->notEmpty('profile')
->ascii('profile')
->minLength('profile',10,'10文字以上入力ください。')
->maxLength('profile',50,'50文字以下で入力ください。');
return $validator;
}
}
<?php
namespace App\Model\Entity;
use Cake\ORM\Entity;
class Member extends Entity {
protected $_accessible = [
'*' => true,
'id' => false
];
}
補足情報(言語/FW/ツール等のバージョンなど)
cakePHP3.4.6
PHP5.6.30
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
checkベストアンサー
+1
まず、バリデーションエラーになった場合、エラー内容がフォームに表示されるように、$memberをentityにセットした方がいいと思います。
public function register(){
if ($this->request->is('post')) {
$member = $this->Members->newEntity($this->request->data);
if($this->Members->save($member)){
$this->Flash->success('データの登録が完了しました');
return $this->redirect('\members\index');//一覧へ戻る
}else{
$this->Flash->error('データの登録に失敗しました');
}
$this->set('entity',$member);
} else {
$this->set('entity',$this->Members->newEntity());
}
}
次に、バリデーションの設定ですが、 ->notEmpty('id')
は不要だと思います。フォームにidを設定する欄がない確実にエラーになると思います。自動採番ならバリデートの必要はありません。
※他にもバリデーションエラーがあれば調整してください。よくわからないのであれば、bakeコマンドを使ってコードを自動生成してみると参考になると思います。
投稿
-
回答の評価を上げる
以下のような回答は評価を上げましょう
- 正しい回答
- わかりやすい回答
- ためになる回答
評価が高い回答ほどページの上位に表示されます。
-
回答の評価を下げる
下記のような回答は推奨されていません。
- 間違っている回答
- 質問の回答になっていない投稿
- スパムや攻撃的な表現を用いた投稿
評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.37%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
2017/05/23 12:11
バリデーションエラー時の動きが考慮されていなかったため、
ご指摘いただいた通り、修正しました。
エラー時の対処はこれで問題ないと考えているのですが、正常系の動き(DBへの登録)がうまくいきません。以下のSQLエラーが発生してしまいます。
Error: SQLSTATE[HY000]: General error: 1366 Incorrect integer value: '' for column 'joinyear' at row 1
If you are using SQL keywords as table column names, you can enable identifier quoting for your database connection in config/app.php.
実行された以下のSQLを見ると、joinyearの設定値がないため、エラーとなっているのかなと考えています。
INSERT INTO members (familyname, firstname, sex, dept, joinyear, profile)
VALUES ('shimizu', 'masaki', 2, 2, '', 'registregist')
調査したところ、コントローラのregister()内で、newEntityした際($member = $this->Members->newEntity($this->request->data);)に、$memberにjoinyearが設定されていませんでした。
また、入力フォームから値が取得できているか、$this->request->dataを確認したところ、以下のように取得できているようでした。
~略~
[dept] => 1
[joinyear] => Array ( [year] => 2000 )
~略~
※但し、他フィールドと異なり、データが存在する階層が異なる。
以上のことから、newEntity時にデータを弾いてしまっているとわかったのですが、対処方法がよくわからない状況です。
引き続きの質問となってしまい、誠に恐縮ですが、ご教示いただけますでしょうか。
2017/05/23 12:17
2017/05/23 12:38
DBはmysqlを利用してまして、YEAR型で設定しています。
↓↓↓↓↓↓desc の結果(一部)↓↓↓↓↓↓
+------------+--------------+------+-----+---------+----------------+
| Field | Type | Null | Key | Default | Extra |
+------------+--------------+------+-----+---------+----------------+
| joinyear | year(4) | NO | | NULL | |
+------------+--------------+------+-----+---------+----------------+
2017/05/23 12:46 編集
試しにnewEntity前に以下のようなコードを追記すると上手くいきますか?
$this->request->data['joinyear'] = $this->request->data['joinyear']['year'];
2017/05/23 12:52
<?=$this->Form->input('joinyear',['type'=>'year', 'name' => 'joinyear', "minYear" => 2000,"maxYear"=>date( "Y" ) ])?>
2017/05/23 13:40
それぞれ試してみました。
先にご連絡いただいた配列を直す方法は、DBの更新までうまく処理できました。
追加したコードで、joinyearの配列を直せたことも確認しています。
次にテンプレート側でnameを指定する方法ですが、こちらはエラーとなりました。
エラーのメッセージ等、これまでと同じで、joinyearは、 [joinyear] => Array ( [year] => 2000 )として取得されるため、newEntity時にデータを弾いてしまっています。
いろいろご丁寧に教えてくださり、誠にありがとうございました。
何故、このような仕様になっているのか等、若干の疑問は残りますが、
今回は、配列を直す案で乗り切ろうと思います。
また、自己解決が難しいような事象が発生しましたら、当サイトへ書き込ませていただきますので、
その際は、何卒、よろしくお願いいたします。