Just to illustrate (in case I’m not being clear).
Currently if you have an EAV table with article information as follows:
ARTICLE TABLE (Article 'article' model)
ID article_name
5 "CPU"
6 "Cheese"
7 "CPU"
PROPERTY TABLE (Property 'props' model)
ID entity(article ID) attribute value
1 5 "frequency" "2.3 GHz"
2 5 "socket" "LGA 1567"
3 6 "smell" "gross"
4 6 "maturity" "old"
1 7 "frequency" "2.3 GHz"
If you had you relation between Article and Property you would have to set a "getPropertyValue($attribute)" method in your Article model that would return the value for a given property attribute then go (to get all cpus):
$criteria = new CDbCriteria(array('condition'=>`article_name` = "CPU"));
$dataProvider = new CActiveDataProvider('Article', array(
'criteria'=>$criteria)
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'id',
'article_name',
array(
'header'=>'Frequency',
'value'=>'$data->getPropertyValue("frequency")'
),
array(
'header'=>'Socket',
'value'=>'$data->getPropertyValue("socket")'
),
)
);
The immediate issues with this are that you can not set the dataProvider sort attributes for these fields.
"article.props" has no meaning nore does "article.props.frequency"
The other main one is that if you want to filter all CPUs with a frequency of "2.3 GHz" and "LGA 1567" sockets then the following does not work as it obviously tries to find rows that match both which is impossible:
$criteria = new CDbCriteria(array('condition'=>`article_name` = "CPU"));
$frequency_filter_crit = new CDbCriteria(array('together'=>true,
'with'=>array('props'=>array(
'condition'=>'attribute = "frequency" AND value = "2.3 GHz"'))));
$criteria->mergeWith($frequency_filter_crit);
$socket_filter_crit = new CDbCriteria(array('together'=>true,
'with'=>array('props'=>array(
'condition'=>'attribute = "socket" AND value = "LGA 1567"'))));
$criteria->mergeWith($socket_filter_crit);
$dataProvider = new CActiveDataProvider('Article', array(
'criteria'=>$criteria)
$this->widget('zii.widgets.grid.CGridView', array(
'dataProvider'=>$dataProvider,
'columns'=>array(
'id',
'article_name',
array(
'header'=>'Frequency',
'value'=>'$data->getPropertyValue("frequency")'
),
array(
'header'=>'Socket',
'value'=>'$data->getPropertyValue("socket")'
),
)
);
Ideally there would be some simple level of abstraction that would allow us to make a Property model that would be defined in relations() and would return data as if the EAV table were in fact a normal Table with attributes as columns and values as rows (dynamically).
So if you were looking for a CPU you would obtain a Property table like:
ID(optional and redundant) frequency socket
5 "2.3 GHz" "LGA 1567"
7 "2.3 GHz" NULL
Likewise you could save in the same fashion with $article->props->frequency = “1.2 GHz” or even search by attribute etc… that way. But maybe that’s pushing it.
I don’t know if this level of abstraction is doable/notrecommended, etc. But I thought I would throw it out there.