konapaz
(Konapaz)
February 14, 2014, 10:24am
1
Hi
I want to use namedscopes into CActiveDataProviders like that:
$dataProvider = new CActiveDataProvider(MyModel::model()->scopeA());
and in another widget
$dataProvider2 = new CActiveDataProvider(MyModel::model()->scopeB());
The problem is in the second provider $dataProvider2 has models that are applied both scopeA and scopeB !!
The solution is using MyModel::model()->resetScope(); before the second CActiveDataProvider
but is strange to be kept the first scope. each MyModel::model()->scopeA() should be a seperated task (or not ?)
am I missing something ?
konapaz
(Konapaz)
February 14, 2014, 11:54am
2
Notes:
If I use find(All e.t.c) instead CActiveDataProvider everything works correctly
MyModel::model()->scopeA()->findAll()
MyModel::model()->scopeB()->findAll()
So what is the problem ??
konapaz
(Konapaz)
February 14, 2014, 3:06pm
3
KonApaz:
Notes:
If I use find(All e.t.c) instead CActiveDataProvider everything works correctly
MyModel::model()->scopeA()->findAll()
MyModel::model()->scopeB()->findAll()
So what is the problem ??
According to this
https://code.google.com/p/yii/issues/detail?id=2619
The problem could be solved using resetScopes as I mentioned or using new instances like that
$a = new MyModel();
$dataProvider = new CActiveDataProvider($a->scopeA());
$b = new MyModel();
$dataProvider2 = new CActiveDataProvider($b->scopeB());
I don’t know exactly why CActiveRecord is designed in this way but the above code seems to works
redguy
(Maciej Lizewski)
February 14, 2014, 9:25pm
4
model is intended to be used in pipeline so every subsequent criteria modification (scopes) are combined. Query function (find, findAll, delete, etc) resets this criteria and you can start from begining. So typical usage is:
MyModel::model()->scopeA()->scopeB()->with(...)->findAll();
also ::model() function is kind-of singleton pattern so every call to that function returns same instance.
if you want to use model in two dataproviders you need to store filters and scopes in criteria objects like:
$model1 = MyModel::model()->scopeA();
$criteria1 = new CDbCriteria();
$model1->applyScopes( $criteria1 );
$dataProvider = new CActiveDataProvider($model1, array( 'criteria'=>$criteria1 ) );
...
...
$model2 = MyModel::model()->scopeB();
$criteria2 = new CDbCriteria();
$model2->applyScopes( $criteria2 );
$dataProvider = new CActiveDataProvider($model2, array( 'criteria'=>$criteria2 ) );
konapaz
(Konapaz)
February 15, 2014, 4:21pm
5
redguy:
model is intended to be used in pipeline so every subsequent criteria modification (scopes) are combined. Query function (find, findAll, delete, etc) resets this criteria and you can start from begining. So typical usage is:
MyModel::model()->scopeA()->scopeB()->with(...)->findAll();
also ::model() function is kind-of singleton pattern so every call to that function returns same instance.
if you want to use model in two dataproviders you need to store filters and scopes in criteria objects like:
$model1 = MyModel::model()->scopeA();
$criteria1 = new CDbCriteria();
$model1->applyScopes( $criteria1 );
$dataProvider = new CActiveDataProvider($model1, array( 'criteria'=>$criteria1 ) );
...
...
$model2 = MyModel::model()->scopeB();
$criteria2 = new CDbCriteria();
$model2->applyScopes( $criteria2 );
$dataProvider = new CActiveDataProvider($model2, array( 'criteria'=>$criteria2 ) );
Hi redguy
Good explanation, I suppose it could achieved the same thing using one instance. Using applyScopes, resetScopes called internally so …
$model1 = MyModel::model()->scopeA();
$criteria1 = new CDbCriteria();
$model1->applyScopes( $criteria1 );
$dataProvider = new CActiveDataProvider($model1, array( 'criteria'=>$criteria1 ) );
...
...
$model1 = MyModel::model()->scopeB();
$criteria2 = new CDbCriteria();
$model1->applyScopes( $criteria2 );
$dataProvider = new CActiveDataProvider($model1, array( 'criteria'=>$criteria2 ) );
… has the desired results. But is there any difference in the results with the below code ?
$a = new MyModel();
$dataProvider = new CActiveDataProvider($a->scopeA());
$b = new MyModel();
$dataProvider2 = new CActiveDataProvider($b->scopeB());
redguy
(Maciej Lizewski)
February 16, 2014, 3:12pm
6
KonApaz:
… has the desired results. But is there any difference in the results with the below code ?
$a = new MyModel();
$dataProvider = new CActiveDataProvider($a->scopeA());
$b = new MyModel();
$dataProvider2 = new CActiveDataProvider($b->scopeB());
::model() function creates class instance without scenario: new MyModel(null) which has impact on initialisation in constructor:
public function __construct($scenario='insert')
{
if($scenario===null) // internally used by populateRecord() and model()
return;
$this->setScenario($scenario);
$this->setIsNewRecord(true);
$this->_attributes=$this->getMetaData()->attributeDefaults;
$this->init();
$this->attachBehaviors($this->behaviors());
$this->afterConstruct();
}
so it may give different results (but does not have to ). Creating model without any param is same as new MyModel(‘insert’) You could however create your models passing null
and get very same results:
$a = new MyModel(null);
$dataProvider = new CActiveDataProvider($a->scopeA());
$b = new MyModel(null);
$dataProvider2 = new CActiveDataProvider($b->scopeB());