When adding the product attribute, set used_in_product_listing
, used_for_sort_by
and filterable
to true
.
You can do that with the following update script:
$installer = Mage::getResourceModel('catalog/setup', 'catalog_setup');
$installer->startSetup();
$installer->updateAttribute('catalog_product', 'product_type', 'used_in_product_listing', 1);
$installer->updateAttribute('catalog_product', 'product_type', 'used_for_sort_by', 1);
$installer->updateAttribute('catalog_product', 'product_type', 'is_filterable', 1);
$installer->endSetup();
Thats all, if if you are NOT using the flat catalog.
If you enable the flat catalog product feature, then you need to ensure that your custom source model implements the methods getFlatColums()
, getFlatIndexes()
and getFlatUpdateSelect()
.
If they are missing, your attribute won't be included in the generated flat tables, even if used_in_product_listing
is enabled.
Have a look at the class Mage_Eav_Model_Entity_Attribute_Source_Boolean
for an example. You can probably copy over the methods with minimal adjustments into your custom source model from there. Otherwise, please ask a new question.
A little extra debugging should get you where you need to be.
First, your error string/code, (104 (Incorrect attribute type)), can be traced to the following API exception.
#File: app/code/core/Mage/Catalog/etc/api.xml
<invalid_frontend_input>
<code>104</code>
<message>Incorrect attribute type.</message>
</invalid_frontend_input>
This means the API code used to trigger the exception will look something like this
$this->_fault('invalid_frontend_input');
That is, the name of the configured node in api.xml
is used as a shortcut for the exception. As you hinted in your question, this can be traced to the following bit of PHP code
#File: app/code/core/Mage/Catalog/Model/Product/Attribute/Api.php
//validate frontend_input
$allowedTypes = array();
foreach ($this->types() as $type) {
$allowedTypes[] = $type['value'];
}
if (!in_array($data['frontend_input'], $allowedTypes)) {
$this->_fault('invalid_frontend_input');
}
Here Magento's API code is checking the method's data paramater for a frontend_input
key. The "frontend input" is the type of UI form Magento will generate for editing this attribute's value in the Magento admin. Based on your soap request, it looks like your code failed to submit a value for frontend_input
.
<!-- no frontend input -->
<data xsi:type="ns1:catalogProductAttributeEntityToCreate">
<attribute_code xsi:type="xsd:string">testattribute</attribute_code>
<scope xsi:type="xsd:string">store</scope>
<default_value xsi:type="xsd:string"/>
<frontend_label xsi:type="ns1:catalogProductAttributeFrontendLabelEntity">
<store_id xsi:type="enc:string">0</store_id>
<label xsi:type="enc:string">Test label</label>
</frontend_label>
</data>
That's why Magento raised an exception. You need your SOAP calling code to submit a value that is both not blank and matches the one of the values returned by the $this->types()
method call (which populates the $allowedTypes
array). If you trace the call to types
, you'll see
public function types()
{
return Mage::getModel('catalog/product_attribute_source_inputtype')->toOptionArray();
}
Which, in turn, leads you to the catalog/product_attribute_source_inputtype
model (Mage_Catalog_Model_Product_Attribute_Source_Inputtype
), etc. Probably the quickest way to get a list of values here is to write some quick one off code to peek at the results of the toOptionArray
call.
In a stock system the following
$options = Mage::getModel('catalog/product_attribute_source_inputtype')->toOptionArray();
var_dump($options);
results in
array (size=8)
0 =>
array (size=2)
'value' => string 'text' (length=4)
'label' => string 'Text Field' (length=10)
1 =>
array (size=2)
'value' => string 'textarea' (length=8)
'label' => string 'Text Area' (length=9)
2 =>
array (size=2)
'value' => string 'date' (length=4)
'label' => string 'Date' (length=4)
3 =>
array (size=2)
'value' => string 'boolean' (length=7)
'label' => string 'Yes/No' (length=6)
4 =>
array (size=2)
'value' => string 'multiselect' (length=11)
'label' => string 'Multiple Select' (length=15)
5 =>
array (size=2)
'value' => string 'select' (length=6)
'label' => string 'Dropdown' (length=8)
6 =>
array (size=2)
'value' => string 'price' (length=5)
'label' => string 'Price' (length=5)
7 =>
array (size=2)
'value' => string 'media_image' (length=11)
'label' => string 'Media Image' (length=11)
Meaning the valid values for frontend_input
are
text
textarea
date
boolean
multiselect
select
price
media_image
If you're curious how Magento chooses these values, checkout the aforementioned toOptionArray
in
app/code/core/Mage/Catalog/Model/Product/Attribute/Source/Inputtype.php
and its parent class Mage_Eav_Model_Adminhtml_System_Config_Source_Inputtype
app/code/core/Mage/Eav/Model/Adminhtml/System/Config/Source/Inputtype.php
Best Answer
you can try adding this attribute to product attribute set.