Joomla Get menu id from names - joomla

I am in joomla 2.5 and I try to get the id of a menu, I have the name, the alias
exemple :
menu = FAQ-> menu item =FAQ
I have try :
$app = JFactory::getApplication('site');
$params = $app->getParams();
$idfaq = $params->get('content_id_faq');
but i am a newbie so I dont even know if content_id_faq is correct
thanks

Have a look at here for more information on how to get the correct item.

There is no guarantee that either the menu item alias or the article alias must be unique within either the #__menu or #__content table, they just need to be unique within that menu-parent item branch or the category, respectively. Since you are making something custom for a specific site you could modify the queries in the other answer to reflect this; I would do that rather than assuming no one in the future is ever going to use the same aliases. Of course you could write a plugin to basically make those aliases reserved words. Also in your code I would force that to cache so you aren't constantly doing that query.

Related

Prestashop: Get id of parent category

I've faced the problem while coding my very first prestashop template. So what I want to do is to get the list of all sub categories which are under the same parent category. So running foreach loop I need to send parent category id.
In the internet there's not so much information about prestas' coding, modules or stuff, but I found two possible solutions.
One was: {$product->id_category_default} but that works only inside a product page (?) Maybe I'm wrong and it's possible to get a solution with this?
Another way sounds bit desperate: {$cookie->last_visited_category}
problem with this one, that it works only if you come from parent category directly, but fails when followed by direct link or any other way.
Also I was thinking of writing php function, which sends MySQL query and returns parent category id, but is this optimal way to do? Also I haven't tried writing my own php functions in smarty, seems it woks in some different way than just calling function.
So to conclude, do anyone knows how to get parent category id without separate php function and if it's so desperate, where and how to define your own php functions for smarty and how to call them.
I'm working with prestashop 1.4.
Thank you for your attention.
I've used this code in a module, you might need to adapt it but basically, the id of the parent category is stored in the database.
$parentCategoryList = array(2, 3, 4, 5);
if(!in_array($id_category, $parentCategoryList)){
$parentCategory = Db::getInstance(_PS_USE_SQL_SLAVE_)->ExecuteS('
SELECT DISTINCT c.id_parent
FROM '._DB_PREFIX_.'category c
WHERE c.id_category = '.(int)($id_category)
);
$id_category_parent = $parentCategory[0]['id_parent'];
}
else{
$id_category_parent = $id_category;
}
In my code, the $parentCategoryList stores the id of my main categories (change it to your values). Then it checks if the category you're viewing ($id_category) is a main category. If not, it looks for the parent category in the database.
I am not really happy about the use of an array to store manually the main categories, but it works.
Hope this helps!

Magento EAV: how to hard delete an attribute value?

