Reputation: 1009
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;
}
Upvotes: 1
Views: 1155
Reputation: 1
->joinWith('product', true,'cross join')
public function getProduct()
{
return $this->hasOne(Product::className(), []);
}
Upvotes: -1
Reputation: 5731
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()
Upvotes: 0
Reputation: 133380
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 );
Upvotes: 1