2019.05.03CakePHP3のcontainメソッドは、EagerLoadingを自動で行ってくれる便利なメソッドです。目次containメソッドの使い方containメソッドがやってくれることN+1問題EagerLoadingまとめcontainメソッドの使い方CakePHP3のcontainメソッドは、引数に指定したアソシエーション先テーブルのデータをEagerLoadingしてくれます。引数はテーブル名のarrayです。Postsコントローラで、Postsテーブルとアソシエーションしているtagsテーブルをcontainしたい時は、以下のように書きます。$this->Posts->find('all')->contain(['tags']);もちろん、複数のテーブルをcontainできます。'comments']);containメソッドがやってくれることcontainメソッドを使うとEagerLoadingをやってくれると書きましたが、そもそもなんやそれ?って感じだったので調べてみました。EagerLoadingというのは、簡単にいうと事前に必要なデータをLoadしておくことで、これが後述するN+1問題の解決に役立ちます。アソシエーション先のデータをとってこようとすると、N+1問題と言われるものが発生してしまいます。N+1問題SQLクエリがデータの量N+1回走ってしまい、取得するデータ量Nが増えるたびに発行クエリも増えてしまいパフォーマンスが低下する問題のことです。下の画像のようなuser_idで関連づけられているUsersテーブルとPostsテーブルがあるとします。UsersテーブルからみたPostsテーブルとのアソシエーションは1対多(hasMany)で、PostsテーブルからみたUsersテーブルとのアソシエーションは多対1(belongsTo)です。この画像の「投稿一覧」のような画面を作りたいとすると、Postsテーブルのアソシエーション先であるUsersテーブルのカラム(Users.name)も必要になります。この時、PostsControllerでPostsテーブル(PostsTableクラスのインスタンス)のみを読み込んでビューにsetし、index.ctpでforeachを回してPostsの一覧を表示するとします。}}すると、ループ1回につき1文、(1投稿につき1文)Users.nameを取得するためのSQLクエリが発行されてしまいます。key))がN回走ることになるので、合計でN+1個のSQLクエリが発行されてしまいます。これをN+1問題と言います。データが少量の時はそこまで問題はないのですが、データが大量にある時はNの大きさもかなりのものになるので、パフォーマンスの大幅な低下を招いてしまいます。EagerLoadingこれを防ぐのがEagerLoadingで、先のコントローラーにおいてPostsテーブルの読み込み時に、アソシエーション先のUsersテーブルのデータもまとめて事前にLoadしておきます。することで既に必要なすべてのデータが用意された状態でビューへのsetが行われるため、Templateにおいてループのたびに必要なデータを取得するためのSQLクエリが走るようなことがなくなります。CakePHP3では、モデルのloadはデフォルトでlazyloading(後から必要になったタイミングでloadする)なので、containメソッドを使ってEagerLoadingを明示的に行わないといけません。}}のようにcontainメソッドを使い引数にUsersテーブル名を指定してあげるだけでOKです。CakePHP3の力でEagerLoadingを自動的に行ってくれます。posts.user_idみたいなSQLです。postsざっくりとはこの2文です。containメソッドはこれらのようなSQLを作ってくれてデータを取得し、さらに2つの情報を紐付けた多次元配列を作成し、返してくれます。hasOneアソシエーションの場合はご想像の通り簡単なので書きませんが、とにかく実際に発行されるSQLは、アソシエーションの種類や結合タイプによって異なります。いちいちこれらのSQLを書き分けるのは面倒臭い上、その紐付けを行うのも大変なので、有名なフレームワークにはだいたいEagerLoadingのためのメソッドがあります。その1つがCakePHP3におけるcontainメソッドなのです。まとめCakePHP3のcontainメソッドは、N+1問題を解消するためのEagerLoadingを自動で行ってくれるメソッドでした。TableにhasManyなどのアソシエーション設定をしておけば、Controllerではcontain(‘アソシエーション先Tabel名’)のようなメソッドを書くだけで、勝手にアソシエーションに合わせたEagerLoadingを行ってくれるので、大変便利ですね。今回の記事は前の記事の続きで、初心者がCloud9でPython3系のプログラムをどう動かしていけばいいのかを説明する内容になっています。初心者で新しくPythonを始める方は、ほとんどがPython2系ではなくPython3系を使...Angular【Angular】html文書をエスケープしないでそのままtemplateに表示するAngularなどのフロントエンドフレームワークでは、多くの場合HTMLを出力しようとすると自動で文字列にエスケープするセキュリティシステムが組み込まれています。これをサニタイジングといい、クロスサイトスクリプティング(XSS)対策のために...AWSCloud9でPython3環境構築入門!【AWS】PyQさんのおかげもあってPythonの文法や、簡単なWebアプリの開発周りについてはなんとなくわかってきました。なんでそろそろポートフォリオ作りたいなと思い、まずPyQから離れてプログラムを書き始めようと思ったわけです。...Programming【Python】コマンドライン引数を利用できるargparseの使い方argparseというPythonの標準モジュールがあります。これを使うとプログラムの実行時にコマンドライン引数を取ることができ、コマンドライン上での柔軟なプログラム実行が可能になります。p...ProgrammingFileZillaでFTP接続失敗を解決、ついでにSFTP接続にしてみたFTPツールにはFileZillaを使っている人が多いかと思います。今回レンタルサーバーのファイルを弄ろうと久々にFileZillaで接続してみたのですが、なぜか接続ができなくなっていました。コメントをキャンセルメールアドレスが公開されることはありません。*サイト上に表示された文字を入力してください。【Swift】frameとboundsの違いは?UIViewにどう影響するのか【Swift】オプショナル型とは?4種類のアンラップ方法と共に解説!【Angular】html文書をエスケープしないでそのままtemplateに表示するアーカイブ2019年9月2019年5月2019年4月2019年3月2019年2月カテゴリーAngularAWSCSSDockerExcelJavaScriptMySQLPHPProgrammingPythonSwiftタイトルとURLをコピーしました。