Creating a router.php file for making sef urls.
Creating a router.php file in a joomla component for making the URLs SEO friendly is a little bit of a complex task, as compared to what we have learned in the previous steps. Let me explain it to you in as simple words as I can.
Why Search Engine Friendly urls?
Search engine friendly (SEF) urls are indeed human-readable urls that provide particular information regarding the page they point to. They have good search engine ranking as compared to non-sef urls, but there are also other reasons why sef urls are used in Joomla and index.php is eliminated. Some of those reasons are: matching with the logic of the website, as you will not have to use this file every time and on every page url with other variables. Secondly, they are easier to type, memorize and vocalize. Third, while making urls sef, you have to use the.htaccess file to eliminate index.php from the url. The benefit of using this file is that it can provide a lot of security enhancements. To use the.htaccess file, rename the htaccess.txt file in the Joomla root to.htaccess. After you have set it, go to the Joomla backend configuration manager and switch on search engine friendly urls.
Concept of using alias in url:
When there is no sef on in Joomla, generally records are loaded on the basis of their unique ids. But as these numeric keys are not allowed in the sef url structure, in place of this, aliases are used, which are generated for each url as they are saved. For example, while creating a new article in the backend, you will see an alias field, which will automatically calculate the correct alias for that article if you don’t provide it with your own.
So, in our breed component, on which we have worked so far, we also have to create alias support first so that joomla could pick it and use it to construct a url.
Files to create / update
create router.php /site/router.php
File Details
update breedform.xml /site/models/forms/breedform.xml
<field name="alias" type="text"
label="COM_BREED_FORM_LBL_BREED_ALIAS"
description="COM_BREED_FORM_DESC_BREED_ALIAS" />
First update the breedform.xml file located in /site/models/forms folder as listed above. This code will create a field for alias in the breed form view.
update default.php /site/views/breedform/tmpl/default.php
<div class="control-group">
<div class="control-label"><?php echo $this->form->getLabel('alias'); ?></div>
<div class="controls"><?php echo $this->form->getInput('alias'); ?></div>
</div>
Next in default.php, located in /site/views/breedform/tmpl folder, put the above mentioned code, right after the breed name field code. After this, refresh the breed form in frontend and you will see an additional alias field there.
update breedform.php /site/models/breedform.php
public function &getData($id = null)
{
if ($this->item === null)
{
$this->item = false;
$alias = JRequest::getVar('alias');
if($alias!=''){
$db = JFactory::getDbo();
$dbQuery = $db->getQuery(true)
->select('id')
->from('#__breed_breed')
->where('alias="'.$alias.'"');
$db->setQuery($dbQuery);
$id = $db->loadResult();
}
else{
$id = JRequest::getVar('id');
if (empty($id))
{
$id = $this->getState('breed.id');
}
}
We are also updating the breedform.php model file to revise the dynamics of getting the id of the record, because we are using alias in place of id in the sef mode. So, according to it, we have written some code in the getData () method which first gets the alias value from the URL and, based on this, gets the proper id from the database table, corresponding to the alias. The remaining code is the same for this method.
update breed.php /administrator/tables/breed.php
if (trim($this->alias) == '') {
$this->alias = $this->breedname;
}
$this->alias = JApplication::stringURLSafe($this->alias);
Then put the above mentioned code in the breed.php file, located in administrator/tables folder, in the check() method, right before return parent::check(); code. This code will automatically create alias suitable for being used in the urls.
update breed.xml /administrator/models/forms/breed.xml
<field name="alias" type="text"
label="COM_BREED_FORM_LBL_BREED_ALIAS"
description="COM_BREED_FORM_DESC_BREED_ALIAS" />
Update the breed.xml form file at backend by adding alias field to it, so that an alias field could be rendered in the process of adding or editing a breed form.
update edit.php /administrator/views/breed/tmpl/edit.php
<div class="control-group">
<div class="control-label"><?php echo $this->form->getLabel('alias'); ?></div>
<div class="controls"><?php echo $this->form->getInput('alias'); ?></div>
</div>
In the edit.php breed view file, we are fetching the alias field we have created in the breed.xml file in this step for adding the alias value to the record.
create router.php /site/router.php
<?php
// No direct access
defined('_JEXEC') or die;
JLoader::register('BreedFrontendHelper', JPATH_BASE . '/components/com_breed/helpers/breed.php');
class BreedRouter extends JComponentRouterBase
{
public function build(&$query)
{
$segments = array();
$view = null;
if (isset($query['task']))
{
$taskParts = explode('.edit', $query['task']);
$segments[] = implode('/', $taskParts);
$view = $taskParts[0];
unset($query['task']);
unset($query['view']);
}
if (isset($query['view']))
{
$segments[] = $query['view'];
$view = $query['view'];
unset($query['view']);
}
if (isset($query['id']))
{
if ($view !== null)
{
$db = JFactory::getDbo();
$dbQuery = $db->getQuery(true)
->select('alias')
->from('#__breed_breed')
->where('id=' . (int) $query['id']);
$db->setQuery($dbQuery);
$alias = $db->loadResult();
$segments[] = $alias;
}
else
{
$segments[] = $query['id'];
}
unset($query['id']);
}
return $segments;
}
public function parse(&$segments)
{
$vars = array();
$vars['view'] = array_shift($segments);
$model = BreedFrontendHelper::getModel($vars['view']);
while (!empty($segments))
{
$segment = array_pop($segments);
if (is_numeric($segment))
{
$vars['id'] = $segment;
}
else
{
$vars['alias'] = $segment;
}
}
return $vars;
}
}
The way Joomla creates a url is by first getting an alias from the menu for the component for creating a base, and after this, the component is responsible for generating the rest of the url. This is the router.php file in the component root, at the front end, which is meant to generate self-urls on the basis of providing aliases.
In the above mentioned router.php file, first we have declared a class called BreedRouter, which extends the JComponentRouterBase class, which holds all the methods required to generate a proper human-readable URL. Next, we declare a standardized function called “build” which passes in a query array by reference and it holds all the variables that Joomla uses for this component to build a URL. So, first we created a $segments array which would be returned at the end to inform Joomla about the URL pieces we want to build.
At first, we are checking if there is a “task” variable in the query array. If this is the case, we are going to eliminate the “.edit” part of it and render the remaining one by imploding the array with “/”. After that, we are unsetting the “task” variable and, in this way, it will not be added to the url. Next, we are looking for the view variable and if it is found, we are going to unset it as well.
Next, we are looking for the id variable in the url and it is the most important one. If the system finds any, on the basis of this id, we are going to get the alias for that specific record from the database, and once we get the alias, we will pass it to the segments array and then unset the query id. Thus, we are removing the id from the url.
After that, we have a parse method and we pass in the segments array that we have built in the build method, and the purpose of this method is to translate the SEF URL that is coming out of the previous method back to a query. It will only be executed when the joomla sef mode is switched on. In this method, first we shift the ‘views’ element of the array, to make it the first element, and then, on the basis of this array, we put the id or the alias back to the url.