简体   繁体   中英

Is there a proper way to cross join using yii2?

I'm doing a query for activedataprovider, which I'm going to use for the purpose of search. I need to use cross join. I used joinWith, but it complains about warehouse model not having relation with product. it was calling product. Are there any work around here so that it won't trigger the relation, since it's a cross join?

Other notes: Certain attributes like product_id, product.category, etc doesn't exist on the original model which is based on warehouse. Will it work on the fly if I just add public property/attribute variables or do I need a work around?

public function search($params)
    {               
        $query = Warehouse::find()->joinWith('product')
                ->select(['product_id' => 'product.id','warehouse.warehouse', 'product.category', 'product.product', 'min_stock' => 'coalesce(critical.min_stock, -1)'])
                ->leftJoin('critical', 'critical.product_id = product.id AND critical.warehouse_id = warehouse.id')
                ->where(['warehouse.id' => $this->_id]);

        $this->load($params);

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

        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;
        }

        $query->andFilterWhere(['category' => $this->category]);
        $query->andFilterWhere(['like', 'product', $this->product]);        

        return $dataProvider;
    }

For all the query that are difficult (or impossibile) to build using yii2 activeRecord or activeQuery functionalites you can use findBySql

$sql = "select 
          product.id as id
          , warehouse.warehouse as warehouse 
          , product.category as category
          , product.product as product
          , coalesce(critical.min_stock, -1) as min_stock 
          from Warehouse 
          cross join product  
          left join critical on ritical.product_id = product.id AND critical.warehouse_id = warehouse.id
          where warehouse.id' = " . $this->_id  

 $model =  Warehouse::findBySql($sql );

Get Your Query record as array so you don't require to define relationship

public function search($params)
    {               
        $query = Warehouse::find()->joinWith('product')
                ->select(['product_id' => 'product.id','warehouse.warehouse', 'product.category', 'product.product', 'min_stock' => 'coalesce(critical.min_stock, -1)'])
                ->leftJoin('critical', 'critical.product_id = product.id AND critical.warehouse_id = warehouse.id')
                ->where(['warehouse.id' => $this->_id]);

        $query = Warehouse::find()
                ->select('product.id as id,warehouse.warehouse as warehouse, product.category as category, product.product as product, coalesce(critical.min_stock, -1) as min_stock ')
                ->leftJoin('product', 'warehouse.product_id = product.id')
                ->leftJoin('critical', 'critical.product_id = product.id')
                ->where(['warehouse.id' => $this->_id]);
                ->andWhere('critical.warehouse_id = warehouse.id')
                ->asArray();

        $this->load($params);

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

        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;
        }

        $query->andFilterWhere(['category' => $this->category]);
        $query->andFilterWhere(['like', 'product', $this->product]);        

        return $dataProvider;
    }

Now you will get record as Array not as object.

Second way is, Define relation between Warehouse and Product in model using hasOne() or hasMany()

->joinWith('product', true,'cross join')

public function getProduct()
{
    return $this->hasOne(Product::className(), []);
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM