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.