エス技研

WordPress、CakePHP、PHP、baserCMSなどの Web系システムを中心に情報を提供します!


CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll

      2017/03/10

CakePHP 2.3 主キー(ID)以外のキーで更新方法 updateAll

 

CakePHPでレコードを更新する方法・概要

 
CakePHPは非常に便利で、主キーをもとにレコードを更新する場合は、下記の記述方法で簡単に処理できます。

$this->テーブル名->save($this->request->data)

 
でも、主キー以外でレコードを更新する必要が出てき調べましたので、その報告です。
 
上記の saveの処理を下記の記述方法に変更することで更新処理が行えるようになります。
 

$this->テーブル名->updateAll(
       array ( '更新するカラム' => 変更の値 ),
       array ( '条件のカラム'   => 条件の値 ) )

 
 
[amazonjs asin=”4774153249″ locale=”JP” title=”CakePHP2 実践入門 (WEB+DB PRESS plus)”]
 

CakePHPでレコードを更新する方法・具体例

 
ここでは下記の「comments」テーブルを利用し、bakeで作成したプログラムソースを改変してサンプルプログラムを作成します。
通常の更新は editで行い、主キー(ID)以外の更新のための画面を edit2として作成します。
 
 
まず、サンプルで使ったテーブルの構築です。
下記の SQLを使ってください。
 
——————

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 ;

——————
 
続けて、データは自身で入れていただければいいのですが、面倒な方用にサンプルです。
 
——————

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
———————————

  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
———————————

  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の値を追加していくことで検索条件の項目を増やしていくことができます。
 
———————————

      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のためテキスト文字が入ったことでエラーになったものと思われます。
今後のトラブル回避のためには、上記の条件指定の方もシングルクォートで囲む方がいいでしょう。
 
———————————

      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」の様に複数の項目に合致するように指定した場合は、複数のレコードが一気に更新されます。
 
———————————

      if ( $this->Comment->updateAll(
                      array('Comment.sec_code' => '5'),
                      array('Comment.modified' => '2014-04-01 00:00:00'))){

———————————
 
また、条件の指定は、下記の様に不等号、等号などの条件を指定することも可能です。
 
———————————

      if ( $this->Comment->updateAll(
                      array('Comment.sec_code' => '5'),
                      array('Comment.post_id >' => 50))){

———————————
 
 

追記・updateAllは自前でサニタイズをする必要がある

 
さらにいろいろと調べている過程で、updateAllは、自前でエスケープする必要があることが分かりました。
上記の説明で、下記の様にクォート囲む必要があると書きましたが、それだけでなくエスケープ処理も自前で行う必要があるとのことですので、下記の様にサニタイズをする必要があります。
そうしないと、入力されたデータの中に「’」などが入っているとエラーになってしまいます。
 
———————————

                            '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/

 - CakePHP 3.x 4.x 5.x

最後までお読みいただきましてありがとうございます。
この記事が参考になったと思いましたらソーシャルメディアで共有していただけると嬉しいです!

Message

メールアドレスが公開されることはありません。 ※ が付いている欄は必須項目です

下記の空欄を埋めてください。 * Time limit is exhausted. Please reload CAPTCHA.

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)

※入力いただいたコメントは管理者の承認後に掲載されます。

  関連記事

CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説

CakePHP3でパンくずの指定方法の解説。2つのヘルパーがあるが簡単なHTMLヘルパーを使った方法を、実際の状況に合わせて3つのパターン(エレメント化、ブロック化)にして解説。

CakePHP2の検索Plugin CakeDC/Searchで重複を省くgroup by(distinct)の実装方法
CakePHP2の検索Plugin CakeDC/Searchで重複を省くgroup by(distinct)の実装方法

CakePHP2の検索プラグイン「CakeDC/Search」で、重複レコードを省くgroup by、distinctを使う方法についての解説。設定する場所はpaginatorの条件とするので、find()関数と同じ。

getParam('action')で取得するアクション名は別関数に移動しても不変
getParam('action')で取得するアクション名は別関数に移動しても不変

CakePHP4系、5系では「getParam()」で処理中のアクション名を取得できる。そのアクションから別関数を呼び出してた関数でアクション名を調べたが同一の名称だった。

CakePHP 2.3で PDFを作成する方法を調査「mpdf」「TCPDF」「FPDF」

CakePHPで PDFを編集、出力するには「mpdf」「TCPDF」「FPDF」といったプラグインがあり、使い勝手を比較検討しました。TCPDFが一番良さそうでした。

CakePHP3のメッセージ日本語化の設定(国際化と地域化の機能の使い方の解説)
CakePHP3のメッセージ日本語化の設定(国際化と地域化の機能の使い方の解説)

CakePHP3の英語のメッセージを日本語化(多言語化)する手順を解説。オリジナルのメッセージを作成する方法やプログラムで文言を追加する場合の対応なども解説。

CakePHP3の検索プラグイン「friendsofcake/search」の様々な検索の仕方の実装方法
CakePHP3の検索プラグイン「friendsofcake/search」の様々な検索の仕方の実装方法

CakePHP3で検索をするプラグイン「friendsofcake/search」の検索条件のカスタマイズ方法の解説。検索項目を増やしたり、以上、以下での検索や、チェックボックスによる検索の方法などを解説。

CakePHP 2.3でOn Duplicate Key構文を実装

CakePHPで On Duplicate Key構文を Queryを利用して実装する方法をサンプルソース付きで解説します。

CakePHP 2.3 Search Pluginで検索処理 その5入力項目に複数項目入力した場合の AND検索、OR検索

CakePHPの検索プラグイン Search Pluginの検索処理の中で複数項目を入力した場合の AND検索、OR検索についての解説です。

CakePHP3のバージョンを指定してインストールする詳細な手順を解説
CakePHP3、CakePHP4、CakePHP5のバージョンを指定してインストールする詳細な手順を解説

CakePHP3のバージョンを指定してインストールする方法を詳細解説。CakePHP3のインストールはComposerを使うため設定もほぼ自動で完了。データベースの接続情報を記載すればアプリ開発のベースが整う。

MySQL+CakePHPのdate型、datetime型項目は「2999-12-31」までしか扱えない
MySQL+CakePHPのdate型、datetime型項目は「2999-12-31」までしか扱えない

CakePHPの日付、日時の型であるdate型、datetime型の最大値は2999-12-31となっている。MySQLは9999年までなので違いがあるので注意が必要だ。