Explication détaillée de la requête liée à YII

*文
Libérer: 2023-03-18 18:46:02
original
1698 Les gens l'ont consulté

Cet article présente principalement les informations pertinentes sur la requête liée à YII. Les amis dans le besoin peuvent s'y référer. J'espère que cela aide tout le monde.

1. Configuration de la corrélation multi-tables

Avant d'utiliser AR pour effectuer des requêtes de corrélation, nous devons faire savoir à AR ce qu'est un AR. la classe est liée à une autre.

La relation entre deux classes AR est directement liée à travers la relation entre les tableaux de données représentés par les classes AR. Du point de vue d'une base de données, il existe trois types de relations entre les tables A et B : un-à-plusieurs (comme tbl_user et tbl_post), un-à-un (comme tbl_user et tbl_profile) et plusieurs-à-plusieurs ( plusieurs à plusieurs tels que tbl_category et tbl_post). En AR, il existe quatre relations :

BELONGS_TO (appartient à) : Si la relation entre les tables A et B est un-à-plusieurs, alors la table B appartient à la table A (par exemple, Post appartient à l'utilisateur );

HAS_MANY (il y en a plusieurs) : si la relation entre les tables A et B est de un à plusieurs, alors A a plusieurs B (par exemple, l'utilisateur a plusieurs publications

HAS_ONE (il y en a un) : Il s'agit d'un cas particulier de HAS_MANY : A peut avoir au plus un B (par exemple, l'utilisateur peut avoir au plus un profil

MANY_MANY : cela correspond aux plusieurs-) ; relation à plusieurs dans la base de données. Étant donné que la plupart des SGBD ne prennent pas directement en charge les relations plusieurs-à-plusieurs, une table de relations est nécessaire pour diviser la relation plusieurs-à-plusieurs en une relation un-à-plusieurs. Dans notre exemple de structure de données, tbl_post_category est utilisé à cette fin. En termes AR, nous pouvons interpréter MANY_MANY comme la combinaison de BELONGS_TO et HAS_MANY. Par exemple, Post appartient à plusieurs (appartient à plusieurs) Catégorie et Catégorie a plusieurs (a plusieurs) Post.

La relation définie dans AR doit remplacer la méthode relations() dans CActiveRecord. Cette méthode renvoie un tableau de configurations de relations. Chaque élément du tableau représente une relation unique au format suivant.


'VarName'=>array('RelationType', 'ClassName', 'ForeignKey', ...additional options)
Copier après la connexion



où VarName est le nom de la relation ; , qui peut être l'une des quatre constantes suivantes : self::BELONGS_TO, self::HAS_ONE,self::HAS_MANY et self::MANY_MANY ; ClassName est le nom de la classe AR associée à cette classe AR ForeignKey spécifie la clé étrangère ; utilisé dans la relation (un ou plusieurs).

Quelques points qui méritent d'être clarifiés :

(1), à quoi fait référence VarName ? Voir l'exemple 2 ci-dessous pour plus de détails.


(2), Type de relation. Il existe 4 types au total, à savoir

self::HAS_MANY, self::BELONGS_TO, self::MANY_MANY, self::HAS_ONE.


(3), Nom de classe. Autrement dit, un autre ../model/classname.php associé.


(4), Clé étrangère. Qui est la clé étrangère pour qui ?


(5), conditions supplémentaires

Diagramme ER

Exemple 1, relation un-à-plusieurs et plusieurs-à-un (relation entre la publication et l'utilisateur )

1) models/Post.php


class Post extends CActiveRecord 
{ 
...... 
public function relations() 
{ 
return array( 
'author'=>array(self::BELONGS_TO, 'User', 'author_id'), 
); 
} 
}
Copier après la connexion


où Post et Utilisateur La relation est une relation BELONGS_TO (plusieurs à un) et est associée à l'utilisateur via l'author_id de la publication.


L'author_id dans Post est une clé étrangère et est associé à l'utilisateur.


Remarque : VarName est ici l'auteur, un objet.

(2) models/User.php


class User extends CActiveRecord 
{ 
...... 
public function relations() 
{ 
return array( 
'posts'=>array(self::HAS_MANY, 'Post', 'author_id'), 
'profile'=>array(self::HAS_ONE, 'Profile', 'owner_id'), 
); 
} 
}
Copier après la connexion


Pour l'utilisateur, La relation avec Post est une relation HAS_MANY (un-à-plusieurs). Et associé à Post via author_id de Post.

Exemple 2, relation plusieurs-à-plusieurs

dans FailParts.php


'Users' => array(self::MANY_MANY, 'User', 'fail_parts_user(fail_parts_id, user_id)'),
Copier après la connexion


Dans User.php


'FailParts' => array(self::MANY_MANY, 'FailParts', 'fail_parts_user(user_id, fail_parts_id)'),
Copier après la connexion


Puisque les deux sont multiples Pour les relations plusieurs-à-plusieurs, utilisez Users au lieu de User ; utilisez FailParts au lieu de FailPart.

Les utilisateurs et les FailParts ici sont le VarName précédent.

Exemple 3, relation un-à-un

Il est relativement simple et sera omis pour l'instant.

2. À propos de VarName.

Pour la classe A.php, 'VarName'=>array('RelationType', 'B', 'ForeignKey', ...options supplémentaires)

où VarName est fondamentalement le même que B. Mais pas forcément exactement la même chose. À ce stade, vous pouvez accéder à B et à ses valeurs d'attribut via VarName dans le view/A/xx.php de A.

Si c'est un-à-un : A->VarName

S'il s'agit de plusieurs-à-un : author_name = $post->Author->name
Si c'est un-à-un : A->Author->name; est un à plusieurs : $posts = $author->Post
S'il s'agit de plusieurs à plusieurs : $posts = $author->Post;//L'essence est de le diviser en un-à-plusieurs : $posts = $author->Post; à plusieurs et plusieurs à un >2. Utilisation d'associations multi-tables


Souvent dans les contrôleurs

foreach($posts as $u){ 
$_tmp_titles[] = $u -> title; 
} 
titleStr = implode(', ', $_tmp_titles);
Copier après la connexion

1, chargement retardé

(1) beaucoup -to-one

$post = Post::model()-> ;findByPk(10);

$author = $post->author;Remarque : l'essence voici en tête-à-tête. (2) Un à plusieurs

$user = User::model()->findByPk(10);

$posts = $user->posts;

(3) Plusieurs-à-plusieurs

Il est important de noter que les deux identifiants ont une relation séquentielle.

Du point de vue de l'instance $repairInfo, l'association doit être



tandis que du point de vue de $failParts Du point de vue de l'instance, l'association devient

而前面也已经指出,不需要双方都配置,只需需要的一方设置即可。

之前曾使用过的笨方法:


/*方法一:使用表关系(多对多)*/ 
$fails = $repairInfo->FailParts;//在$repairInfo中使用 
/*方法二:使用原始方法*/ 
$id = $repairInfo->id; 
$maps = RepairMapping::model()->findAll("repair_info_id = $id"); 
$f_ids = array(); 
foreach($maps as $map){ 
array_push($f_ids, $maps[0]->fail_parts_id); 
} 
$f_idsStr = implode(',',$f_ids); 
$fails = FailParts::model()->findAll("id IN ($f_idsStr)");
Copier après la connexion


2,主动加载——with

(1)一对多
(2)多对多


$posts = Post::model()->('author')->findAll();
Copier après la connexion


例子:

User.php


//查询一个机房$idc_id的所有用户 
function getAdminedUsersByIdc($idc_id){ 
$c = new CDbCriteria(); 
$c->join = "JOIN idc_user on t.id=idc_user.user_id"; 
$c->condition = "idc_user.idc_id=$idc_id"; 
return User::model()->with('Idcs')->findAll($c); 
} 
//规则中配置 
'Idcs' => array(self::MANY_MANY, 'Idc', 'idc_user(user_id, idc_id)'),
Copier après la connexion


批注:没有with('Idcs'),执行后的结果也一样。只不过不再是eager loading。

三、带参数的关联配置

常见的条件有

1,condition 按某个表的某个字段加过滤条件

例如:


//在User的model里定义,如下关联关系 
'doingOutsources' => array(self::MANY_MANY, 'Outsource', 'outsource_user(user_id, outsource_id)', 
'condition' => "doingOutsources.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
Copier après la connexion


//结论:condition是array里指定model的一个字段。

显然,doingOutsources是真实数据表Outsource的别名,所以在condition中可以使用doingOutsources.status_id,当然也可以使用Outsource.status_id。另本表名user的默认别名是t。

2,order 按某个表的某个字段升序或降序


//在RepairInfo的model里定义,如下关联关系 
'WorkSheet' => array(self::HAS_MANY, 'WorkSheet', 'repair_info_id', order => 'created_at desc'), 
//调用 
$worksheets = $repair_info->WorkSheet; //此时$worksheets是按降序排列
Copier après la connexion


//结论:order是array里指定model的一个字段。

with
joinType
select
params
on
alias
together
group
having
index

还有用于lazy loading的
limit 只取5个或10个
offset
through
官方手册
'posts'=>array(self::HAS_MANY, 'post', 'author_id', 'order'=>'posts.create_time DESC', 'with'=>'categories'),

四、静态查询(仅用于HAS_MANY和MANY_MANY)

关键字:self:STAT

1,基本用法。例如,


class Post extends CActiveRecord 
{ 
...... 

public function relations() 
{ 
return array( 
'commentCount'=>array(self::STAT, 'Comment', 'post_id'), 
'categoryCount'=>array(self::STAT,'Category','post_category(post_id, category_id)'); 

); 
} 
}
Copier après la connexion


2,静态查询也支持上面的各种条件查询


'doingOutsourceCount' => array(self::STAT, 'Outsource', 'outsource_user(user_id, outsource_id)', 
'condition' => "outsource.status_id IN(" . Status::ASSIGNED . "," . Status::STARTED ."," . Status::REJECTED .")"),
Copier après la connexion


其他查询还包括

condition 使用较多

order
select
defaultValue
params
group
having

3,静态查询的加载方式

可以使用lazy loading方式
$post->commentCount.
也可以使用eager loading方式
$posts = Post::model()->with('commentCount','categoryCount')->findAll();
注with中字符串一定是别名。

两者的性能比较:

如果需要取所有post的所有comment,前者需要2N+1次查询,而后者只有一次。两者的选择视情况而定。

相关推荐:

Yii2中的代码自动加载机制

Yii框架中的form表单

Yii2实现增删改查后留在当前页的方法详解

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Étiquettes associées:
source:php.cn
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal