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のCakeDC/UsersのUserHelperでログアウトやreCAPTCHAをカスタマイズ
CakeDC謹製Usersプラグインの紹介。UserHelperを利用し、ログアウトのリンクや権限があるときのみ表示されるリンク、プロフィールページへのリンク、reCAPTCHAの設置方法などを解説。
-
CakePHP3で静的ページの作成は webrootか pagesを使う。トップページを参考に解説
CakePHP3で静的なページを設置する場合の方法(webrootとpagesとを活用する方法)を解説。pagesの解説はデフォルトのトップページがどう表示されているかを参考に解説。ルーティングの機能も。
-
CakePHP4のCSS、JavaScript、画像のブラウザへのキャッシュをコントロールする
CakePHP4、CakePHP3でブラウザにキャッシュさせる設定の解説。CSS、JavaScript、画像をブラウザにキャッシュさせるのか、定期的にリロードする設定にするのかの設定が可能。
-
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3でパンくずの指定方法の解説。2つのヘルパーがあるが簡単なHTMLヘルパーを使った方法を、実際の状況に合わせて3つのパターン(エレメント化、ブロック化)にして解説。
-
CakePHP3のCakeDC/Usersのバリデーションのカスタマイズ方法解説
CakeDC謹製Usersプラグインの紹介。Usersのカスタマイズとして入力項目のバリデーションの変更を、プラグインのファイルは触らずオーバーライドにより実装する方法を解説する。
-
CakePHP4のCakeDC/Usersの画面、メール本文テンプレートのカスタマイズ方法解説
CakeDC謹製Usersプラグインの紹介。ユーザ新規登録の流れを紹介しつつ、テンプレートファイル、設定情報ファイルの場所とそれらをカスタマイズする方法を説明します。
-
CakePHP3で保存前にバリデーション結果を取得する2つの方法
CakePHP3でデータベースに値を保存する前にバリデーションを行い、その結果によって処理を振り分ける方法について解説。「$topic->errors()」と「$topic->hasErrors()」の2つの方法がある。
-
CakePHP4の数値項目は「like %10%」の部分一致検索(find select)はできない
CakePHP4でテーブルの数値項目に対してlike句を使用した部分一致検索を実行するとエラーが発生する。クリエービルダーの不具合だと思われ対処方法が分からない。
-
CakePHP 2.3で確認画面付きのお問い合わせフォームの作り方
CakePHPで確認画面付きのお問い合わせフォーム、メールフォームの作り方をサンプルを提示しながら解説。
-
CakePHP 2.3 Search Pluginで検索処理 その6ORDER、sortソートの機能
CakePHPの検索プラグイン Search Pluginの検索処理の中で order、ソートについての解説です。