エス技研

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


CakePHP3でレコードを保存(追加、更新、Insert、Update)する複数の方法を紹介

      2020/08/24

CakePHP3でレコードを保存(追加(Insert)、更新(Update))する方法を紹介

 

レコードを追加、更新する方法の前提

 
CakePHP3でレコードを追加する方法、更新する方法について解説します。
 
レコードを追加(Insert)する方法も、更新(Update)する方法も 1つではありませんので、複数の方法を紹介しつつ、活用方法や特徴を解説します。
 
 
なお、この記事は、下記の記事である「CSVファイルを読み込んでテーブルを更新する」と言う処理の実験をベースに記事を書いています。
CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説

そのため、一般的な「画面から入力された情報を保存する」という処理とは「foreach」文などが若干異なります。
その辺りについては、解説を加えてはいますが。
 
 
今回のプログラムで更新対象としているテーブルは以下の内容です。
 

 
https://book.cakephp.org/3/ja/tutorials-and-examples/bookmarks/intro.html
このテーブルは、上記の CookBookの「ブックマークチュートリアル」で利用したテーブルを流用したテーブルになります。
(記事の「bookmarks」テーブルを元に「flag_code」「flag」のカラムを追加した「bookmarks2」テーブルを作成しています。)
 
また、「ブックマークチュートリアル」に関連した記事としては以下の記事もあります。
CakePHP3のfriendsofcake/searchでブックマークチュートリアルのタグ検索を実装
 
 

CSVファイルを更新する Controllerの処理

 
CSVアップロードの処理全体は「CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説」を読んでいただくとして、そのうちの Controller(/src/Controller/HogesController.php)の処理の基本形は以下のものとなります。
 

 
 
この Controllerの処理の中で、
32~40行目で保存するレコードを整形し、
43~45行目で整形したレコードをテーブルに保存しています。
 
まず始めに、CSVとして取得したレコード全体で配列を作成し、「saveMany()」メソッドで一括して保存する処理となっています。
 
 
この記事では、このレコードを整形し、テーブルに保存する処理のバリエーションを解説します。
 
 
ちなみに、この処理では CSVファイルを一括して処理するため速い処理が期待できます。
 
ですが、カラム数にもよりますが、数百件程度であれば全く問題がなくても、万単位のレコードがある場合は、メモリオーバーや処理時間オーバーなどの不具合が発生する場合も考えられるため、CSVの件数が多くなる可能性がある場合は、件数をカウントして処理を分岐するなどの対応が必要だろうと思います。
 
 

テーブルの接続方法のバリエーション

 
まず始めに、テーブルに接続する方法のバリエーションです。
 
先の例では下記の記述で「Bookmarks2」のモデルをロードしています。
 

 
ロードしたモデルを下記のように使用します。
 

 
 
モデルを呼び出すほかの方法としては、下記の記述方法もあります。
まず、Controllerの use句を書いている箇所に下記を追記します。
 

 
また、先の「$this->loadModel("Bookmarks2");」の記述を、下記の記述に変更します。
 

 
 

「save()」メソッドで 1件ずつ追加(Insert処理・その2)

 
最初のサンプルでは「saveMany()」メソッドを使用して、一括保存する処理でした。
 
その2では「save()」メソッドを使用して 1件ずつ保存する処理を紹介します。
 

 
この処理が、Bakeを実行して自動的に作成される処理に一番近い処理になります。
foreach文で配列から 1件ずつレコードを取り出して、saveメソッドで保存しています。
 
また、コメントにしていますが、11行目を 13~17行目と置き換えることで、正常に保存できた場合は保存したレコードの IDを取得することや、エラーが発生した場合はそのエラーの対処することなど、1件ずつ細かな管理をすることを容易にすることができます。
 
CSVの件数が少ない場合はこのような処理方法も使用できるでしょう。
 
 
基本的な処理が CSVファイルを取得することを想定していますので、配列「$csvData」を foreach文で処理しています。

ですが、入力フォームから取得した値 1件を受け取って保存する場合は以下の記述になります。
 

 
より Bakeされた際に作成される処理に近づけるならば下記の記述になります。
 

 
 

「save()」メソッドで 1件ずつ更新(Update処理・その1)

 
ここからは、レコードを更新する(Update)処理について解説します。
 
 

「get()」メソッドを使い IDからレコードを取得(その1-1)

 
CSVから取得する項目に IDが含まれ、IDを利用してレコードを更新する場合は下記のように記述することが出来ます。
 

 
getメソッドは、レコードの IDを指定してレコードを取得する処理ですが、指定した IDがない場合はエラーとなります。
 
テーブルに保存されていない IDが入力される可能性がある場合は、取得できない場合に例外処理(エラー処理)とする方法もありますが、ここではまず始めに existsメソッドでレコードの存在チェックをする方法を採用しています。
 
 

「find()」メソッドを使い条件に合致するレコードを取得する(その1-2)

 
IDがない可能性を考慮する場合や、取得する CSVに IDが含まれない、もしくは、プライマリーキーとなる ID以外をキーとしてレコードを更新したい場合は下記のように findメソッドを使用する方法が有効です。
 

 
 

「find()」メソッドを使い条件に合致するレコードを取得(その1-3)

 
基本的には「その1-2」と変わりませんが、5行目と 7行目を 1行にまとめて下記のように記述することも出来ます。
 

 
 

