Magento get category attribute value in Topmenu.php - magento

I have created a custom category attribute.
Now i need to access it's value in the _getHtml() function from Topmenu.php.
Can anyone tell me how to do this?:)
Any help is appreciated :)

Andrew's answer is the way i usually do it. However, it is important to note that if you are adding a custom attribute and if you want your store to work with and without the category flat tables enabled you need to make sure you have the following added to your code:
On your module's config.xml:
...
<frontend>
<category>
<collection>
<attributes>
<my_attribute /><!-- your attribute code here -->
</attributes>
</collection>
</category>
</frontend>
...
That will make sure your attribute is loaded when the default category collection is created on Mage_Catalog_Model_Resource_Category_Tree::_getDefaultCollection(). Now, that works great when the store is set NOT to use the category flat tables. In case you want to use the flat tables, you will also need to add your attributes in Mage_Catalog_Model_Resource_Category_Flat::_loadNodes. Find the code below, where the select is created, and also add your attribute code there:
$select = $_conn->select()
->from(
array('main_table' => $this->getMainStoreTable($storeId)),
array('entity_id',
new Zend_Db_Expr('main_table.' . $_conn->quoteIdentifier('name')),
new Zend_Db_Expr('main_table.' . $_conn->quoteIdentifier('path')),
'is_active',
'is_anchor',
'my_attribute')) /* add your attribute code here */
Only after that your attribute will show up on the Observer. Needless to say, do it using overwriting, never change the core code.

You won't be able to get that kind of data inside the TopMenu block, unless you make some changes.
The Navigation is built up using a generic tree structure which doesn't have an concept of what a category is, however this is built up elsewhere using the categories.
If you look inside Topmenu.php you will see where the Navigation is built up:
Mage::dispatchEvent('page_block_html_topmenu_gethtml_before', array(
'menu' => $this->_menu
));
This will fire off an event, which has an observer attached which will build up the navigation items for us, which happens to be:
Model: Mage_Catalog_Model_Observer
Method: _addCategoriesToMenu()
You can then add your new attribute into the Node data, which will then be available inside Topmenu.php
Example:
$categoryData = array(
'name' => $category->getName(),
'id' => $nodeId,
'url' => Mage::helper('catalog/category')->getCategoryUrl($category),
'is_active' => $this->_isActiveMenuCategory($category),
'my_attribute' => $category->getData('my_attribute') // Add our data in...
);
You should then be able to use this inside Topmenu::_getHtml()
echo $child->getData('my_attribute');

Just to complete Gabriel Queiroz Silva answer :
instead of editing or overriding Mage_Catalog_Model_Resource_Category_Flat::_loadNodes method, you can use observer :
Mage::dispatchEvent('catalog_category_flat_loadnodes_before', array('select' => $select));

Related

Symfony2, dynamically refresh form choices

I am creating a simple Blog system with symfony2. Each blog Post is bound to a certain amount of Tags.
Tags can be selected with checkboxes when creating a new blog post. Now I want to be able to dynamically add new tag-checkboxes to the form.
The AJAX part is done and working, I can add new tag names to the Tag entity and append the new checkboxes to the form.
The problem is when I submit the form, symfony2 doesn't recognize the new added tags because they don't belong to the Tag entity yet (at the time the form was generated).
For example: after submitting the form, I dump:
$tags = $form->get('tags')->getData();
The controller ignores the tags that were added through ajax.
I know it has to be solved with events somehow, I already read this documentation: http://symfony.com/doc/current/cookbook/form/dynamic_form_modification.html but can't figure out how to implement it for this specific case.
Here is my form builder for "PostType":
$builder
->add('title')
->add('content', 'textarea')
->add('tags', 'entity', array(
'class' => 'Bundle:Tag',
'property' => 'name',
'multiple' => true,
'expanded' => true,
))
->add('save', 'submit')
;
You can try to use this: Form Collection
Make sure you persist the newly added Tags before submit the form, and the checkboxes has the right names and values.
Names should be like "post[tags][]" and values should be the database ids of the Tag entities.

Magento: Add a multi-select attribute to categories with existing source?

