Creating attribute sets and attributes programmatically - magento

I am using the code listed on the following link:
http://www.magentocommerce.com/wiki/5_-_modules_and_development/catalog/programmatically_adding_attributes_and_attribute_sets
Everything works until the point:
// Just add a default group.
else
{
$this->logInfo("Creating default group [{$this->groupName}] for set.");
$modelGroup = Mage::getModel('eav/entity_attribute_group');
$modelGroup->setAttributeGroupName($this->groupName);
$modelGroup->setAttributeSetId($id);
// This is optional, and just a sorting index in the case of
// multiple groups.
// $modelGroup->setSortOrder(1);
$model->setGroups(array($modelGroup));
}
I am unsure where the object reference would need to be set from - I am attempting to have this as a separate file that can be automated - I am running this file by doing a
require_once 'app/Mage.php';
Mage::app();
Any help in this would be greatly appreciated

You will need to have a block in your modules config.xml that looks like so
<resources>
<namespace_module_setup><!-- becomes folder under sql dir -->
<setup>
<module>Namespace_Module</module>
<class>Mage_Eav_Model_Entity_Setup</class>
</setup>
</namespace_module_setup>
</resources>
This will allow you to place your installer code in the directory that is in your XML. You need to make sure that the version listed on the installer file matches the <version>1.2.0</version> of your module otherwise Magento will not be able to run your installer. To add an attribute Set, you can use the following data, I have never use it, but the entityTypeId defines whether it is a customer, shipping, category, product entity, each 1, 2, 3, 4 respectively.
/**
* Add Attribute Set
*
* #param mixed $entityTypeId
* #param string $name
* #param int $sortOrder
* #return Mage_Eav_Model_Entity_Setup
*/
public function addAttributeSet($entityTypeId, $name, $sortOrder = null)
{
$data = array(
'entity_type_id' => $this->getEntityTypeId($entityTypeId),
'attribute_set_name' => $name,
'sort_order' => $this->getAttributeSetSortOrder($entityTypeId, $sortOrder),
);
$setId = $this->getAttributeSet($entityTypeId, $name, 'attribute_set_id');
if ($setId) {
$this->updateAttributeSet($entityTypeId, $setId, $data);
} else {
$this->_conn->insert($this->getTable('eav/attribute_set'), $data);
$this->addAttributeGroup($entityTypeId, $name, $this->_generalGroupName);
}
return $this;
}
This is the code for adding an attribute to a set, just change the attribute set data
//app/code/local/Namespace/Module/sql/Namespace_Module_setup/mysql4-install-1.0.0.php
$installer = $this;
/* #var $installer Mage_Eav_Model_Entity_Setup */
$installer->startSetup();
$data= array (
'attribute_set' => 'Default',
'group' => 'General',
'label' => 'Some Label',
'visible' => true,
'type' => 'varchar', // multiselect uses comma-sep storage
'input' => 'text',
'system' => true,
'required' => false,
'user_defined' => 1, //defaults to false; if true, define a group
);
$installer->addAttribute('catalog_product','attriute_code',$data)
$installer->endSetup();
The above is a working example of an attribute installation for a module.

There is an easier one-liner for this. Just extend Mage_Eav_Model_Entity_Setup for your install script and use something like this in your installer:
$installer = $this;
/* #var $installer Mage_Eav_Model_Entity_Setup */
$installer->startSetup();
$installer->addAttributeSet(Mage_Catalog_Model_Product::ENTITY, 'New Attribute Set Name');
$installer->endSetup();

You should implement this as an installer, so Magento loads it when the module is installed (or upgraded). $this, in the example, means that installer class.
You could create the module and the installer using https://bitbucket.org/alexsiri7/qbmagemoduleshell, and then adding that code there. That tool is a module creator I developed.

Related

how to remove 'order' type attribute

I want to write a script to delete an attribute which was created by an extension. This attribute is somehow more complicated than catalog/product attribute, as when created, it added a column in the database and can't be viewed via attribute manager.
At first, I looked at that extension install script and saw
$installer = new Mage_Sales_Model_Mysql4_Setup('sales_setup');
$installer->startSetup();
$installer->addAttribute('order', 'i4bulksend', array('type' => 'int', 'default' => '0', 'grid' => true));
$installer->endSetup();
So, to remove the attribute, I tried:
$installer = new Mage_Sales_Model_Mysql4_Setup('sales_setup');
$installer->startSetup();
$installer->removeAttribute('order', 'i4bulksend');
$installer->endSetup();
But no luck, the column 'i4bulksend' is still there

Magento Shipping method stops working after ALTER tables 'sales_flat_quote_address' and 'sales_flat_order_address'

