Magento $category->getURL() issue for adding rel="alternate" - magento

Attempting to work out a solution to incorporate rel="alternate" tags into a multi-language Mage store. Note: categories and products have customised URL keys for each store
The below code works properly and gives me the correct full URL for a product, in the format of http://www.storename.com/storecode/product.phtml
$url = Mage::getModel('catalog/product')->setStoreId($storeId)->load($product->getId())->getProductUrl();
But the below does not work for categories. It gives the same store code for each URL, instead of the correct store code for each store in the foreach:
$url = Mage::getModel('catalog/category')->setStoreId($storeId)->load($category->getId())->getUrl();
In head.phtml I've so far got:
<?php
$url = '';
$pageType = Mage::app()->getFrontController()->getRequest()->getControllerName();
foreach (Mage::app()->getWebsites() as $website) {
foreach ($website->getGroups() as $group) {
$stores = $group->getStores();
foreach ($stores as $store) {
$storeId = $store->getStoreId();
switch ($pageType) {
case 'product':
$product = Mage::registry('current_product');
$url = Mage::getModel('catalog/product')->setStoreId($storeId)->load($product->getId())->getProductUrl();
break;
case 'category':
$category = Mage::registry('current_category');
/* Below is the code that isn't working properly */
$url = Mage::getModel('catalog/category')->setStoreId($storeId)->load($category->getId())->getUrl();
break;
default:
$url = 'def';
break;
}
echo '<link rel="alternate" href="' . $url . '" hreflang="' . $store->getConfig('general/locale/code') . '"/>' . "\n";
}
}
}
?>
Any advice or help would be appreciated.

Here's the quickest solution I found:
$url = $store->getCurrentUrl(false) . Mage::getModel('catalog/category')->setStoreId($storeId)->load($category->getId())->getUrlKey() . '.html';

Related

Magento hreflang Implementation

