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
Ha...this is a good one.
The field in the db that determines the text under the attribute field is note
from the eav_attribute
table.
I never noticed that you can't change that from the UI.
I've created a lot of attributes that have a 'comment' below the fields but never change one.
To add that you need to specify this in the install script:
$this->addAttribtue('catalog_product', 'attribute_code_here', array(
....
'note' => 'This will be displayed below the field',
....
));
To change it for one attribute you can add this in an install/upgrade script.
$this->updateAttribute('catalog_product', 'attribute_code_here', 'note', 'This will be displayed below the field');
I can't believe that I've missed this in all the million versions I've used so far.
[EDIT]
See the definition of the meta_description
attribute in Mage_Catalog_Model_Resource_Setup::installEntities()
.
'meta_description' => array(
'type' => 'varchar',
'label' => 'Meta Description',
'input' => 'textarea',
'required' => false,
'note' => 'Maximum 255 chars',
'class' => 'validate-length maximum-length-255',
'sort_order' => 3,
'global' => Mage_Catalog_Model_Resource_Eav_Attribute::SCOPE_STORE,
'group' => 'Meta Information',
),
Best Answer
Therefore a better way to accomplish this would to to add this field to your order item table.
See product attribute to quote item and order item and Adding custom product attribute to quote and order items