「save()」メソッドで 1件ずつ更新(Update処理・その2)

 
あまり代わり映えはしませんが、保存するレコードを配列で整形する方法もあります。
 

 
 

「Query()」メソッドで複数件のレコードを更新(Update処理・その3)

 
続いて、複数のレコードをまとめて更新する方法です。
 
更新のその1、その2は、CSVの 1行でテーブルの 1レコードを更新する更新方法です。
 
「その1-1」は IDをキーに更新を行いますので 1レコードしかありませんが、「その1-2」「その1-3」「その2」に関しては、「["flag_code"=>$vol[0]]」の条件に該当するレコードが複数件ある場合も存在します。
処理上は、firstメソッドを用いていますので、そのうちの最初の 1件のみ更新する処理になっていますが。
 
 
このように、条件に該当するレコードが複数ある場合は、複数件まとめて更新する方法が以下の処理になります。
 
Queryメソッドを使って Update文を生成する方法です。
 

 
 

「UpdateAll()」メソッドで複数件のレコードを更新(Update処理・その4)

 
前項と同じく、条件に該当するレコードが複数件ある場合は、下記のように UpdateAllメソッドを使う方法もあります。
 

 
 

CakePHP3の関連記事

CakePHPのpostlinkで生成した削除リンクをクリックしても処理が実行されない対処法
CakePHP4のCSS、JavaScript、画像のブラウザへのキャッシュをコントロールする
CakePHP3でレコードを保存(追加、更新、Insert、Update)する複数の方法を紹介
CakePHP3でモデルなしフォームからCSVをアップロードしレコードを更新する方法解説
CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
CakePHP3のInsert On Duplicate Key Update(upsert)構文を解説・バルク処理も
CakePHP3の1対多での連携を中間テーブルを使った多対多の連携に変更するときの手順
CakePHP3でデフォルトのソート条件を設定してユーザの選択肢たソート条件を有効にする方法
CakePHP3で Ajaxを使う方法の解説。3.6以降対応。Successとthenの両方を解説。
CakePHP3でパンくずの指定は HTMLヘルパーを使って指定する方法を解説
 
その他の「CakePHP3」に関する記事一覧
 
 

 - CakePHP 3.x 4.x 5.x

GoogleAdwords

GoogleAdwords

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

Message

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

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

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

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

  関連記事

CakePHPで Auto Incrementを外すと Duplicate entry '0' for keyのエラーが出るかも
CakePHPで Auto Incrementを外すと Duplicate entry ‘0’ for keyのエラーが出るかも

CakePHPでAuto Incrementの設定を変更したときに「Duplicate entry ‘0’ for key」のエラーが出た。原因はModel内で IDを編集する処理の追加を忘れていたからだった。

CakePHP3でassociatedを使って関連データをまとめて保存する方法(hasOne、hasMany、belongsTo)

CakePHP3で関連データをまとめて保存する方法。hasOne、hasMany、belongsTo等の関連データはassociatedを追加することでまとめて保存することができます。

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

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

CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合
CakePHP3で環境変数を設定して本番環境と開発環境を分けて処理をする場合

CakePHP3で開発環境と本番環境とで違う設定ファイルを読み込ませて環境ごとに定数を切り替える方法を解説。Apacheのhttpd.confに環境変数を設定し、それを読み込み判別する。

CakePHPのFlashエラーは出るが入力項目ごとのメッセージが出ないエラーの原因
CakePHPのFlashエラーは出るが入力項目ごとのメッセージが出ないエラーの原因

Bakeして自動生成した入力フォーム処理を元に少し処理を追加したら、入力エラーがあってもエラーメッセージが表示されなくなった。原因はリダイレクトの処理にあった。

CakePHP3でCookieを保存、呼び出し、削除の操作・CakePHP3.7対応
CakePHP3でCookieを保存、呼び出し、削除の操作・CakePHP3.7対応

CakePHP3.7でCookieを保存、取り出し、削除する方法を解説。CakePHP3でのCookieの取り扱いはバージョンごとに変更されるため、環境に合わせた方法を探す必要がある。

CakePHP4のCakeDC/Usersのログイン時のリダイレクトとユーザ権限管理の設定解説
CakePHP4のCakeDC/Usersのログイン時のリダイレクトとユーザ権限管理の設定解説

CakeDC謹製UsersプラグインのCakePHP4版の紹介。ログイン認証後にリダイレクトする先の設定方法についての解説と実運用するために必要なコツを解説。便利な仕組みも仕様の理解があって初めてうまく使いこなせる。

CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法
CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングする方法

CakePHP3でPHP Simple HTML DOM Parserを使ってスクレイピングをする方法を解説。インストール方法、読み込み方法。および、具体的なスクレイピングを実行するサンプルソースも。

CakePHP3でkeywords、DescriptionをHTMLヘルパーを使って設定する
CakePHP3でkeywords、DescriptionをHTMLヘルパーを使って設定する

CakePHP3のkeywordsとdescriptionを設定する方法の解説。CakePHP3にはmetaタグを編集するHTMLヘルパーが用意されているためそれを利用すればOK!ポイントはブロック化を有効にすること。

CakePHP3でアソシエーション先のカラムでデータをソートして取得したい
CakePHP3でアソシエーション先のカラムでデータをソートして取得したい

アソシエーション先のテーブルのカラムをキーにソートをしたデータを取得したい!ときの記述方法を解説。「orderAsc()」ではなく「contain()」の中にSort条件を記述する。