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
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!
関連記事
-
-
CakePHP4の数値項目は「like %10%」の部分一致検索(find select)はできない
CakePHP4でテーブルの数値項目に対してlike句を使用した部分一致検索を実行するとエラーが発生する。クリエービルダーの不具合だと思われ対処方法が分からない。
-
-
CakePHP4、5のnewEmptyEntityで作成したオブジェクトは空なのか、確認してみた
CakePHPでレコードを新規登録をする際にnewEmptyEntity()を使って空のEntityを作成するが、これのempty、is_nullなどのでの判定結果がtrueかfalseか確認してみた。
-
-
CakePHP3でアソシエーション先のカラムでデータをソートして取得したい
アソシエーション先のテーブルのカラムをキーにソートをしたデータを取得したい!ときの記述方法を解説。「orderAsc()」ではなく「contain()」の中にSort条件を記述する。
-
-
CakePHP 2.3 Search Pluginで検索処理 その3入力エリア一つで複数の項目を同時に検索する方法
CakePHPの検索プラグイン Search Pluginの検索処理の中で入力エリア一つで複数の項目を同時に検索する方法を解説。
-
-
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
CakePHP3のCookbookにあるブックマークチュートリアル。ここで紹介されているタグで検索する処理を検索プラグイン「friendsofcake/search」で実現する方法を解説しました。
-
-
CakePHP 2.x系 Viewでのコメントの記述方法など
CakePHPにおいて View、ctpファイルでコメントを記述する方法を解説。
-
-
CakePHP 2.3 コマンドラインからPHPのシェル実行の方法解説
CakePHP 2.3でコマンドラインから CakePHPで記述した処理を実行する方法を解説します。
-
-
CakePHP4、5で$_SERVERと同じようにURIを取得する「getUri()」の紹介
PHPでサーバ情報、環境情報を取得する際は「
$_SERVER」を利用するが、似たような情報をCakePHPの関数で取得する際は「getUri()」を使用する。取得出来る値は一致するものもあるが、違うものもあり便利な使い方もある。
-
-
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3で Insert … On Duplicate Key Update構文(upsert)を実行する方法を解説。バルク処理の方法も用意されているため大量処理の場合も対応可能。
-
-
CakePHP3、CakePHP4、CakePHP5のバージョンを指定してインストールする詳細な手順を解説
CakePHP3のバージョンを指定してインストールする方法を詳細解説。CakePHP3のインストールはComposerを使うため設定もほぼ自動で完了。データベースの接続情報を記載すればアプリ開発のベースが整う。