Blog

See what else is new…

Remove Joomla 3 Tags ID in the URL

We were migrated from old K2 system in Joomla 2.5 to standard Articles in Joomla 3 and got trouble with SEF URL for Tags system. It used to be like this: http://foobla.com/tag/rss.html and we want it to be http://foobla.com/tag/rss for now (we have Massive Redirects Joomla plugin to redirect all *.html page to *), but the Joomla 3 Tags doesn't manage to do it that way, every link to each tag has the Tag ID as prefix, like this: http://foobla.com/tag/124-rss

There are a nice discussion at the Joomla CMS Development Group about that at Why do Tags have the ID in the URL?

And an core-hacking solution at this: How to remove ID from URL in Joomla 2.5 & 3.0

Finally, I decided to make a simple SQL query to make that happen by dealing with Joomla core menu system, no core hacking since you don't want your work will be overwritten when your Joomla site be updated.

Ok, here we go

Firstly, you will probably need to create a hidden meny system which wont be show anywhere on your Joomla frontend site, unless you have room for it on Mainmenu. Afterward, create a menu item to the list of all tags from Tags component. In foobla.com, I created myself one with the menu alias: "tag", see the screenshot

Joomla 3 create tags menu item

You will now have a hidden menu item like this http://foobla.com/tag, let's say this menu item has the ID: 221 (you can easily to find it on the Menu Items listing).

The next step is running a SQL Query to create massive menu items for all of your tags except the ROOT one (with ID: 0 - zero)

Well, hold on, it's highly recommend to make a backup of #__menu database table before running below SQL Query.

INSERT IGNORE INTO #__menu (menutype, title, alias, path, link, type, published, parent_id, level, access, params, component_id, language)
SELECT \'hiddenmenu\' AS menutype, t.title AS title, t.alias AS alias, CONCAT(\'tag/\', t.alias) AS path, CONCAT(\'index.php?option=com_tags&view=tag&layout=list&id[0]=\', t.id, \'&types[0]=1\') AS link, \'component\' AS type, 1 AS published, 221 AS parent_id, 2 AS level, 1 AS access, \'{"show_tag_title":"","tag_list_show_tag_image":"","tag_list_show_tag_description":"","tag_list_image":"","tag_list_description":"","show_tag_num_items":"","tag_list_orderby":"","tag_list_orderby_direction":"","tag_list_show_item_image":"","tag_list_show_item_description":"","tag_list_item_maximum_characters":0,"filter_field":"","show_pagination_limit":"","show_pagination":"","show_pagination_results":"","tag_list_show_date":"","date_format":"","return_any_or_all":"","include_children":"","maximum":200,"show_feed_link":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":0,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}\' AS params, 29 AS component_id, \'*\' AS language FROM #__tags t WHERE t.id <> 0

Be noticed to replace particular values of your Joomla site for: menutype, path, parent_id, level, params, component_id as well as replace database prefix #__ to your own one.

The cons of this method is that you will need to re-execute gain when you have new tags in your Joomla system. Just a little share, if you have any problem with this method, please comment.

UPDATED 2013-12-26: USING CRONJOB to execute this MySQL Query automatically

Create a php file, named it "mysql_cron.php" for example, by the following code

<?php
$username="DBUSERNAME";
$password="DBPASSWORD";
$dbname="DBNAME";
$dbhost="DBHOST";
$query='
	INSERT IGNORE INTO #__menu (menutype, title, alias, path, link, type, published, parent_id, level, access, params, component_id, language)
		SELECT 
			\'hiddenmenu\' AS menutype,
			t.title AS title,
			t.alias AS alias,
			CONCAT(\'tag/\', t.alias) AS path,
			CONCAT(\'index.php?option=com_tags&view=tag&layout=list&id[0]=\',
				t.id,
				\'&types[0]=1\') AS link,
			\'component\' AS type,
			1 AS published,
			221 AS parent_id,
			2 AS level,
			1 AS access,
			\'{"show_tag_title":"","tag_list_show_tag_image":"","tag_list_show_tag_description":"","tag_list_image":"","tag_list_description":"","show_tag_num_items":"","tag_list_orderby":"","tag_list_orderby_direction":"","tag_list_show_item_image":"","tag_list_show_item_description":"","tag_list_item_maximum_characters":0,"filter_field":"","show_pagination_limit":"","show_pagination":"","show_pagination_results":"","tag_list_show_date":"","date_format":"","return_any_or_all":"","include_children":"","maximum":200,"show_feed_link":"","menu-anchor_title":"","menu-anchor_css":"","menu_image":"","menu_text":1,"page_title":"","show_page_heading":0,"page_heading":"","pageclass_sfx":"","menu-meta_description":"","menu-meta_keywords":"","robots":"","secure":0}\' AS params,
			29 AS component_id,
			'*' AS language
		FROM
			#__tags t
		WHERE
			t.id <> 0
';
mysql_connect($dbhost,$username,$password);
@mysql_select_db($dbname) or die(strftime('%c')." Unable to select database");
mysql_query($query);
mysql_close();
echo strftime('%c')." ok!";
?>

You will need to replace DB INFORMATION and other value in the above code to your Joomla environment. It's now the time to execute a daily cronjob to run that php file from command line. Something like this:

0 * * * * /usr/local/bin/php /PATH_TO_PHP_FILE/mysql_cron.php

That's it, you don't need to lift your finger to do this annoying thing any longer.

PS: you may want to click around some tags for this blog, I have some here 

Get Our Newsletter

Important Notice: Since September 15th - 2018, because of the limitation of the resources, our support services have stopped with all kind of licenses! We are really sorry for that!
GOT IT