Yii2:使用来自多对多关系的值填充模型字段 [英] Yii2: Populating model field with value from many-to-many relation
问题描述
我们正在尝试以用户只能检索与其帐户相关的数据的方式设置REST API.到目前为止,我们只有一个公共API,所有这些都像个魅力一样. 公共API仍然会被使用,因此我们从头开始.
We are trying to set-up our REST API in a way that a user can only retrieve data related to his account. Uptill now, We've only had a public API and it all worked like a charm. The public API will still get used, so we started from scratch.
我们有一个User
模型,扩展了ActiveRecord
并实现了IdentityInterface
.用户将与Customer
模型有关系(很多:很多,但至少一个).一个用户将具有only one MASTER
个客户.
上面的内容使用3个表app_customer_users
,app_customers
和link_customer_users_customers
保存在数据库中.联接表包含一个布尔字段master
.
We have a User
model, extending ActiveRecord
and implementing IdentityInterface
. A User will have a relation to a Customer
model (Many:Many, but at least one). A User will have only one MASTER
Customer.
The above is saved in the database using 3 tables app_customer_users
,app_customers
and link_customer_users_customers
. The join table contains a boolean field master
.
在用户模型中:
public function getCustomers() {
return $this->hasMany(Customer::className(), ['id' => 'customer_id'])
->viaTable('link_customer_users_customers', ['user_id' => 'id']);
}
在客户模型中:
public function getUsers() {
return $this->hasMany(User::className(), ['id' => 'user_id'])
->viaTable('link_customer_users_customers', ['customer_id' => 'id']);
}
如果我们请求所有客户,这将非常有用,他们将填充用户"(如果我们将其添加到extraFields
等,等等...)
This works great if we would request all customers, they'll have 'users' populated (if we add it in extraFields
etc, etc...)
新的API使用Basic user:pass
进行身份验证,我们可以通过调用Yii::$app->user->getIdentity()
来获取当前的用户对象/身份.
The new API uses Basic user:pass
in authentication, and we can get the current user object/identity by calling Yii::$app->user->getIdentity()
.
当用户以一种可以通过调用Yii::$app->user->getIdentity()->customer_id
或Yii::$app->user->getIdentity()->getCustomerId()
的方式进行连接的方式进行连接时,我们希望能够包含客户ID.客户ID应该是联接表中master
的ID == true
.
We would like to be able to include the Customer ID when a user connects in a way that we can get it by calling Yii::$app->user->getIdentity()->customer_id
OR Yii::$app->user->getIdentity()->getCustomerId()
The Customer ID should be the ID where master
in the join table == true
.
我们尝试将其添加到fields
中,就像我们以前使用hasOne
关系一样,但是在这种情况下,它似乎不起作用:
We've tried adding it to fields
, as we did before with hasOne
relations, but in this case it does not seem to work:
$fields['customer_id'] = function($model) {
return $model->getCustomers()->where('link_customer_users_customers.master', true)->one()->customer_id;
}; // probably the where part is our porblem?
我们已经尝试过创建这样的自定义getter:
And we've tried creating a custom getter like this:
public function getCustomerId() {
return $this->getCustomers()->andFilterWhere(['link_customer_users_customers.master' => true])->one()->customer_id;
}
最后一次尝试导致错误:
SQLSTATE[42S22]: Column not found: 1054 Unknown column 'link_customer_users_customers.master' in 'where clause'\nThe SQL being executed was: SELECT * FROM `app_customers` WHERE (`link_customer_users_customers`.`master`=TRUE) AND (`id`='93')
我们一直在文档中和Google上进行搜索,但没有找到有关如何执行此操作的示例.
We've been searching in the docs and on Google, but did not find an example on how to do this.
根据接受的答案,我们添加了一些代码.
Based on accepted answer we added some code.
在User
模型中:
// Include customer always with user
public static function findIdentity($id) {
return static::findOne($id)->with('customer');
}
// Next to `getCustomers()`, added this `hasOne` relation to get only the customer from
// which the current user is the master user
public function getCustomer() {
return $this->hasOne(Customer::className(), ['id' => 'customer_id'])
->viaTable('link_customer_users_customers', ['user_id' => 'id'], function ($query) {
$query->andWhere(['master' => 1]);
});
}
// Getter, just because
public function getCustomerId() {
return $this->customer->id;
}
现在我们可以通过调用项目中的Yii::$app->user->getIdentity()->customer->id
或Yii::$app->user->identity->customer->id
等,从客户那里获取ID.
And now we can get the ID from the customer by calling Yii::$app->user->getIdentity()->customer->id
OR Yii::$app->user->identity->customer->id
etc, etc.. in the project..
推荐答案
您应添加如下所示的关系,并将anonymous
函数用作viaTable
的第三个参数,以添加另一个条件以检查master
字段确实如此.
You should add a relation like below and use an anonymous
function as the third parameter to the viaTable
to add another condition to check master
field as true.
public function getMasterCustomerId() {
return $this->hasOne(Customer::className(), ['id' => 'customer_id'])
->viaTable('link_customer_users_customers', ['user_id' => 'id'],function($query){
$query->andWhere(['master' => 1]);
});
}
,然后可以按如下所示将其用于已登录的用户.
and then you can use it for the logged in user as below.
Yii::$app->user->identity->masterCustomerId->id;
这篇关于Yii2:使用来自多对多关系的值填充模型字段的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!