YiiのActiveRecordはデータベースを扱うクラスで、MVCのM(モデル層)、ORMのO(オブジェクト)にあたります。
よくある質問。最近、グループ内でのフィードバックを通して、この問題をまだ理解していない人が多いと感じました。今日はこの問題についてわかりやすく説明しました。yii2 ActiveRecord の複数テーブルの関連付けと、この関連付けを最適化する方法を見てみましょう。
シナリオ要件:
ユーザー テーブル user とユーザー チャネル テーブル auth があり、2 つのデータ テーブルが user.id と auth.uid によって 1 対 1 に関連付けられているとします。ここで、認証テーブルのソース チャネル ソースをユーザー リストに表示する必要があり、チャネルが検索可能である必要があります。
まず、gii を通じてユーザーおよび認証シリーズ関連のモデルと操作を生成します。ここでは詳しい説明はありません。xxx
を参照してください。引き続き重要な手順を見ていきます。
1. ユーザー テーブルに対応する AR モデル クラス commonmodelsUser.php を見つけて関連付けます。このクラスファイルでは、認証テーブル
/** * 关联auth表 */ public function getAuth() { // hasOne要求返回两个参数 第一个参数是关联表的类名 第二个参数是两张表的关联关系 // 这里uid是auth表关联id, 关联user表的uid id是当前模型的主键id return $this->hasOne(common\models\Auth::className(), ['uid' => 'id']); }
が設定された後、2 つのデータテーブルが自動的に関連付けられるわけではありません。ユーザー リスト ページにアクセスします (リスト ページは GII によって生成されますが、これまでは操作していません)。デバッグを通じてデータベース クエリを表示すると、実際のクエリが認証テーブルに関連付けられていないことがわかります
。2. グリッドビューのソースチャネルフィールドソースに関連付けテーブルを追加します
上記で auth.source を直接使用するにはどうすればよいか疑問に思う人もいます。
心配しないでください。デバッグを開いて実際のクエリを確認します。
select * from `auth` where uid = xxx; のような多くの操作があることがわかります。ページングのデフォルトが 20 個のデータである場合、同様のクエリが 20 個存在します。
まず何が起こったのか見てみましょう?
実はこれ、phpの基礎知識なんです。オブジェクトの存在しないメンバー変数を読み書きする場合、__get() __set() マジック関数が自動的に呼び出されます。 Yii もこれを利用して実装しています。
この操作は、ほとんどの人がグリッドビューでメソッドをカプセル化し、関連するテーブル データを取得するのとほぼ同じですが、! 20 個の SQL クエリでは、明らかにオーバーヘッドが大幅に増加します。これが左結合操作であれば素晴らしいでしょう。
3. SQL を最適化する
最適化する必要があるのは次のとおりです:
20 sql を 1 sql に変更します
関連するテーブルに必要なフィールドのみを取得します
いくつかの生徒が質問していますが、これが Yii に付属する操作です。それを最適化するにはどうすればよいですか?データ ソースの取得に戻り、ユーザー リストのデータが userSearch モデルの検索メソッドを通じて提供されていることがわかります。
つまり、データ クエリは実際には関連テーブル クエリを実行しません。この場合、UserSearch に関連クエリを追加します
<?= GridView::widget([ // other codes 'columns' => [ // other columns 'auth.source', ] ]); ?>
ユーザー リスト ページを再度更新して、デバッグ分析を通じて、2 つの SQL ステートメントが注目を集めていることがわかります
$query = User::find(); $query->joinWith(['auth']); $query->select("user.*, auth.source");
つまり、SQL の最適化という目標は達成されました。デバッグ分析を通じて、DB のクエリ時間が大幅に短縮されたことがわかりました。
4. 関連するテーブル フィールドにクエリを追加します。
GridView の検索モデルも、searchModel を通じて実装され、どのフィールドが検索可能か、どのフィールドが検索不可能かを制御します。
次に、関連付けテーブルのソースを検索可能にする必要があるため、searchModel で属性ソースを定義し、それをルールに追加します
SELECT `user`.*, `auth`.`source` FROM `user` LEFT JOIN `auth` ON `user`.`id` = `auth`.`uid` LIMIT 20 SELECT * FROM `auth` WHERE `user_id` IN (20个uid);
次に、gridview で auth.source を変更します
public $source; public function rules() { return [ // other rules ['source', 'safe'], ]; }
この時点までのインターフェースは問題ありません。プログラムによる検索を実装するためのステップがまだ 1 つ残っています。データ ソースを取得する場所に新しいソース条件を追加するだけです
以下はActiveRecord1 の一部の使用法、 object to array$model = new ActiveRecord(); ActiveRecord は単純な配列ではないため、直接 json_encode することはできません。情報は不完全になります。 解決策: $model.toArray(); これにより、単純な配列に変換され、json_encode できるようになります。
2. 名前またはその他のフィールドから ActiveRecord ID を直接取得します。
// 'auth.source', [ 'attribute' => 'source', 'value' => 'auth.source', 'label' => '渠道来源', ],
私が昔よく使っていた方法は次のとおりです(今ではとても下品だと思います):
$query->andFilterWhere([ // other params 'auth.source' => $this->source, ]);
3、モデルの理解
$nIdcId = idc_info::model()->find('name like :name',array(':name'=>"%".$strIdcName."%"))->id;
上記はエディターは、Yii2 ActiveRecord マルチテーブル関連付けとマルチテーブル関連付け検索の実装に関する知識を皆さんに紹介します。ご質問があれば、メッセージを残してください。編集者がすぐに返信します。 。また、PHP 中国語 Web サイトをサポートしていただきありがとうございます。
Yii2 ActiveRecord マルチテーブル関連付けとマルチテーブル関連付け検索の実装に関連するその他の記事については、PHP 中国語 Web サイトに注目してください。