Let's ask the question clearly before entering into the details:
Is there a way of hard deleting an attribute value from a product?
By hard I mean, removing the row from the database and not only setting the value to null or empty.
Now, the details:
I'm currently confronted to a problem on Magento.
Many product in my store have user defined attributes that are not related to the product. For example, let's say we have a bag product, among other products like t-shirts,dresses,pants,etc.:
Our bag product has only configurable 1 attribute: color.
Our T-Shirt product has 2 configurable attributes: color and tshirt_size.
Our Dress product has 2 configurable attributes: color and dress_size
My current problem is that when I retrieve my Bag product from the database, the attributes stored in my product are: color, tshirt_size and dress_size.
I suspect that it is because on our store you can change the attribute set of a product (thanks to the FlagBit ChangeAttributeSet community extension).
I think that the bag product has been created with a specific attribute set, then someone changed the attribute set to another, and another again. That would have lead the product to get ALL the attributes from ALL the attribute sets it has been changed to. But that's just a though, and it could be another reason. I'm actually currently not looking for the specific reason that led my product to have unrelated attributes.
I today want to reset my products. By reset I mean removing the attributes unrelated to my product. In the case of my bag, that means removing the tshirt_size and dress_size attributes. And by removing I mean deleting forever these attributes from the object.
My problem is that, I can't find how to do it. I tried setting the attributes to NULL and saving the product, but when I query again the product, I still get the attribute in the datas, with a null value. I don't want the attribute value to be null, I want the attribute to not exist.
Here is a sample of code that explains a bit what I tried:
$product = Mage::getModel('catalog/product')->load(1234); //Let's assume that my bag product ID is 1234
Mage::log($product->getData());
/* This last line dump all my products datas and contains among other things:
[...]=>...
[color]=>3
[tshirt_size]=>34
[dress_size]=>45
[...]=>...
*/
If I do a:
$product->setData('tshirt_size',null);
$product->setData('dress_size',null);
$product->save();
then again:
$product = Mage::getModel('catalog/product')->load(1234);
Mage::log($product->getData());
/* I get:
[...]=>...
[color]=>3
[tshirt_size]=>null
[dress_size]=>null
[...]=>...
*/
I don't want that. I want:
/*
[...]=>...
[color]=>3
[...]=>...
*/
The fact that I still have the entries in my array mean that the actual rows in the database are not deleted. I want the rows to be deleted.
Even more frustrating, when I do a:
$product->getAttributes();
It returns me all the attributes that can be set to my product without the unrelated attributes -which makes sense because the unrelated attributes are not in the attribute set of my product.
So, again, the question is:
Is there a way of hard deleting an attribute value from a product?
By hard I mean, removing the row from the database and not only setting the value to null or empty.
Thanks for your help!
Hugues.
FYI: I'm using Magento 1.6.1.0 (but it does not really change anything)
I finally had to tackle this, and although #vBuck was close, I always was able to query the old data after the switch in the attribute set and if I switched back I would see the old data when it shouldn't have been there. Today, I have the same need to ensure the random data is removed. Here is how I approached this topic.
In order to programmatically delete attributes when you switch from one set to another you must first look at all the entries for the new set, then get a list of all attributes, check against that list and (this is the important part) remove it from the correct entity table. For example, I want to get rid of a value of 500 GB that is in the sample Magento data when I switch Western Digital 500GB HD - 7200RPM from Hard Drive to Shoes. In order to do that I must remove the entry in the catalog_product_entity_text table it's stored at. This means that I must find that entry where it's equal to the product id and then delete it from it's entity type table.
I was able to do this, and was not able to find the stray data after. This was confirmed by both a DB search and switching back to the old attribute set and looking for the data. you can find it all here
https://gist.github.com/jeremyBass/6581038#file-attribute-clean-switch-md
TESTED in CE 1.7.0.2, 1.8.0.0
So I too would love to have the programmatic answer, but I don't have the time to do it. But this is what I can provide to this chain. You see the desired resulting action happening when you try to remove an attribute by its self from the admin.
Steps:
make sure the attr set has the attr in it's set.
update all products with that attr set to have the attr needing deletion as null.
remove the the attr from the set
Seems when I don't clear all attrs before removal of attr from the set, the result is for the app to leave the rows there. Maybe for safety, I don't know as I have not dived in. What I can tell with as little as I have looked in this it’s that if you don't clear the values before attr removal from the set, when you set the attr to null, the attr remains.
So, then the programmatic solutions will need to follow that pattern. If I get time I'll write it, but I have like 15 other tasks in the queue right now.
Ok, I found it finally, 15 minutes after asking the question (and spending few hours trying to solve it)
Here is the answer:
$product = Mage::getModel('catalog/product')->load(1234); //Let's assume that my bag product ID is 1234
$product->setData('unwanted_attribute',null);
$resource = $product->getResource();
$resource->saveAttribute($product,'unwanted_attribute');
Edit: This doesn't work. If you re-save the product later by doing a $product->save(), all the attributes reappear.
Looks like this is an old post, but I too was looking for an answer here, and I think I'm onto a solution.
To solve this, I had to work directly with the product resource's write adapter:
$product->getResource()->getWriteConnection()
to delete the attribute values from the table.
I got clues on how to do this after digging through some code. See Mage_Catalog_Model_Resource_Eav_Mysql4_Abstract::_saveAttributeValue:
$write = $this->_getWriteAdapter();
$storeId = Mage::app()->getStore($object->getStoreId())->getId();
$table = $attribute->getBackend()->getTable();
/**
* If we work in single store mode all values should be saved just
* for default store id
* In this case we clear all not default values
*/
if (Mage::app()->isSingleStoreMode()) {
$storeId = $this->getDefaultStoreId();
$write->delete($table, join(' AND ', array(
$write->quoteInto('attribute_id=?', $attribute->getAttributeId()),
$write->quoteInto('entity_id=?', $object->getEntityId()),
$write->quoteInto('store_id<>?', $storeId)
)));
}
By using this code in a loop through $product->getAttributes() before changing the attribute set, you are able to "unlink" the values from the attributes of the product without destroying the attributes themselves. Then you can change the attribute set (as done in Flagbit's extension) safely, not leaving behind dead data.
Using the above code, here's a demonstration that I've written to prove my theory:
$product=Mage::getModel('catalog/product')->load(MY_TARGET_PRODUCT_ID);
$write=$product->getResource()->getWriteConnection();
foreach($product->getAttributes() as $attribute) {
if($attribute->getId()==MY_TARGET_ATTRIBUTE_ID) {
$write->delete(
$attribute->getBackend()->getTable(),
join(' AND ', array(
$write->quoteInto('attribute_id=?',$attribute->getAttributeId()),
$write->quoteInto('entity_id=?',$product->getId())
))
);
}
}
In this example, I'm looking for a specific attribute to clear from the product, but you can remove the IF conditional to delete every attached value.
I haven't fully tested this, but so far it seems alright. I'm running Magento 1.4, by the way. Hope it helps someone!
UPDATE:
Looks like the above is only half correct. You'll still have to be careful not to clear certain attributes that might render the product dead (such as the name, mode, status, and others). So in my case, it looks like I'll have to compare with the default attribute set before removing.
ANOTHER UPDATE:
With the help of this SO post: https://stackoverflow.com/a/8500506/1442685
I was able to compare all attributes linked to a product and delete only the non-default values. This way, when changing sets, I can ensure that basic information about the product is not lost. Check out my Gist for the two classes which make it all happen:
https://gist.github.com/vbuck/5911170
You should be able to unset the value like either of these:
$product->unsetData('unwanted_attribute')
->save();
$product->unsUnwantedAttribute()
->save();
you need to go to admin>>catalog>>attributes>>manage attribute sets
if your trying to manage your product catalog you should first think of your attributes (separate to your product), then your sets(again not actually part of your products).
after you have properly established your attributes and sets (of attributes) you can apply them to products with values for each attribute.
or maybe you prefer this kinda thing?
class Mage_catalog_Model_Product_Attribute_Set_Api extends Mage_Api_Model_Resource_Abstract
{
{
/**
* Retrieve attribute set list
*
* #return array
*/
public function items()
{
$entityType = Mage::getModel('catalog/product')->getResource()->getEntityType();
$collection = Mage::getResourceModel('eav/entity_attribute_set_collection')
->setEntityTypeFilter($entityType->getId());
$result = array();
foreach ($collection as $attributeSet) {
$result[] = array(
'set_id' => $attributeSet->getId(),
'name' => $attributeSet->getAttributeSetName()
);
}
return $result;
}
} // Class Mage_Catalog_Model_Product_Attribute_Set_Api End
Once you have associated an attribute set to a product there is no way to change attribute set or remove that attribute set.
The way out is to export product and then modify sheet and import.
This link also explains :
https://collaborate.magento.com/magento/topics/how_do_i_change_product_attribute_set

Magento saving a product option for an attribute with a dropdown type

I have written code that automatically imports products basically something like:
$product->setName('my name');
$product->save();
This is fine for free fill text boxes, but how would I go about setting say manufacturer, which is a drop down menu? Is there also a way that if the option doesnt exist, then it will automagically add it?
Thanks
This is tested in 1.5.0.1, you just need to target the correct attribute ID. As #B00MER stated, the attribute will not be created that you are targetting but if the attribute exist, this will create the options.
$eav_entity_setup = new Mage_Eav_Model_Entity_Setup('core_setup');
$new_option['attribute_id'] = $id;
$new_option['value']['_custom_'.$value][0] = $value;
$eav_entity_setup->addAttributeOption($new_option);
Documentation about addAttributeOption can be found here.
http://freegento.com/doc/d0/d7b/_eav_2_model_2_entity_2_setup_8php-source.html#l00603
You will need to create the functionality yourself unfortunately. And by default Magento will not 'automagically' create a option if one doesn't pre-exist.
To simply set the ID of the value you want (Say Sony was ID 12) you can do:
$product->setData('mfr', '12');
However you may find a lot more insight here on steps to do what your looking for:
http://www.arscommunity.com/wiki/magento/configurable-products-creation-code

Magento - Adminhtml - Default website in new customer form

I am developing an online store for my customer and, we only have one website in our Magento setup.
In the admin panel when I go to Add a customer screen, in the "Associate to Website" field I see "Admin" selected by default. I would like to have my website there by default.
I think one possible way would be to write some code in:
Mage_Adminhtml_Block_Customer_Edit_Tab_Account::initForm
The cleanest way to do this is the just set the default value in your database. This will require no code changes at all.
UPDATE eav_attribute
SET default_value = 1
WHERE attribute_code = 'website_id'
The sample MySQL statement above sets your default website_id to 1.
Or You can simply edit array in:
Mage_Customer_Model_Customer_Attribute_Source_Website::getAllOptions()
I took the hint from Lrrr's answer and populated the drop-down with only user added websites, that is "Please Select" and "Admin" are no more available as options there by adding the following line:
$form->getElement('website_id')->setValues(Mage::getSingleton('adminhtml/system_store')->getWebsiteValuesForForm());
at the end of this function:
Mage_Adminhtml_Block_Customer_Edit_Tab_Account::initForm
The ideal way would be of course to override the above function in one's own module, but in our case overriding the above class creates conflict for another extension that we have installed, so I took this way round.

CakePHP, organize site structure around groups

So, I'm not quite sure how I should structure this in CakePHP to work correctly in the proper MVC form.
Let's, for argument sake, say I have the following data structure which are related in various ways:
Team
Task
Equipment
This is generally how sites are and is quite easy to structure and make in Cake. For example, I would have the a model, controller and view for each item set.
My problem (and I'm sure countless others have had it and already solved it) is that I have a level above the item sets. So, for example:
Department
Team
Task
Equipment
Department
Team
Task
Equipment
Department
Team
Task
Equipment
In my site, I need the ability for someone to view the site at an individual group level as well as move to view it all together (ie, ignore the groups).
So, I have models, views and controls for Depart, Team, Task and Equipment.
How do I structure my site so that from the Department view, someone can select a Department then move around the site to the different views for Team/Task/Equipment showing only those that belong to that particular Department.
In this same format, is there a way to also move around ignoring the department associations?
Hopefully the following example URLs clarifies anything that was unclear:
// View items while disregarding which group-set record they belong to
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
http://www.example.com/Departments
// View items as if only those associated with the selected group-set record exist
http://www.example.com/Department/HR/Team/action/id
http://www.example.com/Department/HR/Task/action/id
http://www.example.com/Department/HR/Equipment/action/id
Can I get the controllers to function in this manner? Is there someone to read so I can figure this out?
Thanks to those that read all this :)
I think I know what you're trying to do. Correct me if I'm wrong:
I built a project manager for myself in which I wanted the URLs to be more logical, so instead of using something like
http://domain.com/project/milestones/add/MyProjectName I could use
http://domain.com/project/MyProjectName/milestones/add
I added a custom route to the end (!important) of my routes so that it catches anything that's not already a route and treats it as a "variable route".
Router::connect('/project/:project/:controller/:action/*', array(), array('project' => '[a-zA-Z0-9\-]+'));
Whatever route you put means that you can't already (or ever) have a controller by that name, for that reason I consider it a good practice to use a singular word instead of a plural. (I have a Projects Controller, so I use "project" to avoid conflicting with it.)
Now, to access the :project parameter anywhere in my app, I use this function in my AppController:
function __currentProject(){
// Finding the current Project's Info
if(isset($this->params['project'])){
App::import('Model', 'Project');
$projectNames = new Project;
$projectNames->contain();
$projectInfo = $projectNames->find('first', array('conditions' => array('Project.slug' => $this->params['project'])));
$project_id = $projectInfo['Project']['id'];
$this->set('project_name_for_layout', $projectInfo['Project']['name']);
return $project_id;
}
}
And I utilize it in my other controllers:
function overview(){
$this->layout = 'project';
// Getting currentProject id from App Controller
$project_id = parent::__currentProject();
// Finding out what time it is and performing queries based on time.
$nowStamp = time();
$nowDate = date('Y-m-d H:i:s' , $nowStamp);
$twoWeeksFromNow = $nowDate + 1209600;
$lateMilestones = $this->Project->Milestone->find('all', array('conditions'=>array('Milestone.project_id' => $project_id, 'Milestone.complete'=> 0, 'Milestone.duedate <'=> $nowDate)));
$this->set(compact('lateMilestones'));
$currentProject = $this->Project->find('all', array('conditions'=>array('Project.slug' => $this->params['project'])));
$this->set(compact('currentProject'));
}
For your project you can try using a route like this at the end of your routes.php file:
Router::connect('/:groupname/:controller/:action/*', array(), array('groupname' => '[a-zA-Z0-9\-]+'));
// Notice I removed "/project" from the beginning. If you put the :groupname first, as I've done in the last example, then you only have one option for these custom url routes.
Then modify the other code to your needs.
If this is a public site, you may want to consider using named variables. This will allow you to define the group on the URL still, but without additional functionality requirements.
http://example.com/team/group:hr
http://example.com/team/action/group:hr/other:var
It may require custom routes too... but it should do the job.
http://book.cakephp.org/view/541/Named-parameters
http://book.cakephp.org/view/542/Defining-Routes
SESSIONS
Since web is stateless, you will need to use sessions (or cookies). The question you will need to ask yourself is how to reflect the selection (or not) of a specific department. It could be as simple as putting a drop down selection in the upper right that reflects ALL, HR, Sales, etc. When the drop down changes, it will set (or clear) the Group session variable.
As for the functionality in the controllers, you just check for the Session. If it is there, you limit the data by the select group. So you would use the same URLs, but the controller or model would manage how the data gets displayed.
// for all functionality use:
http://www.example.com/Team/action/id
http://www.example.com/Task/action/id
http://www.example.com/Equipment/action/id
You don't change the URL to accommodate for the functionality. That would be like using a different URL for every USER wanting to see their ADDRESS, PHONE NUMBER, or BILLING INFO. Where USER would be the group and ADDRESS, PHONE NUMBER< and BILLING INFO would be the item sets.
WITHOUT SESSIONS
The other option would be to put the Group filter on each page. So for example on Team/index view you would have a group drop down to filter the data. It would accomplish the same thing without having to set and clear session variables.
The conclusion is and the key thing to remember is that the functionality does not change nor does the URLs. The only thing that changes is that you will be working with filtered data sets.
Does that make sense?

Resources