2. Alex Gotgelf
Senior Software Developer at Eltrino
Contacts:
alex@eltrino.com
ramzes3988
http://www.linkedin.com/in/gotgelf
Monday, October 14, 13
3. Lecture Overview
‣ Magento Attributes EAV concepts
‣ Not trivial problems and solutions
Monday, October 14, 13
4. EAV History
EAV has quite a long history. Some of its earliest applications
were storage systems for clinical data back in 1970s.
As a storage method EAV borrows from early object-oriented
languages. SIMULA 67 is cited as one such influence. Functional
languages such as LISP are also known to have contributed to the
development of EAV. They contain storage structures that record
object information in attribute-value pairs – a principle
fundamental to EAV.
Monday, October 14, 13
5. EAV conception
‣ E - Entity
‣ A - Attribute
‣ V - Value
Monday, October 14, 13
6. EAV conception
Eav becomes especially useful when the
following conditions are presented:
‣ Entity attributes vary significantly in terms of
data type
‣ The number of possible entity types is large
and entity types have individual sets of
attributes
Monday, October 14, 13
7. Advantages of EAV
‣ Scalability - you can change your data
without changing the structure of db
‣ Flexible mechanism to work with attributes
associated to entity
Monday, October 14, 13
8. Weakness of EAV
‣ Performance (complex join structures etc...)
Monday, October 14, 13
19. Problem #1
Problem #1 - Solution
y based
2 - jquer
Select
ent for
e placem
r
Select Boxes
Monday, October 14, 13
20. Problem #1
Problem #1 - Solution
http://ivaynberg.github.io/select2/
Monday, October 14, 13
21. Problem #1
Select2 Advantages
‣
‣
Enhancing native selects with search
‣
Nesting opt-groups: native selects only support one level of
nested. Select2 does not have this restriction.
‣
‣
Tagging: ability to add new items on the fly.
‣
etc ...
Loading data from JavaScript: easily load items via ajax and have
them searchable.
Working with large, remote datasets: ability to partially load a
dataset based on the search term.
Monday, October 14, 13
34. Problem #2
Problem #2
• Change Opt1, change Opt300
• Click “Save Attribute” button
• As result Opt1 will be changed and Opt300
will not
Monday, October 14, 13
35. Problem #2
Problem #2
Problem: POST request is truncated, so
we need to increase it’s size
Solution: increase max_input_vars (since
PHP 5.3.9 ) variable, by default it’s 1000
Monday, October 14, 13
36. Problem #3
Problem #3
Product Select Attribute with Large Options Set
(several thousands of options) at the Frontend
Monday, October 14, 13
47. Problem #4
Problem #4
Layer Navigation Issues
(a lot of attributes or a lot of options)
Monday, October 14, 13
48. Problem #4
Problem #4
For each attribute which is used for Layer Navigation, it will
make a call to getAllOptions() method at
Mage_Eav_Model_Entity_Attribute_Source_Table model
and during this call we will load all attribute option
collection !!!
Monday, October 14, 13
49. Problem #4
Problem #4
PHP
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
...
$collection = Mage::getResourceModel('eav/
entity_attribute_option_collection')
->setPositionOrder('asc')
->setAttributeFilter($this->getAttribute()->getId())
->setStoreFilter($this->getAttribute()->getStoreId())
->load();
...
}
Monday, October 14, 13
50. Problem #4
Problem #4 - Solution
n s m e t h od
e t Al l O p t i o
e custom g
reat
es for all
C
ad all valu
hich will lo
w
s at once
attribute
variable)
sing static
(u
Monday, October 14, 13
51. Problem #4
Problem #4 - Solution
PHP
public function getAllOptions($withEmpty = true, $defaultValues = false)
{
...
if (!isset($this->_options[$storeId])) {
$options = $this->_getAttributeOptionsByStore($storeId,
$this->getAttribute()->getId());
$this->_options[$storeId]
= $options['store'];
$this->_optionsDefault[$storeId] = $options['default'];
}
...
}
Monday, October 14, 13
52. Problem #4
Problem #4 - Solution
PHP
protected static $_predefinedOptions = array();
protected static function _getAttributeOptionsByStore($storeId, $attributeId)
{
if (!isset(self::$_predefinedOptions[$storeId])) {
// load options collection
}
if (isset(self::$_predefinedOptions[$storeId][$attributeId])) {
return self:: $_predefinedOptions[$storeId][$attributeId];
}
}
Monday, October 14, 13
53. Problem #4
Problem #4
Preconditions: one dropdown attribute
with 10000 options, used at layer
navigation. Cache is disabled.
Monday, October 14, 13
57. Problem #5
if backend_type is varchar, our attribute will not work
correctly at Layer Navigation (as example - default Magento
attribute ‘manufacture’), use int backend type instead.
PHP
protected function _getIndexableAttributes($multiSelect)
{
$select = ...
if ($multiSelect == true) {
$select->where('ea.backend_type = ?', 'varchar')
->where('ea.frontend_input = ?', 'multiselect');
} else {
$select->where('ea.backend_type = ?', 'int')
->where('ea.frontend_input = ?', 'select');
}
return $this->_getReadAdapter()->fetchCol($select);
}
Monday, October 14, 13
58. Problem #6
Problem #6
Load all category collection
(getStoreCategories() method) to add
needed attributes for each item in the
collection.
Monday, October 14, 13
59. Problem #6
Mage_Catalog_Model_Resource_Category_Tree
PHP
protected function _getDefaultCollection($sorted = false)
{
$this->_joinUrlRewriteIntoCollection = true;
$collection = Mage::getModel('catalog/category')->getCollection();
$attributes = Mage::getConfig()->getNode('frontend/category/
collection/attributes');
if ($attributes) {
$attributes = $attributes->asArray();
$attributes = array_keys($attributes);
}
$collection->addAttributeToSelect($attributes);
...
}
Monday, October 14, 13
63. Step 1 - add Observer to create new mass action
PHP
public function addNewActionToProductGrid($observer)
{
$block = $observer->getBlock();
if ($block instanceof Mage_Adminhtml_Block_Catalog_Product_Grid){
$attributeSets = Mage::getResourceModel('eav/
entity_attribute_set_collection')
->setEntityTypeFilter(Mage::getModel('catalog/product')>getResource()->getTypeId())
->load()
->toOptionHash();
...
Monday, October 14, 13
66. Step 3 - remove old attribute’s values
PHP
protected function _cleanOldAttributeValues($product, $attributes)
{
$productResource = $product->getResource();
foreach ($attributes as $attribute) {
if (!in_array($attribute['code'], $this->_fixAttributes)) {
$product->setData($attribute['code'], null);
$productResource->saveAttribute($product, $attribute['code']);
}
}
return $this;
}
Monday, October 14, 13
67. There are two ways of constructing a
software design: One way is to make it so
simple that there are obviously no
deficiencies, and the other way is to make it
so complicated that there are no obvious
deficiencies. The first method is far more
difficult.
(Tony Hoare)
Monday, October 14, 13