Yii2:使用来自多对多关系的值填充模型字段 [英] Yii2: Populating model field with value from many-to-many relation

查看:98
本文介绍了Yii2:使用来自多对多关系的值填充模型字段的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我们正在尝试以用户只能检索与其帐户相关的数据的方式设置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_usersapp_customerslink_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_idYii::$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->idYii::$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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