Using code from a previous discussion (link:https://magento.stackexchange.com/questions/12504/how-to-add-hreflang-tags-or-other-meta-tags-to-pages-in-magento), I was able to implement the hreflang links into our Magento site.
Here is the code that worked for me:
<?php foreach (Mage::app()->getWebsites() as $website) {
foreach ($website->getGroups() as $group) {
$stores = $group->getStores();
foreach ($stores as $store) {
$storeId = $store->getId();
$storeCode = substr(Mage::getStoreConfig('general/locale/code', $storeId),0,2);
if (Mage::registry('product')) {
$productId = Mage::registry('product')->getId();
$base_url = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
$url = Mage::getModel('catalog/product')->setStoreId($storeId)->load($productId)->getProductUrl();
$url = preg_replace('/\?.*/', '', $url);
echo '<link rel="alternate" hreflang="' . $storeCode . '" href="' . $url . '"/>';}
elseif(Mage::registry('current_category')) {
$categoryId = Mage::registry('current_category')->getId();
$base_url = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
$url = Mage::getModel('catalog/category')->setStoreId($storeId)->load($categoryId)->getUrlPath();
echo '<link rel="alternate" hreflang="' . $storeCode . '" href="' . $base_url . $url . '"/>' . "\n";
}}}}
?>
<?php
$storeId = 1;
if (Mage::registry('product')) {
$productId = Mage::registry('product')->getId();
$base_url = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
$url = Mage::getModel('catalog/product')->setStoreId($storeId)->load($productId)->getProductUrl();
$url = preg_replace('/\?.*/', '', $url);
echo '<link rel="alternate" hreflang="x-default" href="' . $url . '"/>';
}
elseif(Mage::registry('current_category')) {
$categoryId = Mage::registry('current_category')->getId();
$base_url = Mage::app()->getStore($storeId)->getBaseUrl(Mage_Core_Model_Store::URL_TYPE_LINK);
$url = Mage::getModel('catalog/category')->setStoreId($storeId)->load($categoryId)->getUrlPath();
echo '<link rel="alternate" hreflang="x-default" href="' . $base_url . $url . '"/>' . "\n";
}
?>
I'm having an issue with layered navigation URL's and canonical links disappearing on category pages.
Is there something I can add to this code to make sure that layered navigation URL's that contain "?" after .html get written as shown in the browsers address bar?
Also, on these types of category pages the canonical link does not show.
The code works perfectly on product pages.
Any help would be greatly appreciated!
Thanks in advance.
To solve this I need to know:
Where have you put this code? Is executed in categories?
Is the current_category empty?
Regards.
I missunderstood the question. Could you show an example?
The code only shows the category base URLs. When applying filters the module change the URL adding parameters filtered but your code doesn't have those parameters.
Usually people do not position the filters because it gives many problems of duplicate content. Take a look at this link:
https://amasty.com/blog/magento-layered-navigation-best-settings-for-seo/
In my opinion, I would left canonical URLs in categories using its base URL and disallow to index anything layered because could give duplicated content issues.
Kind regards

get all Categories and SubCatgories without loading model in foreach loop

I want to display all categories and their subcategories in primary nav menu.
When i hover on cateory, it should display its subcategories.
I want to implement this functionality without loading Mage::getModel('catalog/category') in foreach loop.
as you want to write code in phtml file use below code which create tree structure of category.
<ul>
<?php
$obj = new Mage_Catalog_Block_Navigation();
$storeCategories = $obj->getStoreCategories();
Mage::registry('current_category') ? $currentCategoryId = Mage::registry('current_category')->getId() : $currentCategoryId='';
foreach ($storeCategories as $_category):
?>
<li>
<strong><?php echo $_category->getName(); ?></strong>
<?php $categoryChildren = $_category->getChildren(); ?>
<?php if($categoryChildren->count()) : ?>
<ul>
<?php foreach($categoryChildren as $_categoryChild) : ?>
<?php $_categoryChildModel = Mage::getModel('catalog/category')->load($_categoryChild->getId());?>
<?php $categoryGrandchildren=$_categoryChild->getChildren(); ?>
<li>
<?php
$currentCategoryId===$_categoryChild->getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
echo ' ' . '<a href="' . $_categoryChildModel->getUrl() . '"' . $bold . '>' . $_categoryChild->getName() . '(' . $_categoryChildModel->getProductCollection()->count() . ')</a>';
?>
</li>
<?php if($categoryGrandchildren->count()) : ?>
<?php foreach($categoryGrandchildren as $_categoryGrandchild) : ?>
<?php $_categoryGrandchildModel = Mage::getModel('catalog/category')->load($_categoryGrandchild->getId());?>
<li>
<?php
$currentCategoryId===$_categoryChild->getId() ? $bold="style=\"font-weight:bold\"" : $bold='';
echo '  ' . '<a href="' . $_categoryGrandchildModel->getUrl() . '"' . $bold . '>' . $_categoryGrandchild->getName() . '(' . $_categoryGrandchildModel->getProductCount() . ')</a>';
?>
</li>
<?php endforeach; ?>
<?php endif; ?>
<?php endforeach; ?>
</ul>
<?php endif; ?>
</li>
<?php endforeach ?>
</ul>
and using css and HTML you can achieve your goal to display sub menu on hover of main menu.
Still let me if you need any other help.
Thanks
ok so I just did this and I figured I'd search to see if anyone was wondering how to achieve this. The trick to this is
Mage::getResourceSingleton('catalog/category')->getAttributeRawValue($categoryEntityId,array('name','level','url_key','path','is_active'),Mage::app()->getStore());
This does not load the category model lets take a look at what it is actually doing.
Go to app/code/core/Mage/Catalog/Model/Resource/Abstract
public function getAttributeRawValue($entityId, $attribute, $store)
{
if (!$entityId || empty($attribute)) {
return false;
}
if (!is_array($attribute)) {
$attribute = array($attribute);
}
$attributesData = array();
$staticAttributes = array();
$typedAttributes = array();
$staticTable = null;
$adapter = $this->_getReadAdapter();
foreach ($attribute as $_attribute) {
/* #var $attribute Mage_Catalog_Model_Entity_Attribute */
$_attribute = $this->getAttribute($_attribute);
if (!$_attribute) {
continue;
}
$attributeCode = $_attribute->getAttributeCode();
$attrTable = $_attribute->getBackend()->getTable();
$isStatic = $_attribute->getBackend()->isStatic();
if ($isStatic) {
$staticAttributes[] = $attributeCode;
$staticTable = $attrTable;
} else {
/**
* That structure needed to avoid farther sql joins for getting attribute's code by id
*/
$typedAttributes[$attrTable][$_attribute->getId()] = $attributeCode;
}
}
/**
* Collecting static attributes
*/
if ($staticAttributes) {
$select = $adapter->select()->from($staticTable, $staticAttributes)
->where($this->getEntityIdField() . ' = :entity_id');
$attributesData = $adapter->fetchRow($select, array('entity_id' => $entityId));
}
/**
* Collecting typed attributes, performing separate SQL query for each attribute type table
*/
if ($store instanceof Mage_Core_Model_Store) {
$store = $store->getId();
}
$store = (int)$store;
if ($typedAttributes) {
foreach ($typedAttributes as $table => $_attributes) {
$select = $adapter->select()
->from(array('default_value' => $table), array('attribute_id'))
->where('default_value.attribute_id IN (?)', array_keys($_attributes))
->where('default_value.entity_type_id = :entity_type_id')
->where('default_value.entity_id = :entity_id')
->where('default_value.store_id = ?', 0);
$bind = array(
'entity_type_id' => $this->getTypeId(),
'entity_id' => $entityId,
);
if ($store != $this->getDefaultStoreId()) {
$valueExpr = $adapter->getCheckSql('store_value.value IS NULL',
'default_value.value', 'store_value.value');
$joinCondition = array(
$adapter->quoteInto('store_value.attribute_id IN (?)', array_keys($_attributes)),
'store_value.entity_type_id = :entity_type_id',
'store_value.entity_id = :entity_id',
'store_value.store_id = :store_id',
);
$select->joinLeft(
array('store_value' => $table),
implode(' AND ', $joinCondition),
array('attr_value' => $valueExpr)
);
$bind['store_id'] = $store;
} else {
$select->columns(array('attr_value' => 'value'), 'default_value');
}
$result = $adapter->fetchPairs($select, $bind);
foreach ($result as $attrId => $value) {
$attrCode = $typedAttributes[$table][$attrId];
$attributesData[$attrCode] = $value;
}
}
}
if (sizeof($attributesData) == 1) {
$_data = each($attributesData);
$attributesData = $_data[1];
}
return $attributesData ? $attributesData : false;
}
As you can see no model loading happening just retrieving specific pieces of info. Also being part of the resource abstract means all catalog resource models (I haven't checked other resource models but, I wouldn't be too surprised to find this in others) have this available.
If you use this in an override of Mage_Catalog_Block_Navigation you can then call all of the info you need about any category without loading the model. To traverse the tree however, you have to do terrible things.
You can use 'path'(explode on /) to easily retrieve parents but you will need to get dirty in order to retrieve children categories so something like this to get Children.
$childrenQuery = "SELECT entity_id FROM catalog_category_entity WHERE path REGEXP '^.*\/" . $categoryId . "\/[[:digit:]]?[[:digit:]]?[[:digit:]]?[[:digit:]]?$'";
$resource = Mage::getSingleton('core/resource');
$readCxn = $resource->getConnection('core/read');
$children = $readCxn->fetchAll($childrenQuery);
if ($children[0]) {
return $children;
} else {
return;
}
The overall difficulty is that all model and resource model functions will expect an instance of a category object to make them all work with just the entity_id is definitely possible just a pain.
So I would not recommend doing this in general the only reason I did this is because the default magento root category in my case was not the actual functional root of categories (fun eh). If you are using a standard root category I would recommend using the Helper functions and retrieving the info from cache.
Either way from here all you have to do complete your functions in Mage_Catalog_Block_Navigation and assemble your menu in a template. And there you go; complete category menu without ever accessing a model->load.
Try This Code
<?php
require_once("app/Mage.php");
Mage::app();
function getChildCategories($category, $First = false) {
$sub = $First ? $category : $category->getChildren();
foreach ($sub as $child) {
$_categories[] = [ "name" => $child->getName(), "id" => $child->getId(), "children" => getChildCategories($child) ];
}
return $_categories;
};
function CategoriesTree($category, $First = false) {
$sub = $First ? $category : $category->getChildren();
echo "<pre>";
foreach ($sub as $child) {
echo $child->getName(); ;
CategoriesTree($child);
}
}
$_categories = Mage::helper('catalog/category')->getStoreCategories();
$categories = getChildCategories($_categories, true);
CategoriesTree($_categories, true);
?>

Magento sort media folder files by filename

I want to sort media folder files by filename.I tried with
$collection = $this->getCollection($path)
->setCollectDirs(false)
->setCollectFiles(true)
->setCollectRecursively(false)
->setOrder('filename', Varien_Data_Collection::SORT_ORDER_ASC);
but it is not case sensitive.It sorts all upper case words first then lowercase. (Apple,Bat,apple)
Please help !!!
You have to rewrite lib/Varien/Data/Collection/Filesystem.php
and change function
protected function _usort($a, $b)
{
foreach ($this->_orders as $key => $direction) {
$result = $a[$key] > $b[$key] ? 1 : ($a[$key] < $b[$key] ? -1 : 0);
return (self::SORT_ORDER_ASC === strtoupper($direction) ? $result : -$result);
break;
}
}
Please try this:
- create a test.php file in magento root directory.
- change the name of media folder to $sub_dir variable.
<?php
require_once 'app/Mage.php';
Mage::app();
$file = new Varien_Io_File();
$sub_dir = "wysiwyg/new";
$dir = Mage::getBaseDir('media') . DS . $sub_dir . DS;
$file->open(array('path' => $dir));
$fileDetails = $file->ls();
$allFiles = array();
foreach ($fileDetails as $value) {
$allFiles[] = $value['text'];
}
echo "<pre>";
print_r($allFiles);
echo "</pre>";
?>

export attributes to csv from magento

I found a working code that exports the attributes to the browser interface,
like this:
this is the code:'
<?php
chdir(dirname(__FILE__));
require_once 'app/Mage.php';
Mage::app();
umask(0);
$productModel = Mage::getModel('Mage_Catalog_Model_Product');
$categoryModel = Mage::getModel('Mage_Catalog_Model_Category');
$resource = Mage::getModel('core/resource');
$db = $resource->getConnection('core_write');
$attributes = Mage::getSingleton('eav/config')
->getEntityType(Mage_Catalog_Model_Product::ENTITY)->getAttributeCollection();
foreach($attributes as $attribute) {
#if(!$attribute->getIsUserDefined()) continue;
if($attribute->getEntityTypeId() != 4) continue;
if($attribute->getFrontendInput() != 'select' && $attribute->getFrontendInput() != 'multiselect') continue;
echo $attribute->getFrontendLabel(). ' (' . $attribute->getAttributeCode() . ')' . "\n";
foreach ($attribute->getSource()->getAllOptions(false) as $option) {
if(empty($option['label'])) continue;
echo "," . $option['label']."\n";
}
echo "================,=================\n";
}
I would like to export this data to a csv, but I dont know how.
As another question I would also like to export the attribute sets and not only the attributes, is this possible?
Thanks in advance!

Article Tags shown in Article List-Layout

So I've been adding tags you add to articles in Joomla!, which works fine. But now I want to show the tags in the article list layout that is default in Joomla.
I found and made an override for the list-layout and tried to add the tags code from a single article layout to the list-layout. Underneath is the code I tried to add in the list-layout. But none of the tags are shown in the layout..
<?php
// set tags
$tags = '';
if (!empty($this->item->tags->itemTags)) {
JLoader::register('TagsHelperRoute', JPATH_BASE . '/components/com_tags/helpers/route.php');
foreach ($this->item->tags->itemTags as $i => $tag) {
if (in_array($tag->access, JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id')))) {
if($i > 0) $tags .= ', ';
$tags .= ''.$this->escape($tag->title).'';
}
}
}
$args['tags'] = $tags;
?>
If this isn't clear, I can try to explain it a different way.
Your php works in the sense that it builds a set of "tag" links but it doesn't actually echo it out to the page. You need to add this line either at the end of your code or somewhere after, where you want to display the tags.
echo $tags;
e.g.
<?php
// set tags
$tags = '';
if (!empty($this->item->tags->itemTags)) {
JLoader::register('TagsHelperRoute', JPATH_BASE . '/components/com_tags/helpers/route.php');
foreach ($this->item->tags->itemTags as $i => $tag) {
if (in_array($tag->access, JAccess::getAuthorisedViewLevels(JFactory::getUser()->get('id')))) {
if($i > 0) $tags .= ', ';
$tags .= ''.$this->escape($tag->title).'';
}
}
}
$args['tags'] = $tags;
echo $tags;
?>
I'm not sure what you're using $args for either, it could probably be removed, unless you're using somewhere else.

Resources