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
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
CakePHP 2.3 連携先のテーブルの項目で条件抽出する場合
アソシエーション(連携)している先のテーブルの項目で条件抽出する際の考え方と注意点をサンプルソースを用いて説明しています。
-
CakePHP3チュートリアルで日付と時刻のDateTimeでエラーが出たときの対処方法
CakePHP3のブックマークチュートリアルには記載ミスもあり、そのまま動かない個所もある。CakePHP3では namespaceを使うようになったので、classを呼び出すときに¥を追加する必要が!
-
CakePHP4のクリエビルダーを使用してOR条件をAND条件でつなぐSQL文を作る方法
CakePHP4のクリエビルダーを使って複数のOR条件をANDでつなぐSQL文を作成する方法を解説。OR条件を記述したwhere句を2つつなげて記述する。
-
CakePHP 2.3 コマンドラインからPHPのシェル実行の方法解説
CakePHP 2.3でコマンドラインから CakePHPで記述した処理を実行する方法を解説します。
-
CakePHP3でアソシエーション先のカラムでデータをソートして取得したい
アソシエーション先のテーブルのカラムをキーにソートをしたデータを取得したい!ときの記述方法を解説。「orderAsc()」ではなく「contain()」の中にSort条件を記述する。
-
CakePHP3でkeywords、DescriptionをHTMLヘルパーを使って設定する
CakePHP3のkeywordsとdescriptionを設定する方法の解説。CakePHP3にはmetaタグを編集するHTMLヘルパーが用意されているためそれを利用すればOK!ポイントはブロック化を有効にすること。
-
CakePHP3で /Layout/defult.ctpにある titleタグ、h1タグを編集する方法
CakePHP3でtitleタグ、h1タグのテキストをデフォルトから変更する方法を解説。テンプレートファイルに「$this->assign()」でテキストを指定して「/Layout/defult.ctp」で受け取る。
-
CakePHP3のプラグイン「CakeDC/Users」を日本語化・翻訳ファイルもダウンロード可
CakePHP3のユーザ管理、ログイン認証プラグインである「CakeDC/Users」のメッセージを日本語にする手順の解説とともに、日本語の翻訳ファイルを提供。ファイルを設置すれば日本語になる!
-
CakePHP3で他のテーブルのマスタテーブルからセレクトボックス(プルダウンリスト)を作る
他のテーブルのマスタのレコードからプルダウンリストを作成し、選択できるようにするサンプルプログラムと解説。ORMの設定によりデータベースの値を取得し、配列を作成し optionsに与える。
-
CakePHP4のメッセージ日本語化の設定(国際化と地域化の機能の使い方の解説)
CakePHP4の英語のメッセージを日本語化(多言語化)する手順を解説。オリジナルのメッセージを作成する方法やプログラムで文言を追加する場合の対応なども解説。