I have an existing 'brand' select-attribute.
Is there a way to add a multiple-select field to categories with values from this attribute (Perhaps something similar to how I'd add a Yes/No attribute to categories)?
Here is an example of how you can create a product attribute with custom options. It works the same for categories.
Just change this:
$this->addAttribute('catalog_product', 'provider', array(
to this:
$this->addAttribute('catalog_category', 'provider', array(
The main idea is to give the attribute a custom source that is a model with a method that returns all the options.
TO get all the options of brand attribute, do this:
$options = Mage::getModel('eav/config')->getAttribute('catalog_product', 'brand')->getSource()->getAllOptions();

How to sort only top menu by category custom attribute in magento?

I have 15 categories created. and in left navigation i need categories in default order.
But in top menu I need to display categories in specific sort order. For that I have created attribute and followed this link.
So from above link, sorting is done by name, but i need to sort by int value stored in custom attribute
So please help anybody!!
You could use the function you mentioned with a small alteration: instead of getName() use getYourAttribute().
That is, however, not all. The nodes of the menu tree do not have your attribute in their internal data storage yet. To add it there, you'll have to create a class that overrides the catalog observer model, specifically the function Mage_Catalog_Model_Observer::_addCategoriesToMenu. this function is responsible for populating the top menu with category nodes.
Make sure that your overridden function adds your attribute in this procedure:
$categoryData = array(
'name' => $category->getName(),
'id' => $nodeId,
'url' => Mage::helper('catalog/category')->getCategoryUrl($category),
'is_active' => $this->_isActiveMenuCategory($category),
'your_attribute' => $category->getYourAttribute()
);
I feel uneasy about modifying the lib files with custom code, as the tutorial suggests, but if this is your last resort...

Magento Backendgrid: Click on a data entry and display its data

I used this tutorial (especially Lesson 6 and 7) to create my own backend grid for Magento: http://www.pierrefay.com/magento-developper-guide-howto-tutorial-5
Everything works fine. I can create new data entries for my grid. If I click on an entry the VarienForm is displayed again but all the text fields are empty. This seems as if Magento thinks I want to edit all the text fields. But actually I want it to display the entry data first. But it only shows empty fields.
Can anyone help me out here? Thanks a lot!
There are a lot of things that could be wrong with your implementation, but it's impossible to say without seeing your code. Nevertheless, I'm going to try. That tutorial looks fine to me, but I haven't run the code so I can't be sure. I'm inclined to think you might have just missed something. Working in grids & tabs can be particularly delicate at the best of times.
It does sound to me like it's one of two things. It sounds like either
A) Your model data is not being stored in the registry. That means the problem is in this part of the code:
<?php
class Pfay_Test_Adminhtml_IndexController extends Mage_Adminhtml_Controller_Action
{
...
public function editAction()
{
$testId = $this->getRequest()->getParam('id');
$testModel = Mage::getModel('test/test')->load($testId);
if ($testModel->getId() || $testId == 0)
{
Mage::register('test_data', $testModel);
}
What this section of code does is 'registers' the selected model in Magento's registry. Later in the code, you'll see that it calls:
$form->setValues(Mage::registry('test_data')->getData());
to populate your form fields.
Try putting commands like these in the code above:
var_dump($testId);
die();
or
print_r($testModel);
die();
and running it again. Is $testId being set? Is $testModel being loaded? Is the if statement for the registry loading? If not, trace the problem back.
or it might also be
B) Your form is not prepopulating data because the column names are wrong.
Look where the code says:
<?php
class Pfay_Test_Block_Adminhtml_Test_Edit_Tab_Form extends Mage_Adminhtml_Block_Widget_Form
{
protected function _prepareForm()
{
$form = new Varien_Data_Form();
$this->setForm($form);
$fieldset = $form->addFieldset('test_form', array('legend'=>'ref information'));
$fieldset->addField('nom', 'text',
array(
'label' => 'Nom',
'class' => 'required-entry',
'required' => true,
'name' => 'nom',
)
);
You need to ensure that "nom" is in fact one of your model's attribute names. Did you change the attribute names when you created your test model and forgot to change it here? Change these values accordingly.
I hope that this helps you to solve your problem. Good luck!

Magento - Can't delete mulitple select value in the product admin

I created a new attribute (multiple select) with some values, everything works fine but when I want to delete all the selected values for a product, I get the message "The product attribute has been saved." but the values are still selected.
Notes:
I press Ctrl + Click to unselect the last value before I save.
I set the parameter Value Required of my attribute to No
If I save a product without any value selected yet, then no values get selected
My Indexes are properly refreshed
See below two screens, on the left the parameters of my attribute and on the right my multiple select.
I'm running out of ideas so thanks for your help.
This is a known (annoying) behaviour of the Magento Adminhtml forms.
The problem is that if no value is selected for the multiselect, no value for that attribute is posted when the form is submitted.
On the server side Magento then loads the model, sets all the posted attribute values on the model and saves it.
Because no value was posted the original value that was loaded on the model wasn't updated.
As a solution for attributes with a custom source model I tend to provide an empty option with a special option value (e.g. -1). That value must not be 0 or an empty string.
Then I specify a backend model for that attribute that checks for that special value in the _beforeSave() method. If it is found the backend model unsets the attribute on the model instance.
Here is an example:
Source Model:
class Your_Module_Model_Entity_Attribute_Source_Example
extends Mage_Eav_Model_Entity_Attribute_Source_Abstract
{
const EMPTY = '-1';
public function getAllOptions()
$options = array(
array('value' => 1, 'label' => 'One'),
array('value' => 2, 'label' => 'Two'),
array('value' => 3, 'label' => 'Three')
);
if ($this->getAttribute()->getFrontendInput() === 'multiselect')
{
array_unshift($options, array('value' => self::EMPTY, 'label' => ''));
}
return $options;
}
}
Backend Model:
class Your_Module_Model_Entity_Attribute_Backend_Example
extends Mage_Eav_Model_Entity_Attribute_Backend_Abstract
{
public function beforeSave($object)
{
$code = $this->getAttribute()->getAttributeCode();
$value = $object->getData($code);
if ($value == Your_Module_Model_Entity_Attribute_Source_Example::EMPTY)
{
$object->unsetData($code);
}
return parent::beforeSave($object);
}
}
If you find a better workaround please let me know.
There is a feature called <can_be_empty> you need to go to your system.xml and add this configuration into your file:
<can_be_empty>1</can_be_empty>
then inspect the element and remove the selected="selected" and hit save, now you can save the multi-select without any values.
Yes I found this a big pain in the bum too BUT it is an improvement on the previous bug which caused drop down attribute selections to be wiped if you tried to update attributes for several products at once.
Anyway, here is my what I do if I want to remove an option from products using a drop down attribute:
Go to Manage attributes
Click Manage Label Options
Add a temporary option to the list
Assign this new attribute option to all the products you want to
change
Delete the temporary attribute option
All solved.
Add a non existent option to html via chrome/firefox developer tool, select that option and save.
eg.
<option value="99999999">Click this to unselect option</option>
Just ran into this problem in Magento 1.7.0.2, my solution :
Use Firefox with Firebug
right-click the multiselect list, choose Inspect with Element and you'll see something like this at the bottom in Firebug :
XLarge
Double-click on selected, right-click, cut, no more selected attribute and just save the page.

Resources