【问题标题】:How to implement join query in Yii2Yii2中如何实现join查询
【发布时间】:2018-06-07 14:55:52
【问题描述】:

我已经阅读了所有 Yii2 框架文档,但是在尝试实现它时感到困惑。

我有一个客户视图,它显示了客户表中的所有字段,包括地址表中的address_id 字段。

我想在 Yii2 框架中使用 MySQL 实现一个连接查询,但生成的代码如下:

模型中的客户搜索:

class CustomerSearch extends Customer{
/**
 * {@inheritdoc}
 */
public function rules()
{
    return [
        [['customer_id', 'store_id', 'address_id', 'active'], 'integer'],
        [['first_name', 'last_name', 'email', 'create_date', 'last_update'], 'safe'],
    ];
}

/**
 * {@inheritdoc}
 */
public function scenarios()
{
    // bypass scenarios() implementation in the parent class
    return Model::scenarios();
}

/**
 * Creates data provider instance with search query applied
 *
 * @param array $params
 *
 * @return ActiveDataProvider
 */
public function search($params)
{
    $query = Customer::find();

    // add conditions that should always apply here

    $dataProvider = new ActiveDataProvider([
        'query' => $query,
    ]);

    $this->load($params);

    if (!$this->validate()) {
        // uncomment the following line if you do not want to return any records when validation fails
        // $query->where('0=1');
        return $dataProvider;
    }

    // grid filtering conditions
    $query->andFilterWhere([
        'customer_id' => $this->customer_id,
        'store_id' => $this->store_id,
        'address_id' => $this->address_id,
        'active' => $this->active,
        'create_date' => $this->create_date,
        'last_update' => $this->last_update,
    ]);

    $query->andFilterWhere(['like', 'first_name', $this->first_name])
        ->andFilterWhere(['like', 'last_name', $this->last_name])
        ->andFilterWhere(['like', 'email', $this->email]);

    return $dataProvider;
}

客户类别:

class Customer extends \yii\db\ActiveRecord{
/**
 * {@inheritdoc}
 */
public static function tableName()
{
    return 'customer';
}

/**
 * {@inheritdoc}
 */
public function rules()
{
    return [
        [['store_id', 'first_name', 'last_name', 'address_id'], 'required'],
        [['store_id', 'address_id', 'active'], 'integer'],
        [['create_date', 'last_update'], 'safe'],
        [['first_name', 'last_name'], 'string', 'max' => 45],
        [['email'], 'string', 'max' => 50],
    ];
}

/**
 * {@inheritdoc}
 */
public function attributeLabels()
{
    return [
        'customer_id' => 'Customer ID',
        'store_id' => 'Store ID',
        'first_name' => 'First Name',
        'last_name' => 'Last Name',
        'email' => 'Email',
        'address_id' => 'Address ID',
        'active' => 'Active',
        'create_date' => 'Create Date',
        'last_update' => 'Last Update',
    ];
}
}

【问题讨论】:

  • 你想加入什么?您必须有另一个表和模型并定义关系。您是否使用 Gii 模型/CRUD 生成器生成了此代码?
  • 表Customer和表Address使用公共字段'address_id'
  • 啊,是的,我错过了,抱歉。你用过 Gii 模型/CRUD 生成器吗?
  • 是的,CRUD 生成器

标签: php mysql activerecord yii2 foreign-keys


【解决方案1】:

您需要在 ActiveRecord 模型中声明一些关系...

在官方文档中查看Working with Relational Data

如果您将address_id 存储在customer 表中,那么您将与每个拥有1 个address 的客户绑定(即一对一的关系),这是一个相当糟糕的设计。或者您可以使用junction table。您最好将customer_id 存储在每个地址记录中并定义一对多关系,使每个客户能够存储多个地址(更像是在现实生活中,即家庭、工作地址等)。

例如,在您的 Customer 模型中,您将为客户地址定义 has-many 关系:

use app\models\Address;

class Customer extends \yii\db\ActiveRecord
{

    /**
     * {@inheritdoc}
     */
    public static function tableName()
    {
        return 'customer';
    }

    /**
     * {@inheritdoc}
     */
    public function rules()
    {
        return [
            [['store_id', 'first_name', 'last_name', 'primary_address_id'], 'required'],
            [['store_id', 'primary_address_id', 'active'], 'integer'],
            [['create_date', 'last_update'], 'safe'],
            [['first_name', 'last_name'], 'string', 'max' => 45],
            [['email'], 'string', 'max' => 50],
        ];
    }

    /**
     * {@inheritdoc}
     */
    public function attributeLabels()
    {
        return [
            'customer_id' => 'Customer ID',
            'store_id' => 'Store ID',
            'first_name' => 'First Name',
            'last_name' => 'Last Name',
            'email' => 'Email',
            'primary_address_id' => 'Primary Address ID',
            'active' => 'Active',
            'create_date' => 'Create Date',
            'last_update' => 'Last Update',
        ];
    }

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getAddresses()
    {
        return $this->hasMany(Address::className(), ['customer_id' => 'id']);
    }

}

在您的 Address 模型中,您将定义反向 has-one 关系:

    /**
     * @return \yii\db\ActiveQuery
     */
    public function getCustomer()
    {
        return $this->hasOne(Customer::className(), ['id' => 'customer_id']);
    }

然后您可以通过定义的关系名称从模型实例中Access relational data,例如:

// SELECT * FROM `customer` WHERE `id` = 123
$customer = Customer::findOne(123);

// SELECT * FROM `address` WHERE `customer_id` = 123
// $addresses is an array of Address objects
$addresses = $customer->addresses;

另外请注意,如果您在架构中定义了正确的主键/外键,Gii 模型/CRUD 生成器将自动在您的模型和 CRUD 文件中创建样板关系代码。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多