I had ALTER tables 'sales_flat_quote_address' and 'sales_flat_order_address' to add a new column in order to add a custom field in Billing and Shipping process. But after doing that even the default shipping method stops working and it is not still not working after drop of this column. Below is the code I had used in my sql file of my module.
$installer = $this;
$installer->startSetup();
/* #var $addressHelper Mage_Customer_Helper_Address */
$addressHelper = Mage::helper('customer/address');
$store = Mage::app()->getStore(Mage_Core_Model_App::ADMIN_STORE_ID);
/* #var $eavConfig Mage_Eav_Model_Config */
$eavConfig = Mage::getSingleton('eav/config');
// update customer address user defined attributes data
$attributes = array(
'suburb' => array(
'label' => 'Suburb',
'type' => 'varchar',
'input' => 'text',
'is_user_defined' => 1,
'is_system' => 0,
'is_visible' => 1,
'sort_order' => 140,
'is_required' => 1,
'multiline_count' => 0,
'validate_rules' => array(
'max_text_length' => 255,
'min_text_length' => 1
),
),
);
foreach ($attributes as $attributeCode => $data) {
$attribute = $eavConfig->getAttribute('customer_address', $attributeCode);
$attribute->setWebsite($store->getWebsite());
$attribute->addData($data);
$usedInForms = array(
'adminhtml_customer_address',
'customer_address_edit',
'customer_register_address'
);
$attribute->setData('used_in_forms', $usedInForms);
$attribute->save();
}
$installer->run("
ALTER TABLE {$installer->getTable('sales_flat_quote_address')} ADD COLUMN suburb VARCHAR(255) CHARACTER SET utf8 DEFAULT NULL AFTER fax;
ALTER TABLE {$installer->getTable('sales_flat_order_address')} ADD COLUMN suburb VARCHAR(255) CHARACTER SET utf8 DEFAULT NULL AFTER fax;
");
$installer->endSetup();
by fiddling with shipping options I noticed it may stop checkout (not loading shipping methods) but it thows fatal error. Enable logging in your backend, then navigate to your checkout and try selecting everything up to non-working shipping method. when this is done, check your exception log, and var/reports folder. these may give you some information what has gone wrong in your particular case.

Magento sort by entity_id

Does anyone know how to make entity_id visible on the frontend as a sortable attribute? I went to manage attributes and I can't add entity_id as an attribute as it says
"The attribute code 'entity_id' is reserved by system. Please try another attribute code"
So I tried to do a search in the whole database I had Magento on using the following SQL CMD:
select attribute_id from eav_attribute where attribute_code = 'updated_at';
and it returned zero results, I tried other attributes and those showed...
Does anyone know how I can add entity_id as an attribute, as I can't even make it visible because I have no idea what the attribute_id # is even while searching the whole database for that value.
Here is the code I use to make a attribute visible on the admin section of magento:
UPDATE `catalog_eav_attribute`
SET `is_visible` = '1'
WHERE `catalog_eav_attribute`.`attribute_id` = 105;
I've tried searching high and low for days, and trying different variations - so stuck at this point, any help would be great.
I'm using Magento Enterprise 12.2 if that helps, but to be honest the DB is not much different than the community version the only differences are the added modules but when it comes to products it's pretty much the same.
This is surprisingly nasty - I can't see a way to do this simply in the DB, as entity_id isn't a standard attribute (it's really just a key field) and the core code repeats the same logic in three place (urgh).
It's also changed a lot since the older versions of Magento, so many of the tutorials and forum posts on this no longer apply.
What you can do is add "entity_id" in as a new sorting option, similar to the way "Best Value" exists as a sorting option. In the following example I've labelled it "Newest"
The usual caveats apply: You should do this in an extension (or at the least in /local/ overrides) but the three core file methods that need overriding in Community Edition 1.7 are:
Mage_Adminhtml_Model_System_Config_Source_Catalog_ListSort
public function toOptionArray()
{
$options = array();
$options[] = array(//benz001
'label' => Mage::helper('catalog')->__('Newest'),
'value' => 'entity_id'
); //end benz001
$options[] = array(
'label' => Mage::helper('catalog')->__('Best Value'),
'value' => 'position'
);
foreach ($this->_getCatalogConfig()->getAttributesUsedForSortBy() as $attribute) {
$options[] = array(
'label' => Mage::helper('catalog')->__($attribute['frontend_label']),
'value' => $attribute['attribute_code']
);
}
return $options;
}
Then Mage_Catalog_Model_Category_Attribute_Source_Sortby
/**
* Retrieve All options
*
* #return array
*/
public function getAllOptions()
{
if (is_null($this->_options)) {
$this->_options = array(
array(//benz001
'label' => Mage::helper('catalog')->__('Newest'),
'value' => 'entity_id'
), //end benz001
array(
'label' => Mage::helper('catalog')->__('Best Value'),
'value' => 'position'
));
foreach ($this->_getCatalogConfig()->getAttributesUsedForSortBy() as $attribute) {
$this->_options[] = array(
'label' => Mage::helper('catalog')->__($attribute['frontend_label']),
'value' => $attribute['attribute_code']
);
}
}
return $this->_options;
}
And then Mage_Catalog_Model_Config
public function getAttributeUsedForSortByArray()
{
$options = array(
'entity_id' => Mage::helper('catalog')->__('Newest'), //benz001
'position' => Mage::helper('catalog')->__('Position'),
);
foreach ($this->getAttributesUsedForSortBy() as $attribute) {
/* #var $attribute Mage_Eav_Model_Entity_Attribute_Abstract */
$options[$attribute->getAttributeCode()] = $attribute->getStoreLabel();
}
return $options;
}
With those in place, flush the cache and refresh and you can then select to sort by Newest/entity_id in the config and on the category page and on the frontend.
Note: even if you have caching turned off it's still a good idea to flush the cache - parts of the admin are cached even when caching is disabled.

Magento - Sort Products by ID

I am trying to set up my Magento store to sort the products in the order that they were added to the catalog (by product ID). However, I haven't been able to find a good example of how to set this up. It seems to do this by default in most of my product categories, but not all of them.
I thought the sort by "Position" option on the frontend would do this, but it doesn't seem to work for all of my categories. I am using community edition 1.6.1.
Thanks in advance!
Copy :
app/code/core/Mage/Catalog/Block/Product/List.php
to (create the appropiate folder ):
app/code/local/Mage/Catalog/Block/Product/List.php
Find the following line in List.php :
$this->_productCollection = $layer->getProductCollection();
add the following line below :
$this->_productCollection->joinField('category_product', 'catalog/category_product', 'product_id', 'product_id=entity_id', array('store_id'=> Mage::app()->getStore()->getId()), 'left');
// Here is the explain
/*
* #param string $alias 'category_product'
* #param string $table 'catalog/category_product'
* #param string $field 'name'
* #param string $bind 'PK(product_id)=FK(entity_id)'
* #param string|array $cond
* #param string $joinType 'left'
*
* default definition
* joinField($alias, $table, $field, $bind, $cond=null, $joinType='inner')
*
*/
Copy
app/code/core/Mage/Catalog/Model/Config.php
to
app/code/local/Mage/Catalog/Model/Config.php
Find the following line in Config.php :
'position' => Mage::helper('catalog')->__('Position')
Replace with :
$options = array(
'position' => Mage::helper('catalog')->__('Position'),
'product_id' => Mage::helper('catalog')->__('Product ID')
);
PS : I am writing this article from home which I haven't got Magento installation on my machine, so I didn't test but the structure is OK. If you face of any toruble, make sure field and table name.
Just in case someone needs:
Change this:
'product_id' => Mage::helper('catalog')->__('Product ID')
to this:
'entity_id' => Mage::helper('catalog')->__('Product ID')
Copy
app/code/core/Mage/Catalog/Model/Config.php
to
app/code/local/Mage/Catalog/Model/Config.php
Find the following line in Config.php :
$options = array(
'position' => Mage::helper('catalog')->__('Position')
);
Replace with :
$options = array(
// 'position' => Mage::helper('catalog')->__('Position')
'entity_id' => Mage::helper('catalog')->__('Last')
);
then change the default sorting direction to descending:
open app/design/frontend/your theme/your layout/layout/catalog.xml
add the line
<action method="setDefaultDirection"><dir>desc</dir></action>
in block
<block type="catalog/product_list_toolbar" name="product_list_toolbar" template="catalog/product/list/toolbar.phtml">
<block type="page/html_pager" name="product_list_toolbar_pager"/>
<!-- The following code shows how to set your own pager increments -->
here
</block>
</block>

Creating Custom Options on a Product using the Magento API

How do I add custom options to a product like you can in the backend, using the API.
Im using C# but if you know how do to this in Php, that would be helpful too.
I noticed that product has this:
var product = new catalogProductCreateEntity();
product.options_container = "blah";
And there is this:
catalogAttributeOptionEntity optionEntity = new catalogAttributeOptionEntity();
optionEntity.value = "sds";
optionEntity.label = "ere";
But I cant see a way of utilizing them, im not sure how to make a container, and the catalogAttributeOptionEntity does not have all the properties needed to make a custom option.
Look at the admin product controller. Yes it is possible.
/**
* Initialize data for configurable product
*/
if (($data = $this->getRequest()->getPost('configurable_products_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableProductsData(Zend_Json::decode($data));
}
if (($data = $this->getRequest()->getPost('configurable_attributes_data')) && !$product->getConfigurableReadonly()) {
$product->setConfigurableAttributesData(Zend_Json::decode($data));
}
$product->setCanSaveConfigurableAttributes((bool)$this->getRequest()->getPost('affect_configurable_product_attributes') && !$product->getConfigurableReadonly());
/**
* Initialize product options
*/
if (isset($productData['options']) && !$product->getOptionsReadonly()) {
$product->setProductOptions($productData['options']);
}
This is not documented anywhere (else), but at least in Magento 1.6 one can find the appropriate API methods for product options in the source code. (I don 't know since which version that feature exists.)
The API itself is defined in: app/code/core/Mage/Catalog/etc/api.xml
<catalog_product_custom_option translate="title" module="catalog">
<title>Catalog product custom options API</title>
<model>catalog/product_option_api</model>
<acl>catalog/product/option</acl>
<methods>
<add translate="title" module="catalog">
<title>Add new custom option into product</title>
<acl>catalog/product/option/add</acl>
</add>
<update translate="title" module="catalog">
<title>Update custom option of product</title>
<acl>catalog/product/option/update</acl>
</update>
<types translate="title" module="catalog">
<title>Get list of available custom option types</title>
<acl>catalog/product/option/types</acl>
</types>
<info translate="title" module="catalog">
<title>Get full information about custom option in product</title>
<acl>catalog/product/option/info</acl>
</info>
<list translate="title" module="catalog">
<title>Retrieve list of product custom options</title>
<acl>catalog/product/option/list</acl>
<method>items</method>
</list>
<remove translate="title" module="catalog">
<title>Remove custom option</title>
<acl>catalog/product/option/remove</acl>
</remove>
</methods>
</catalog_product_custom_option>
The called functions are defined in: app/code/core/Mage/Catalog/Model/Product/Option/Api.php
class Mage_Catalog_Model_Product_Option_Api extends Mage_Catalog_Model_Api_Resource
{
/**
* Add custom option to product
*
* #param string $productId
* #param array $data
* #param int|string|null $store
* #return bool $isAdded
*/
public function add( $productId, $data, $store = null )
/**
* Update product custom option data
*
* #param string $optionId
* #param array $data
* #param int|string|null $store
* #return bool
*/
public function update( $optionId, $data, $store = null )
/**
* Read list of possible custom option types from module config
*
* #return array
*/
public function types()
/**
* Get full information about custom option in product
*
* #param int|string $optionId
* #param int|string|null $store
* #return array
*/
public function info( $optionId, $store = null )
/**
* Retrieve list of product custom options
*
* #param string $productId
* #param int|string|null $store
* #return array
*/
public function items( $productId, $store = null )
/**
* Remove product custom option
*
* #param string $optionId
* #return boolean
*/
public function remove( $optionId )
/**
* Check is type in allowed set
*
* #param string $type
* #return bool
*/
protected function _isTypeAllowed( $type )
}
The $data-array also is a bit tricky, since it's keys partly depend on the selected option type. The basic $data-array looks like:
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => '10.0000',
'price_type' => 'fixed', // 'fixed' or 'percent'
'sku' => '',
),
),
);
The additional_fields always conatin at least one row with at least the columns price, price_type and sku. More additional fields (maf: …) may be added depending on the type. The types in the group select may have more than one row specified in additional_fields. The custom option types/type-groups are:
text (maf: 'max_characters')
field
area
file (maf: 'file_extension', 'image_size_x', 'image_size_y')
file
select (maf: 'value_id', 'title', 'sort_order')
drop_down
radio
checkbox
multiple
date
date
date_time
time
Examples for complete option data arrays:
// type-group: select, type: checkbox
$data = array (
'is_delete' => 0,
'title' => 'extra Option for that product',
'type' => 'checkbox',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'value_id' => '3',
'title' => 'Yes',
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 1,
),
1 => array (
'value_id' => 3,
'title' => 'No',
'price' => 0.00,
'price_type' => 'fixed',
'sku' => NULL,
'sort_order' => 2,
),
),
);
// type-group: text, type: field
$data = array (
'is_delete' => 0,
'title' => 'Custom Option Label',
'type' => 'text',
'is_require' => 0,
'sort_order' => 1,
'additional_fields' => array (
0 => array (
'price' => 10.00,
'price_type' => 'fixed',
'sku' => NULL,
'max_characters' => 150,
),
),
);
In the end I decided it cant be done via the API and went to the database directly.

Resources