CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll
2017/03/10
CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll
CakePHPでレコードを更新する方法・概要
CakePHPは非常に便利で、主キーをもとにレコードを更新する場合は、下記の記述方法で簡単に処理できます。
1 |
$this->テーブル名->save($this->request->data) |
でも、主キー以外でレコードを更新する必要が出てき調べましたので、その報告です。
上記の saveの処理を下記の記述方法に変更することで更新処理が行えるようになります。
1 2 3 |
$this->テーブル名->updateAll( array ( '更新するカラム' => 変更の値 ), array ( '条件のカラム' => 条件の値 ) ) |
CakePHPでレコードを更新する方法・具体例
ここでは下記の「comments」テーブルを利用し、bakeで作成したプログラムソースを改変してサンプルプログラムを作成します。
通常の更新は editで行い、主キー(ID)以外の更新のための画面を edit2として作成します。
まず、サンプルで使ったテーブルの構築です。
下記の SQLを使ってください。
——————
1 2 3 4 5 6 7 8 9 |
CREATE TABLE IF NOT EXISTS `comments` ( `id` int(8) NOT NULL AUTO_INCREMENT, `post_id` int(8) NOT NULL, `sec_code` char(4) DEFAULT NULL, `list` varchar(255) DEFAULT NULL, `created` datetime DEFAULT NULL, `modified` datetime DEFAULT NULL, PRIMARY KEY (`id`) ) ENGINE=InnoDB DEFAULT CHARSET=utf8 AUTO_INCREMENT=8 ; |
——————
続けて、データは自身で入れていただければいいのですが、面倒な方用にサンプルです。
——————
1 2 3 4 5 6 7 8 |
INSERT INTO `comments` (`id`, `post_id`, `sec_code`, `list`, `created`, `modified`) VALUES (1, 12, '1234', '12-1234のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (2, 23, '2345', '23-2345のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (3, 34, '3456', '34-3456のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (4, 45, '4567', '45-4567のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (5, 56, '5678', '56-5678のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (6, 67, '6789', '67-6789のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'), (7, 78, '7890', '78-7890のリスト', '2014-04-01 12:00:00', '2014-04-01 12:00:00'); |
——————
このテーブルをもとに、Bakeコマンドで Controller、Model、Viewを作成してください。
続けて修正対応を行います。
Modelは、全く修正しません。
Viewは、「edit.ctp」をもとに「edit2.ctp」をコピーして作成します。ファイル名は違いますが、中身は全く同じです。画面を表示した際に違いが分かるように何か追加で記述してもいいでしょう。
また、index.ctpから「edit2.ctp」にリンクを貼ります。23行目付近の「edit」へのリンクの行をコピーし「edit2」に変更するだけです。(面倒でなければ、URL直打ちでも問題ありません。)
修正のメインは、Controllerです。
/app/Controller/CommentsController.php
———————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
public function edit($id = null) { if (!$this->Comment->exists($id)) { throw new NotFoundException(__('Invalid comment')); } if ($this->request->is('post') || $this->request->is('put')) { if ($this->Comment->save($this->request->data)) { $this->Session->setFlash(__('The comment has been saved')); $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The comment could not be saved. Please, try again.')); } } else { $options = array('conditions' => array('Comment.' . $this->Comment->primaryKey => $id)); $this->request->data = $this->Comment->find('first', $options); } } |
———————————
上記が Bakeで作成される「edit」関数の部分です。ここは、主キー(ID)をキーとして更新を行う処理です。
その部分をコピーして作成したものが下記の edit2の関数です。
上記の 6行目を 6行目~8行目に変更しています。
実は、変更する部分はここだけで済みます。
ここでは、post_idの値が同じレコードを変更対象とし、sec_codeのカラムの値を変更する指定になっています。
ちなみに、「$this->request->data[‘Comment’][‘sec_code’]」が「Comment」の画面から入力があった「sec_code」という項目の入力を取得しているものになります。
PHPの取得処理で記述すると「$_POST[‘sec_code’]」といったところでしょうか。
/app/Controller/CommentsController.php
———————————
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
public function edit2($id = null) { if (!$this->Comment->exists($id)) { throw new NotFoundException(__('Invalid comment')); } if ($this->request->is('post') || $this->request->is('put')) { if ( $this->Comment->updateAll( array('Comment.sec_code' => $this->request->data['Comment']['sec_code']), array('Comment.post_id' => $this->request->data['Comment']['post_id']))){ $this->Session->setFlash(__('The comment has been saved(edit2)')); $this->redirect(array('action' => 'index')); } else { $this->Session->setFlash(__('The comment could not be saved. Please, try again.')); } } else { $options = array('conditions' => array('Comment.' . $this->Comment->primaryKey => $id)); $this->request->data = $this->Comment->find('first', $options); } } |
———————————
続いて、更新するレコードを指定する条件を複数指定することもできます。
下記は、post_idと listの値が合致するレコードを更新する設定になっています。
arrayの値を追加していくことで検索条件の項目を増やしていくことができます。
———————————
1 2 3 4 |
if ( $this->Comment->updateAll( array('Comment.sec_code' => $this->request->data['Comment']['sec_code']), array('Comment.post_id' => $this->request->data['Comment']['post_id'], 'Comment.list' => $this->request->data['Comment']['list']))){ |
———————————
続いて、更新するカラムを増やすこともできます。
下記は、sec_code、listのカラムの値を更新する指定になっています。
ちなみに、なぜだかわかりませんが、上記の様にレコードを指定する条件の方は「$this->request->data[‘Comment’][‘list’]」をクォートで囲まなくてもエラーにはなりませんでしたが、更新するカラムの値の方はシングルクォートで囲まないとエラーになってしまいましたので、下記の様にシングルクォートで囲むよう指定を行います。
これは、sec_codeは intのために数値しか入りませんが、listは varcharのためテキスト文字が入ったことでエラーになったものと思われます。
今後のトラブル回避のためには、上記の条件指定の方もシングルクォートで囲む方がいいでしょう。
———————————
1 2 3 4 |
if ( $this->Comment->updateAll( array('Comment.sec_code' => $this->request->data['Comment']['sec_code']), 'Comment.list' => "'" . $this->request->data['Comment']['list'] . "'"), array('Comment.post_id' => $this->request->data['Comment']['post_id']))){ |
———————————
また、下記のように、modifiedが「2014-04-01 00:00:00」の様に複数の項目に合致するように指定した場合は、複数のレコードが一気に更新されます。
———————————
1 2 3 |
if ( $this->Comment->updateAll( array('Comment.sec_code' => '5'), array('Comment.modified' => '2014-04-01 00:00:00'))){ |
———————————
また、条件の指定は、下記の様に不等号、等号などの条件を指定することも可能です。
———————————
1 2 3 |
if ( $this->Comment->updateAll( array('Comment.sec_code' => '5'), array('Comment.post_id >' => 50))){ |
———————————
追記・updateAllは自前でサニタイズをする必要がある
さらにいろいろと調べている過程で、updateAllは、自前でエスケープする必要があることが分かりました。
上記の説明で、下記の様にクォート囲む必要があると書きましたが、それだけでなくエスケープ処理も自前で行う必要があるとのことですので、下記の様にサニタイズをする必要があります。
そうしないと、入力されたデータの中に「’」などが入っているとエラーになってしまいます。
———————————
1 |
'Comment.list' => "'" . Sanitize::escape( $this->request->data['Comment']['list'] ) . "'"), |
———————————
また、Sanitize::escape()を使う際には、それを呼び出しておく必要がありますので、Controllerの上の方に「App::import(‘Utility’, ‘Sanitize’);」を追記しておきましょう。
サニタイズのことについて、下記のサイトが参考になりました。
http://blog.xao.jp/blog/cakephp/postscript-of-entry-about-model-updateall/
GoogleAdwords
GoogleAdwords
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
CakePHP3のビューで受取ったテーブルのオブジェクトを連想配列に変換する方法
コントローラーからビューに送ったテーブルのオブジェクトを連想配列に変換し、ビューの中で自由に使えるようにするメソッド「toArray()」の解説。連想配列に変換できれば利用度アップ!
-
CakePHP3で値を入力直後にバリデーションする方法解説
CakePHP3でバリデーションの実行を保存する時から入力情報を受け取るときに変更する処理の解説。CakePHP3ではnewEntity()の処理でバリデートするため1行追加で対応可能。
-
CakePHP3ログファイルへの出力・$this->log()、独自ログへの出力方法の解説
コントロール、モデルの変数の中身を見るときはログに出力する方法が有効です。$this->log()を利用すると変数だけじゃなく、連想配列、オブジェクトも簡単にログ出力ができます。
-
CakePHP4で定数の設定と呼び出し方法の解説(defineとConfigure)
CakePHP4で定数を設定、使用する方法を解説。定数定義はdefineとConfigureを使用する方法を解説。また、bootstrap.phpに直接記述する方法と別のファイルにする方法を解説。
-
CakePHP3、CakePHP4のdatetime型カラムの日時の扱い。秒まで表示する方法
CakePHP3の日時カラムで秒まで扱う場合はdate()、strtotime()関数ではうまくいかない。CakePHP3であらかじめ用意された「i18nFormat()」を使用する。
-
CakePHP 2.3で PDFを作成する方法を調査「mpdf」「TCPDF」「FPDF」
CakePHPで PDFを編集、出力するには「mpdf」「TCPDF」「FPDF」といったプラグインがあり、使い勝手を比較検討しました。TCPDFが一番良さそうでした。
-
CakePHP4でロギングスコープやログレベルを使用してログを出し分ける方法を解説
CakePHPのログ出力方法の解説。app.phpにログ設定をし、スコープやレベルを指定してログ出力を振り分ける方法、CakePHP4で配列出力にはvar_exportが必要なことなどを解説。
-
CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHPの検索プラグイン Search Pluginの検索処理の中で入力エリア一つで複数の項目を同時に検索する方法を解説。
-
CakePHP3でPHPExcelを使ってエクセルファイルを生成、出力する方法
CakePHP3でPHPExcelを利用してエクセルを編集、出力するサンプルソース+解説。PHPExcelのインストール方法の解説からファイル保存とダウンロードの方法なども解説。
-
CakePHP3にWYSIWYGエディタのCKEditor4を設置、カスタマイズ方法を解説
WYSIWYGエディタであるCKEditor4をCDNを利用して簡単にCakePHP3に導入する方法とカスタマイズする方法を解説。CakePHP3にはページごとの振り分けを行うブロック化を利用する。