Hello Im currently writing a product syncronisation script for magento. I know how to add a new product with a given attribute set. However one of the atributes i am using is a size field. When a new size is encounterd I want to add this option to the attribute, I am wondering how to do this please?
Here is a script to add new option to attribute from Product View or Block:
$attributeInfo = Mage::getResourceModel('eav/entity_attribute_collection')
->setCodeFilter(YOUR_ATTRIBUTE_CODE)
->getFirstItem();
$options = $attributeInfo->getSource()->getAllOptions(false);
$_optionArr = array(
'value' => array(),
'order' => array(),
'delete' => array()
);
foreach ($options as $option) {
$_optionArr['value'][$option['value']] = array($option['label']);
}
$_optionArr['value']['option_1'] = array(NAME_OF_OUR_NEW_OPTION);
$attribute->setOption($_optionArr);
$attribute->save();
...
Put a file ie: test-attribute.php in your Magento root.
<?php
// Include and start Magento
require_once dirname(__FILE__).'/app/Mage.php';
Mage::app()->setCurrentStore(Mage_Core_Model_App::ADMIN_STORE_ID);
// Load attribute model and load attribute by attribute code
$model = Mage::getModel('catalog/resource_eav_attribute')->load('some_dropdown_attribute', 'attribute_code');
// Get existing options
$options = $model->getSource()->getAllOptions(false);
// Get the count to start at
$count = count($options) + 1;
// Prepare array
$data = array(
'option' => array(
'value' => array(),
'order' => array()
)
);
// You can loop here and increment $count for multiple options
$key = 'option_'.$count;
$data['option']['value'][$key] = array('Test '.$count);
$data['option']['order'][$key] = 0;
// Add array to save
$model->addData($data);
// Save
$model->save();
Should create a new option called Test X on the attribute. Tested on Magento Enterprise 1.11.2
After doing some more looking around I finaly found out how to do it. Then I found a extension to xml-api that extends api to support operations such as one i wanted to do.
The extension i used was MagentoeXtended
Related
I try to add multiple custom values to my product options while adding the product to cart. It works fine but the problem is that it loops through all options and stores only the last option to the $optionData array.
protected $customOption;
\Magento\Catalog\Api\Data\CustomOptionInterface $customOption
$this->customOption = $customOption;
Execute
$customOptionInterface = $this->customOption;
$optionData = array();
foreach ($product->getOptions() as $o) {
$optionKeyIndex = array_search($o->getTitle(), array_column($optionsArray, 'name'));
$optionData[] = $customOptionInterface->setdata(array(
"option_id" => $o->getId(),
"option_value" => "TEST"
));
}
$productOption = $this->productOption;
$extAttribute = $productOption->getExtensionAttributes();
$extAttribute->setCustomOptions($optionData);
$productOption->setExtensionAttributes($extAttribute);
$cartItem->setProductOption($productOption);
$newItem = $this->itemRepository->save($cartItem);
The reason for it has to be the "$customOptionInterface->setdata". Without it all individual array will be added to $optionData but of course I can't use it this way. Any idea what's wrong?
I appreciate your help :)
I have 2 custom option text fields associated with a product called Location To and Location From,
I have set up a Module that has an Observer for checkout_cart_add_product_complete with a method called getLocationCoords, how would I get access to these two fields from the event object that passed to my method.
I need these 2 fields so I can reverse geocode them which I think I will be able to do myself.
Once I get the 2 sets of coordinates how would I go about storing them with the product so I would be able to see them associated with the product when an order is paced?
=======================
edit addded ============================
What i have tried so far
public function getLocationCoords(Varien_Event_Observer $observer)
{
// Retrieve the product being updated from the event observer
$product = $observer->getEvent()->getProduct();
// Write a new line to var/log/product-updates.log
$name = $product->getName();
$sku = $product->getSku();
Mage::log(
"{$name} ({$sku}) updated",
null,
'product-updates.log'
);
foreach ($product->getOptions() as $o) {
$type = "Custom Option TYPE: " . $o->getType();
$title = "Custom Option TITLE: " . $o->getTitle();
Mage::log(
"{$type} ({$title}) custom option {$o}",
null,
'product-updates.log'
);
}
}
It all works except getting the values of the custom options, i will try the answer below and see where i get
when i print out the var dump of the option object this is what i get
2012-12-11T15:19:45+00:00 DEBUG (7): array (
'option_id' => '1',
'product_id' => '1',
'type' => 'field',
'is_require' => '1',
'max_characters' => '0',
'sort_order' => '0',
'default_title' => 'Location To',
'title' => 'Location To',
'default_price' => '0.0000',
'default_price_type' => 'fixed',
'price' => '0.0000',
'price_type' => 'fixed',
)
there is no value to the object
There is also this event
$eventName = sprintf('catalog_product_type_prepare_%s_options', $processMode);
Mage::dispatchEvent($eventName, array(
'transport' => $transport,
'buy_request' => $buyRequest,
'product' => $product
));
With processMode either full or lite. The buy_request should have your details and you can then add a new option on the product
$product->addCustomOption('my_option','my_value');
Not tested but do let us know how you are getting on.
I believe that by the time that event is dispatched you will need to access the sales quote object from the cart session, which smells bad to me. Try the checkout_cart_product_add_after [link] event and get access to the quote item as follows:
public function geoConversion ($obs)
{
$item = $obs->getQuoteItem();
/* #var $item Mage_Sales_Model_Quote_Item */
//I believe the custom options will be in here, not sure
$buyRequest = $item->getBuyRequest();
// your logic
}
I haven't checked this, but it's a bit better an event to use. However, there are lots of considerations when customizing the add to cart process (admin-created orders and updates of existing cart items for example), so test, test, test. Also, there is another event which may be useful/more appropriate: sales_quote_product_add_after [link].
Further, this behavior could also be achieved by giving these products a custom type model based on - or by observing events dispatched in - Mage_Catalog_Model_Product_Type_Abstract.
It's dizzying.
I was able to get to get access to quote item and from that i was able to access the values of the custom attributes. I had two options and after some debugging i realised my options were being called option_1 and option_2 , from that i was able to get the value and set them to my variables.
public function getLocationCoords(Varien_Event_Observer $observer)
{
$item = $observer->getQuoteItem();
$locationFrom = '';
$locationTo = '';
foreach ($item->getOptions() as $o) {
if($o['code'] == 'option_2'){
$locationFrom = $o['value'];
}
if($o['code'] == 'option_1'){
$locationTo = $o['value'];
}
}
Mage::log("the location from = ".$locationFrom);
Mage::log("the location to = ".$locationTo);
}
I want to update/add the options of a drop down attribute in Magento though code (programmatically). I have found how to add attribute options, but how can I update the option values.
Example:
Suppose the attribute is 'manufacturer'. I have added three options man1, man2, man3. Now through my custom code I want to change the label of man1 to man11 and man2 to man22. How can I achieve that?
Thanks.
Well, I found a solution myself. See complete details here.
//Get the eav attribute model
$attr_model = Mage::getModel('catalog/resource_eav_attribute');
//Load the particular attribute by id
//Here 73 is the id of 'manufacturer' attribute
$attr_model->load(73);
//Create an array to store the attribute data
$data = array();
//Create options array
$values = array(
//15 is the option_id of the option in 'eav_attribute_option_value' table
15 => array(
0 => 'Apple' //0 is current store id, Apple is the new label for the option
),
16 => array(
0 => 'HTC'
),
17 => array(
0 => 'Microsoft'
),
);
//Add the option values to the data
$data['option']['value'] = $values;
//Add data to our attribute model
$attr_model->addData($data);
//Save the updated model
try {
$attr_model->save();
$session = Mage::getSingleton('adminhtml/session');
$session->addSuccess(
Mage::helper('catalog')->__('The product attribute has been saved.'));
/**
* Clear translation cache because attribute labels are stored in translation
*/
Mage::app()->cleanCache(array(Mage_Core_Model_Translate::CACHE_TAG));
$session->setAttributeData(false);
return;
} catch (Exception $e) {
$session->addError($e->getMessage());
$session->setAttributeData($data);
return;
}
You might want to try extending the AttributeController located at app\code\core\Mage\Adminhtml\controllers\Catalog\Product\AttributeController.php and override the saveAction() method to suit your needs.
I have created a custom module which displays a tab and a section in admin configuration panel to manage customer attributes.
I have loaded all customer attributes with a check box each.
This is my code for displaying all customer attributes as checkboxes. I want the checkbox value selected from here to be added as a column in Manage Customer Grid.
Model/Attributes.php
$attributes = Mage::getModel('customer/entity_address_attribute_collection');
$result = array();
foreach ($attributes as $attribute)
{
if (($label = $attribute->getFrontendLabel()))
$result[$attribute->getId()] = $label;
}
$attributes1 = Mage::getModel('customer/entity_attribute_collection');
$result1 = array();
foreach ($attributes1 as $attribute1)
{
if (($label1 = $attribute1->getFrontendLabel()))
$result1[$attribute1->getId()] = $label1;
}
$final = array_merge($result, $result1);
return $final;
Now based on selection of these check boxes, I would like to add an extra column in 'Manage Customer' Grid.
I tried retrieving the value of selected checkbox but I just get the array index number.
Mage::getStoreConfig('sectionname/groupname/fieldname');
Can some one tell me how to fetch the the selected checkbox value and add a column based on the selection represented by that checkbox?
Thanks in advance.
When you use array_merge you are destroying the correct indexes, which are supposed to be the attribute IDs. Also it's good practice to give your variables meaningful names.
$result = array();
$addressAttributes = Mage::getModel('customer/entity_address_attribute_collection');
foreach ($addressAttributes as $addressAttribute)
{
if (($addrlabel = $addressAttribute->getFrontendLabel()))
$result[$addressAttribute->getId()] = $addrlabel;
}
$customerAttributes = Mage::getModel('customer/entity_attribute_collection');
foreach ($customerAttributes as $customerAttribute)
{
if (($custlabel = $customerAttribute->getFrontendLabel()))
$result[$customerAttribute->getId()] = $custlabel;
}
return $result;
I suppose the next step is to remove the columns that your grid's parent will add, these are stored in a grid's protected _columns property. Not all columns are to be removed, such as the massaction column. Then add your chosen columns back in.
protected function _prepareColumns()
{
parent::_prepareColumns();
// remove the excess columns here
$attributeIds = Mage::getStoreConfig('sectionname/groupname/fieldname');
$attributes = Mage::getModel('eav/entity_attribute')->getCollection()
->addFieldToFilter('attribute_id', array('in' => $attributeIds));
foreach ($attributes as $attribute)
{
$options = array();
if ($attribute->getFrontendInput() == 'select') {
foreach ($attribute->getSource()->getAllOptions() as $value) {
$options[$value['value']] = $value['label'];
}
}
$this->addColumn($attribute->getCode(), array(
'index' => $attribute->getCode(),
'header' => $attribute->getFrontendLabel(),
'type' => $attribute->getFrontendInput(),
'options' => $options
));
}
return $this;
}
This way may lose useful formatting like column widths, etc. so a more sophisticated way would be to work out which columns are already in place and leave them, then only remove those that haven't been selected.
I would, in your module, set in config.xml that you are overwrting the Block Mage_Adminhtml_Block_Customer_Grid with your own block (which inherits from Mage_Adminhtml_Block_Customer_Grid) and in your own block make a function
protected function _prepareColumns()
{
$this->addColumn('mycolumn', array(
'header' => Mage::helper('customer')->__('My Column'),
'index' => 'key',
));
return parent::_prepareColumns();
}
Without knowing more about your data its hard to give better advice, but this should be enough to get you started.
I want a simple filter form, and a table below it. When the user changes the option on the select form, the table automaticaly changes. I think thats done with ahah.
I want this (some things can change, like the fieldset containing the table, and other stuff):
But working.. of course..
I'm currently showing that page using one function. It's a complete mess and something like "NEVER DO THIS", but i'm researching and trying some stuff as i'm a drupal learner.
This is the relevant code:
form = array();
ahah_helper_register($form, $form_state);
//query here, build $options for the select
$form['listar_veics'] = array(
'#type' => 'fieldset',
'#prefix' => '<div id="listar-veics-wrapper">',
'#suffix' => '</div>',
'#tree' => TRUE,
);
if (!isset($form_state['values']['listar_veics']['filial']))
$choice = 1;
else
$choice = $form_state['values']['listar_veics']['filial'];
$form['listar_veics']['filial'] = array(
'#type' => 'select',
'#title' => "Listar veĆculos da filial",
'#options' => $filiais,
'#default_value' => $choice,
'#ahah' => array(
'event' => 'change',
'path' => ahah_helper_path(array('listar_veics')),
'wrapper' => 'listar-veics-wrapper',
'method' => 'replace',
),
);
//query for the rows i wanna show
//building $data array, the rows array
//building $header, as an array of strings
$table = theme_table($header, $data);
$page = drupal_render($form);
$page .= $table;
return $page;
So in this code, drupal will only replace the form itself, when i change the option on the select, it shows the new value on the select, but the table isnt rendered again thus not changing.
Thanks, apreciate every suggestion.
I recommend looking at the views module.
http://drupal.org/project/views
With that installed, you can create a custom query.
Add all the fields that you would like displayed on your table. (Placa, Marca)
Then add any filters that you would like to limit your query by. (Listar veiculos da filial)
When adding the filter you "expose" it so that when looking at the query, you can change the options on the page.
Then if you want to view what you just made, you need to add a display. If you make it a page display, you can set the path directly to the table.
For more information might I recommend http://gotdrupal.com/videos/drupal-views-tutorial.
If you want neater exposed fields I might also recommend http://drupal.org/project/better_exposed_filters
To expand Asimov's answer here is a code example (for Drupal 7) that shows a taxonomy term filter for selecting nodes. The selected terms are stored in the session and used in the query to filter the results.
You can put it in a custom module. It doesnt require Views or any other contributed modules.
In the example code below the name of the custom module is tic . Rename tic to the name of your custom module.
Four elements are needed:
A function that outputs the filter and fetches and outputs the results
The filter form
A custom submit function that stores the chosen filter options in the session
A reset function that clears the session
Use hook_menu() to call tic_fetch_results().
Fetch, filter, output results
This example uses a dynamic query because it is easy to extend with conditions.
/**
* Filters, fetches and outputs results
*/
function tic_fetch_results() {
// Adds filter form to the build array.
$form = drupal_get_form('tic_term_filter_form');
$output = drupal_render($form);
$node_types = array('article', 'page', 'blog_post');
// Sets up dynamic query
$query = db_select('node', 'n')
->extend('PagerDefault')
->limit(33)
->fields('n', array('nid', 'title'))
->condition('n.type', $node_types, 'IN')
->condition('n.status', 1);
// Fetches selected values from session and applies them to the query.
if (isset($_SESSION['form_values']['terms']) && count($_SESSION['form_values']['terms']) > 0) {
$query->join('field_data_field_tags', 'tags', 'n.nid = tags.entity_id');
$query->condition('tags.field_tags_tid', $_SESSION['form_values']['terms'], 'IN');
$query->condition('tags.bundle', $node_types, 'IN');
}
$result = $query->execute();
$items = array();
foreach ($result as $row) {
$items[] = array('data' => $row->nid . ' - ' . $row->title);
// do something interesting with the results
}
$output .= theme('item_list', array('items' => $items, 'title' => '', 'type' => 'ul', 'attributes' => array()));
$output .= theme('pager');
return $output;
}
Construct the form
The taxonomy terms options list is populated from the Vocabulary tags
/**
* Implements hook_form().
*/
function tic_term_filter_form($form, &$form_state) {
// Loads terms from the Tags vocabulary and use as select options.
$vocab = taxonomy_vocabulary_machine_name_load('tags');
$terms = taxonomy_get_tree($vocab->vid);
$term_options = array();
foreach ($terms as $term) {
$term_options[$term->tid] = $term->name;
}
// Sets the values that are stored in session as default.
$storage = (isset($_SESSION['form_values']) ? $_SESSION['form_values'] : 0);
$selected_terms = isset($storage['tags']) ? $storage['tags'] : NULL;
$form['terms'] = array(
'#title' => 'Filter by terms',
'#type' => 'select',
'#options' => $term_options,
'#multiple' => TRUE,
'#default_value' => $selected_terms,
);
$form['submit'] = array(
'#type' => 'submit',
'#value' => t('Filter'),
);
$form['reset'] = array(
'#type' => 'submit',
'#value' => t('Reset'),
'#weight' => 30,
'#submit' => array('tic_tools_reset'),
);
return $form;
}
Store selected values in the session
/**
* Implements hook_form_submit().
*/
function tic_term_filter_form_submit(&$form, &$form_state) {
// Stores form values in session.
$_SESSION['form_values'] = $form_state['values'];
}
Reset the filter
/*
* Clears set filters.
*/
function tic_tools_reset() {
if (isset($_SESSION['form_values'])) {
unset($_SESSION['form_values']);
}
drupal_goto(current_path());
drupal_set_message('Filters were reset');
}
The following page on the drupal forum contains a very clear explanation of the drupal form process and what to do in your specific case. See the answer from user Jaypan.
http://drupal.org/node/1770512
To sum his answer up:
Create a submit button on the form to submit the chosen filter. This button has it's own submit function:
$form['submit_filter'] = array(
'#type' => 'submit',
'#value' => 'Apply the filter',
'#submit' => array('apply_filter')
);
Create the submit function for applying your filter. In this function store the value of the filter to save it for the next form building when the page refreshes. Also set $form_state['rebuild'] to TRUE.
function apply_filter($form, &$form_state)
{
// Save the filter
$form_state['filter'] = $form_state['values']['filter'];
$form_state['rebuild'] = TRUE;
}
Now you will have access to the filter value the next time the form is built. Just check for the existence of the value like:
if (isset($form_state['filter']))
{
// do your filtering here
}
Hope this helps.