URLs in Joomla: Difference between revisions

From Joomla! Documentation

Cmb (talk | contribs)
Several markup changes and some Words2Watch corrections.
 
Line 2: Line 2:


== Introduction ==
== Introduction ==
This is one of a series of [[API Guides]], which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.  
This is one of a series of [[API Guides]], which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.


This guide covers use of the <tt>JUri</tt> class (now known as <tt>Uri</tt>) and the use of the <tt>JRoute::_()</tt> method (now called <tt>Route</tt>). The Uri class enables you get the URL of the current webpage, and access parts of the URL. <tt>JRoute::_()</tt> is used to set up links to other webpage resources within your Joomla site.
This guide covers use of the ''JUri'' class (now known as ''Uri'') and the use of the ''JRoute::_()'' method (now called ''Route''). The Uri class enables you get the URL of the current webpage, and access parts of the URL. ''JRoute::_()'' is used to set up links to other webpage resources within your Joomla site.


== Getting the current URL ==
== Getting the Current URL ==
To get the URL of the current webpage do:
To get the URL of the current webpage do:
<source lang="php">
<syntaxhighlight lang="php">
use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Uri\Uri;
$uri = Uri::getInstance();
$uri = Uri::getInstance();
$url = $uri->toString();
$url = $uri->toString();
</source>
</syntaxhighlight>
The advantage of using this method is that it handles any peculiarities of the webserver (eg Apache or IIS) and also performs some cleaning of the URL to avoid some types of injection attacks.
The advantage of using this method is that it handles any peculiarities of the webserver (e.g. Apache or IIS) and also performs some cleaning of the URL to avoid some types of injection attacks.
 
What gets returned from <tt>Uri::getInstance()</tt> isn't a PHP string of the URL, but rather a Joomla Uri object, which also holds internally the various parts of the URL, and provides getter and setter methods to read or write these URL parts as shown below.
What gets returned from ''Uri::getInstance()'' isn't a PHP string of the URL, but rather a Joomla Uri object, which also holds internally the various parts of the URL, and provides getter and setter methods to read or write these URL parts as shown below.


       http://fredbloggs:itsasecret@www.example.com:8080/path/to/Joomla/index.php?task=view&id=32#anchorthis
       http://fredbloggs:itsasecret@www.example.com:8080/path/to/Joomla/index.php?task=view&id=32#anchorthis
Line 57: Line 57:
|getQuery
|getQuery
|setQuery
|setQuery
|Query in string format.  For example, "foo=bar&x=y".  
|Query in string format.  For example, ''foo=bar&x=y''.
|task=view&id=32
|task=view&id=32
|-
|-
Line 78: Line 78:
(Note that passing the user/password in the URL in this fashion is generally deprecated and not recommended, and won't work on some browsers. In this guide below it's not considered.)
(Note that passing the user/password in the URL in this fashion is generally deprecated and not recommended, and won't work on some browsers. In this guide below it's not considered.)


== root() and base() ==
== ''root()'' and ''base()'' ==
<tt>base()</tt> and <tt>root()</tt> are static functions which return key URLs.
''base()'' and ''root()'' are static functions which return key URLs.


<tt>Uri::root($pathonly)</tt> is a static function which returns the URL to the root of the Joomla site. It may or may not be the same as the HTTP domain, depending upon how your webserver is configured. In the common case where a Joomla instance "mysite" is installed in a directory under the webserver document root you are likely to get:
''Uri::root($pathonly)'' is a static function which returns the URL to the root of the Joomla site. It may or may not be the same as the HTTP domain, depending upon how your webserver is configured. In the common case where a Joomla instance "mysite" is installed in a directory under the webserver document root you are likely to get:
* <tt>Uri::root()</tt> returns the string "http://www.mydomain.org/mysite/"    (or https if you're using SSL, etc).
* ''Uri::root()'' returns the string ''<nowiki>http://www.mydomain.org/mysite/</nowiki>'' (or ''https'' if you're using SSL, etc).
* <tt>Uri::root(true)</tt> returns the string "/mysite".
* ''Uri::root(true)'' returns the string ''/mysite''.


The second parameter to <tt>Uri::root()</tt>, namely <tt>$path</tt>, sets the path locally within the <tt>Uri</tt> class, and will get used in subsequent invocations of <tt>Uri::root()</tt>. '''Hence it's strongly advised that you don't set this parameter, as it could seriously muck up your website.'''
The second parameter to ''Uri::root()'', namely ''$path'', sets the path locally within the ''Uri'' class, and will get used in subsequent invocations of ''Uri::root()''. '''Hence it's strongly advised that you don't set this parameter, as it could seriously muck up your website.'''


<tt>Uri::base()</tt> is similar to <tt>Uri::root()</tt> but what is returned depends on whether it's called from the site application or the administrator application.
''Uri::base()'' is similar to ''Uri::root()'' but what is returned depends on whether it's called from the site application or the administrator application.
* If you are on the site Uri::base() returns the same as Uri::root()
* If you are on the site Uri::base() returns the same as Uri::root()
* If you are on the admin back-end Uri::base() returns Uri::root() plus "administrator", so using the example above:  
* If you are on the admin back-end Uri::base() returns Uri::root() plus "administrator", so using the example above:
** <tt>Uri::base()</tt> returns the string "http://www.mydomain.org/mysite/administrator/
** ''Uri::base()'' returns the string ''<nowiki>http://www.mydomain.org/mysite/administrator/</nowiki>''
** <tt>Uri::base(true)</tt> returns the string "/mysite/administrator".
** ''Uri::base(true)'' returns the string ''/mysite/administrator''.


(This is similar to the [[Constants#Difference_between_JPATH_SITE.2C_JPATH_ROOT.2C_and_JPATH_BASE|Joomla Path constants]]).
(This is similar to the [[Constants#Difference_between_JPATH_SITE.2C_JPATH_ROOT.2C_and_JPATH_BASE|Joomla Path constants]]).


== Other URI methods ==
== Other URI Methods ==
As well as the methods above, the Joomla Uri provides the methods listed below. In the following example code snippets, <tt>$uri</tt> refers to a Uri instance, obtained for example through <tt>$uri = Uri::getInstance();</tt>.
As well as the methods above, the Joomla Uri provides the methods listed below. In the following example code snippets, ''$uri'' refers to a Uri instance, obtained for example through ''$uri = Uri::getInstance();''.


* '''<tt>toString(array $parts = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment')) : string</tt>'''
* '''''toString(array $parts = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment')) : string'''''


<tt>toString()</tt> converts the Uri to a string, and allows you to select the parts of the URL which you want, eg
''toString()'' converts the Uri to a string, and allows you to select the parts of the URL which you want, e.g.


<tt>$uri->toString(array('scheme','host','port','path');</tt>
''$uri->toString(array('scheme','host','port','path');''


will return the URL minus any query or anchor (fragment).
will return the URL minus any query or anchor (fragment).


* '''<tt>render()</tt>''' is similar to <tt>toString()</tt> in that it returns the parts of the URL you want, but as you have to pass the parts you want as a bitmask, it's preferable to use <tt>toString()</tt> instead.
* '''''render()''''' is similar to ''toString()'' in that it returns the parts of the URL you want, but as you have to pass the parts you want as a bitmask, it's preferable to use ''toString()'' instead.


* '''<tt>isSsl()<tt>''' returns true if the scheme is https, false otherwise, eg
* '''''isSsl()''''' returns true if the scheme is ''https'', false otherwise, e.g.


<tt>$secure = $uri->isSsl();</tt>
''$secure = $uri->isSsl();''


* '''<tt>isInternal()</tt>''' returns true if the URL is within the Joomla instance (including the administrator area), false otherwise. Note that this is a static function, and you pass the URL as a string, eg
* '''''isInternal()''''' returns true if the URL is within the Joomla instance (including the administrator area), false otherwise. Note that this is a static function, and you pass the URL as a string, e.g.


<tt>$internal = Uri::isInternal("myurl.org");</tt>
''$internal = Uri::isInternal("myurl.org");''


* '''<tt>current()</tt>''' returns the URL of the current page, minus any query string or fragment, eg
* '''''current()''''' returns the URL of the current page, minus any query string or fragment, e.g.
<tt>$currentURL = Uri::current();</tt>
''$currentURL = Uri::current();''


and is basically equivalent to
and is basically equivalent to
<source lang="php">
<syntaxhighlight lang="php">
$uri = Uri::getInstance();
$uri = Uri::getInstance();
$uri->toString(array('scheme','host','port','path'));
$uri->toString(array('scheme','host','port','path'));
</source>
</syntaxhighlight>


== External URLs ==
== External URLs ==
Usually if you're including an external URL in your website you will just specify it as a string, but there may be occasions where using the Uri class to manipulate parts of a URL could be useful. In this case you can do something like
Usually if you're including an external URL in your website you will just specify it as a string, but there may be occasions where using the Uri class to manipulate parts of a URL could be useful. In this case you can do something like:
<source lang="php">
<syntaxhighlight lang="php">
$joomla = Uri::getInstance("//www.joomla.org");
$joomla = Uri::getInstance("//www.joomla.org");
$joomla->setScheme("https");
$joomla->setScheme("https");
Line 133: Line 133:
$joomlaNews = $joomla->toString();  // https://www.joomla.org/announcements
$joomlaNews = $joomla->toString();  // https://www.joomla.org/announcements
echo "<a href='$joomlaNews'>Joomla news</a><br>";
echo "<a href='$joomlaNews'>Joomla news</a><br>";
</source>
</syntaxhighlight>
Joomla uses the PHP [https://www.php.net/manual/function.parse-url.php parse-url] method to parse the URL, so you need to be careful with including appropriate slashes in the URL and path.
Joomla uses the PHP [https://www.php.net/manual/function.parse-url.php ''parse-url''] method to parse the URL, so you need to be careful to include appropriate slashes in the URL and path.


== Internal Static URLs ==
== Internal Static URLs ==
To output a URL link to a file within the Joomla instance use:
To output a URL link to a file within the Joomla instance use:


<tt>$url = Uri::root() . 'path/from/joomla/root/to/file.typ';</tt>
''$url = Uri::root() . 'path/from/joomla/root/to/file.typ';''


For example, to make a URL which points to a file picture.jpg in the Joomla images folder use:
For example, to make a URL which points to a file ''picture.jpg'' in the Joomla images folder use:


<tt>$url = Uri::root() . 'images/picture.jpg';</tt>
''$url = Uri::root() . 'images/picture.jpg';''


The advantage of this approach is that no changes need to be made if you change the name of your joomla site or domain, such as moving from a development environment, via testing to live, and particularly if you want to display absolute URLs on your live site.
The advantage of this approach is that no changes need to be made if you change the name of your Joomla site or domain, such as moving from a development environment, via testing to live, and particularly if you want to display absolute URLs on your live site.


== Internal Dynamic URLs ==
== Internal Dynamic URLs ==
To create a URL which points to an item which is managed by a Joomla component com_example use an approach like what's below:
To create a URL which points to an item which is managed by a Joomla component ''com_example'' use an approach such as:
<source lang="php">
<syntaxhighlight lang="php">
use Joomla\CMS\Router\Route;
use Joomla\CMS\Router\Route;
$url = Route::_("index.php?option=com_example&view=showitem&id=14");
$url = Route::_("index.php?option=com_example&view=showitem&id=14");
// or in the old naming convention:
// or in the old naming convention:
$url = JRoute::_("index.php?option=com_example&view=showitem&id=14");
$url = JRoute::_("index.php?option=com_example&view=showitem&id=14");
</source>
</syntaxhighlight>
This is a bit trickier, as you have to know what parameters to set in the query part of the URL. However, if you set up (even temporarily) a menuitem which points to the appropriate view of the item type which you want to display then you should see in the Link field the parameters which you should add in the <tt>Route::_()</tt> call.  
This is a bit trickier; you have to know what parameters to set in the query part of the URL. However, if you set up (even temporarily) a Menu Item which points to the appropriate view of the item type which you want to display, you should see in the Link field the parameters which you should add in the ''Route::_()'' call.


(Although this method's name is an underscore, there's nothing special about it – it's just an ordinary function).  
(Although this method's name is an underscore, there's nothing special about it – it's just an ordinary function).


=== Joomla Site Routing ===
=== Joomla Site Routing ===
The reason that using ''Route::_()'' is so important is that it will handle the conversion to SEF (Search Engine Friendly) URLs for the Joomla site.
[[File:router.jpg|center|800px]]
The piece of Joomla code which converts between the "internal URL format" (with query parameters defining the option, view, id, etc) and the SEF format (consisting of URL segments) is known as the Router, and this has 2 key methods.
# The ''build()'' method takes as input an array of the URL query variables, and based on these creates segments of the SEF URL. As the query variables are processed in sequence to produce the SEF URL segments they are removed from the input array. The ''Route::_()'' method gets an instance of the site Router class and calls ''build()'' to generate the SEF URL so that it can be displayed in an HTML link.
# The ''parse()'' method does the opposite. Whenever a user clicks on an SEF link Joomla will receive an HTTP GET request with a SEF URL. Joomla then obtains an instance of the site Router class and calls ''parse()'' passing an array of the URL segments. The Router code processes each of the segments in turn and generates the equivalent query variables, which are then set as PHP $_GET variables so that the Joomla code can call ''Factory::getApplication()->input->get('id')'' etc. to access the variables as if they'd been query parameters with the HTTP GET request.


The reason that using <tt>Route::_()</tt> is so important is that it will handle the conversion to SEF (Search Engine Friendly) URLs for the Joomla site.
If you find that the URL returned from ''Route::_()'' still has query parameters then it may be that they are superfluous and you can omit them. However, there are circumstances where it may not be possible to remove all query parameters (specifically the ''Itemid'' parameter relating to the Menu Item).
[[File:router.jpg|center|800px]]
The piece of Joomla code which converts between the "internal URL format" (with query parameters defining the option, view, id, etc) and the SEF format (consisting of URL segments) is known as the Router, and this has 2 key methods.  
# The <tt>build()</tt> method takes as input an array of the URL query variables, and based on these creates segments of the SEF URL. As the query variables are processed in sequence to produce the SEF URL segments they are removed from the input array. The <tt>Route::_()</tt> method gets an instance of the site Router class and calls <tt>build()</tt> to generate the SEF URL so that it can be displayed in an HTML link.
# The <tt>parse()</tt> method does the opposite. Whenever a user clicks on an SEF link Joomla will receive an HTTP GET request with a SEF URL. Joomla then obtains an instance of the site Router class and calls <tt>parse()</tt> passing an array of the URL segments. The Router code processes each of the segments in turn and generates the equivalent query variables, which are then set as PHP $_GET variables so that the Joomla code can call <tt>Factory::getApplication()->input->get('id')</tt> etc to access the variables as if they'd been query parameters with the HTTP GET request.  


If you find that the URL returned from <tt>Route::_()</tt> still has query parameters then it may be that they are superfluous and you can omit them. However, there are circumstances where it may not be possible to remove all query parameters (specifically the Itemid parameter relating to the menuitem).
Even if you're not using SEF on your site, calling ''Route::_()'' will still cause some routing to be performed. For example, on a multilingual site you may find the ''lang'' parameter set on output, even though it wasn't set on your input parameter.


Even if you're not using SEF on your site, calling <tt>Route::_()</tt> will still cause some routing to be performed. For example, on a multilingual site you may find the <tt>lang</tt> parameter set on output, even though it wasn't set on your input parameter.
=== ''Route::_()'' Parameters ===
In addition to the input URL ''Route::_()'' takes the following parameters:
# ''$xhtml'' (default = true) – if true then the URL is passed through the PHP function ''htmlspecialchars()'' to convert special characters, such as ''&'' to ''&amp;'' and ''<'' to ''&lt;'' etc. Spaces in URLs always get converted to ''%20'', regardless of this parameter.


=== Route::_() Parameters ===
# ''$tls'' (default = self::TLS_IGNORE) – defines whether the output URL should be ''http'' or ''https'' or just the same as the current page. There are 3 possible values:
In addition to the input URL <tt>Route::_()</tt> takes the following parameters:
## Route::TLS_IGNORE (value 0) – if an absolute URL is requested, then the scheme (''http'' or ''https'') is set to the same as the current HTTP request
# <tt>$xhtml</tt> (default = true) – if true then the URL is passed through the PHP function <tt>htmlspecialchars()</tt> to convert special characters, such as "&" to "&amp;amp;" and "<" to "&amp;lt;" etc. Spaces in URLs always get converted to "%20", regardless of this parameter.
## Route::TLS_FORCE (value 1) – the scheme is set to ''https'' and an absolute URL is returned (regardless of the setting of the ''$absolute'' parameter).
 
## Route::TLS_DISABLE (value 2) – the scheme is set to ''http'' and an absolute URL is returned (regardless of the setting of the ''$absolute'' parameter).
# <tt>$tls</tt> (default = self::TLS_IGNORE) – defines whether the output URL should be http or https or just the same as the current page. There are 3 possible values:
# ''$absolute'' (default = false) – if true (or overridden by the ''$tls'' parameter) then an absolute URL is returned which includes the scheme, domain and port. If false, a root relative URL is output (where just the scheme, domain and port are missing).
## Route::TLS_IGNORE (value 0) – if an absolute URL is requested, then the scheme (http or https) is set to the same as the current HTTP request
## Route::TLS_FORCE (value 1) – the scheme is set to https and an absolute URL is returned (regardless of the setting of the <tt>$absolute</tt> parameter).
## Route::TLS_DISABLE (value 2) – the scheme is set to http and an absolute URL is returned (regardless of the setting of the <tt>$absolute</tt> parameter).
# <tt>$absolute</tt> (default = false) – if true (or overridden by the <tt>$tls</tt> parameter) then an absolute URL is returned which includes the scheme, domain and port. If false then a root relative URL is output (where just the scheme, domain and port are missing).  


=== Administrator Considerations ===
=== Administrator Considerations ===
Since SEF URLs aren't implemented on the Administrator back-end there's less of a need to use <tt>Route::_()</tt>, but it's standard practice to do so.
Since SEF URLs aren't implemented on the Administrator Backend there's less of a need to use ''Route::_()'', but it's standard practice to do so.


Since Joomla 3.9 the <tt>Route::link()</tt> method has been available, which allows you to obtain an SEF URL to a site page when you're on the administrator application. You pass "site" as the <tt>$client</tt> parameter, and the other parameters are as for <tt>Route::_()</tt>, eg:
Since Joomla 3.9 the ''Route::link()'' method has been available, which allows you to obtain an SEF URL to a site page when you're on the administrator application. You pass ''site'' as the ''$client'' parameter, and the other parameters are as for ''Route::_()'', e.g.
<source lang="php">
<syntaxhighlight lang="php">
use Joomla\CMS\Router\Route;  
use Joomla\CMS\Router\Route;
$url = Route::link("site", "index.php?option=com_example&view=showitem&id=14);
$url = Route::link("site", "index.php?option=com_example&view=showitem&id=14);
</source>
</syntaxhighlight>


=== Joomla Standard Query Parameters ===
=== Joomla Standard Query Parameters ===
The table below lists the more common query parameters which are used in constructing URLs with  
The table below lists the more common query parameters which are used in constructing URLs with
<tt>Route::_()</tt>. It is not a comprehensive list.  
''Route::_()''. It is not a comprehensive list.


{| class="wikitable"
{| class="wikitable"
Line 200: Line 199:
|-
|-
|option
|option
|The component (eg "com_contact") associated with the webpage you want to link to
|The component (e.g. "com_contact") associated with the webpage you want to link to
|-
|-
|view
|view
|The view which the component displays on that page (eg "article" for com_content)
|The view which the component displays on that page (e.g. "article" for com_content)
|-
|-
|layout
|layout
|The layout php file (in tmpl directory under the view) to be used
|The layout PHP file (in ''tmpl'' directory under the view) to be used
|-
|-
|id
|id
Line 212: Line 211:
|-
|-
|catid
|catid
|The id of the category associated with the item  
|The id of the category associated with the item
|-
|-
|Itemid
|Itemid
|The id of the menuitem which points to the webpage you want to link to
|The id of the Menu Item which points to the webpage you want to link to
|-
|-
|lang
|lang
Line 221: Line 220:
|-
|-
|task
|task
|In general the task parameter is of the form "firstpart.secondpart" and for a component called "com_example" Joomla will try to run an instance method called secondpart() of a controller class ExampleControllerFirstpart in a file firstpart.php in the com_example's controllers directory.
|In general the task parameter is of the form ''firstpart.secondpart'' and for a component called ''com_example'' Joomla will try to run an instance method called ''secondpart()'' of a controller class ExampleControllerFirstpart in a file ''firstpart.php'' in the com_example's controllers directory.
|-
|-
|tmpl  
|tmpl
|The template php file to use (instead of index.php). Commonly used with modals in the administrator back-end, by specifying tmpl=component to display the template component.php file in the modal iframe, which doesn't output the toolbar menu etc.  
|The template PHP file to use (instead of ''index.php''). Commonly used with modals in the Administrator Backend, by specifying ''tmpl=component'' to display the template ''component.php'' file in the modal iframe, which doesn't output the toolbar menu etc.
|-
|-
|format
|format
Line 233: Line 232:
Below is the code for a simple Joomla module which you can install and run to demonstrate use of some of the functionality described above. If you are unsure about development and installing a Joomla module then following the tutorial at [[S:MyLanguage/J3.x:Creating a simple module/Introduction|Creating a simple module]] will help.
Below is the code for a simple Joomla module which you can install and run to demonstrate use of some of the functionality described above. If you are unsure about development and installing a Joomla module then following the tutorial at [[S:MyLanguage/J3.x:Creating a simple module/Introduction|Creating a simple module]] will help.


The code assumes that you have an article with id=1 in your Joomla instance, and an image in a file picture.jpg in the images folder; change the relevant lines of code appropriately if this is not the case.  
The code assumes that you have an article with ''id=1'' in your Joomla instance, and an image in a file ''picture.jpg'' in the images folder; change the relevant lines of code appropriately if this is not the case.


The code can also easily be adapted to be an administrator module and include a call to the <tt>Route::link()</tt> function.  
The code can also easily be adapted to be an Administrator module and include a call to the ''Route::link()'' function.


In a folder mod_uri_demo create the following 2 files:
In a folder ''mod_uri_demo'' create the following two files:


<tt>mod_uri_demo.xml</tt>
''mod_uri_demo.xml''
<source lang="xml">
<syntaxhighlight lang="xml">
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
<extension type="module" version="3.1" client="site" method="upgrade">
Line 250: Line 249:
     </files>
     </files>
</extension>
</extension>
</source>
</syntaxhighlight>


<tt>mod_uri_demo.php</tt>
''mod_uri_demo.php''
<source lang="php">
<syntaxhighlight lang="php">
<?php
<?php
defined('_JEXEC') or die('Restricted Access');
defined('_JEXEC') or die('Restricted Access');
Line 283: Line 282:
echo "URL for article 1: $article1<br>";
echo "URL for article 1: $article1<br>";
echo "<a href='$article1'>First article</a><br>";
echo "<a href='$article1'>First article</a><br>";
</source>
</syntaxhighlight>


Zip up the mod_uri_demo directory to create <tt>mod_uri_demo.zip</tt>.
Zip up the ''mod_uri_demo'' directory to create ''mod_uri_demo.zip''.


Within your Joomla administrator go to Install Extensions and via the Upload Package File tab select this zip file to install this sample mod_uri_demo module.
Within your Joomla Administrator, go to {{rarr|Install,Extensions}} and via the ''Upload Package File'' tab select this zip file to install this sample ''mod_uri_demo'' module.


Make this module visible by editing it (click on it within the Modules page) then:
Make this module visible by editing it (click on it within the Modules page) then:
Line 294: Line 293:
# on the menu assignment tab specify the pages it should appear on
# on the menu assignment tab specify the pages it should appear on


When you visit a site web page then you should see the module in your selected position, and it should present a number of URLs and links demonstrating use of several of the Uri and Route class functions.  
When you visit a site web page you should see the module in your selected position, and it should present a number of URLs and links demonstrating use of several of the Uri and Route class functions.


== Related Material ==
== Related Material ==
On the topic of SEF URLs see [[Search Engine Friendly URLs]] and [[J3.x:Supporting_SEF_URLs_in_your_component|Supporting SEF URLs in your component]].
On the topic of SEF URLs, see [[Search Engine Friendly URLs]] and [[J3.x:Supporting_SEF_URLs_in_your_component|Supporting SEF URLs in Your Component]].


A custom router is developed in steps [[J3.x:Developing_an_MVC_Component/Adding_an_alias|Adding an alias]], [[J3.x:Developing_an_MVC_Component/Using_the_language_filter_facility|Using the language filter facility]] and [[J3.x:Developing_an_MVC_Component/Adding_Associations|Adding Associations]] of the MVC Component Development tutorial.
A custom router is developed in steps [[J3.x:Developing_an_MVC_Component/Adding_an_alias|Adding an Alias]], [[J3.x:Developing_an_MVC_Component/Using_the_language_filter_facility|Using the Language Filter Facility]] and [[J3.x:Developing_an_MVC_Component/Adding_Associations|Adding Associations]] of the MVC Component Development tutorial.


[[Category:Development]]
[[Category:Development]]

Latest revision as of 21:25, 6 October 2022

Introduction

This is one of a series of API Guides, which aim to help you understand how to use the Joomla APIs through providing detailed explanations and sample code which you can easily install and run.

This guide covers use of the JUri class (now known as Uri) and the use of the JRoute::_() method (now called Route). The Uri class enables you get the URL of the current webpage, and access parts of the URL. JRoute::_() is used to set up links to other webpage resources within your Joomla site.

Getting the Current URL

To get the URL of the current webpage do:

use Joomla\CMS\Uri\Uri;
$uri = Uri::getInstance();
$url = $uri->toString();

The advantage of using this method is that it handles any peculiarities of the webserver (e.g. Apache or IIS) and also performs some cleaning of the URL to avoid some types of injection attacks.

What gets returned from Uri::getInstance() isn't a PHP string of the URL, but rather a Joomla Uri object, which also holds internally the various parts of the URL, and provides getter and setter methods to read or write these URL parts as shown below.

     http://fredbloggs:itsasecret@www.example.com:8080/path/to/Joomla/index.php?task=view&id=32#anchorthis
     \__/   \________/ \________/ \_____________/ \__/\_______________________/ \_____________/ \________/
      |          |         |              |        |              |                    |            |
   scheme      user       pass          host      port          path                 query       fragment

The example column in the following table illustrates the result of each of the get methods on the URI above, all of which are strings.

Get method Set method Description Example
getFragment setFragment Fragment (everything after the '#'). This is often referred to as an anchor. anchorthis
getHost setHost Hostname or IP address. For example, 'www.joomla.org' or '192.168.2.45'. www.example.com
getPass setPass Password part of the authority. Don't use this! itsasecret
getPath setPath Path string. Note that the path always includes the leading "/" character. /path/to/Joomla/index.php
getPort setPort Port number. Specific schemes (protocols) have their own defaults (for example, 'http' is port 80, 'ftp' is port 21). 8080
getQuery setQuery Query in string format. For example, foo=bar&x=y. task=view&id=32
getScheme setScheme Scheme (protocol). For example, 'http', 'https', 'ftp'. http
getUser setUser Username part of the authority. Don't use this! fredbloggs
getVar setVar An individual query item value from within the query part. A query parameter may be removed using delVar. 32

(Note that passing the user/password in the URL in this fashion is generally deprecated and not recommended, and won't work on some browsers. In this guide below it's not considered.)

root() and base()

base() and root() are static functions which return key URLs.

Uri::root($pathonly) is a static function which returns the URL to the root of the Joomla site. It may or may not be the same as the HTTP domain, depending upon how your webserver is configured. In the common case where a Joomla instance "mysite" is installed in a directory under the webserver document root you are likely to get:

  • Uri::root() returns the string http://www.mydomain.org/mysite/ (or https if you're using SSL, etc).
  • Uri::root(true) returns the string /mysite.

The second parameter to Uri::root(), namely $path, sets the path locally within the Uri class, and will get used in subsequent invocations of Uri::root(). Hence it's strongly advised that you don't set this parameter, as it could seriously muck up your website.

Uri::base() is similar to Uri::root() but what is returned depends on whether it's called from the site application or the administrator application.

  • If you are on the site Uri::base() returns the same as Uri::root()
  • If you are on the admin back-end Uri::base() returns Uri::root() plus "administrator", so using the example above:
    • Uri::base() returns the string http://www.mydomain.org/mysite/administrator/
    • Uri::base(true) returns the string /mysite/administrator.

(This is similar to the Joomla Path constants).

Other URI Methods

As well as the methods above, the Joomla Uri provides the methods listed below. In the following example code snippets, $uri refers to a Uri instance, obtained for example through $uri = Uri::getInstance();.

  • toString(array $parts = array('scheme', 'user', 'pass', 'host', 'port', 'path', 'query', 'fragment')) : string

toString() converts the Uri to a string, and allows you to select the parts of the URL which you want, e.g.

$uri->toString(array('scheme','host','port','path');

will return the URL minus any query or anchor (fragment).

  • render() is similar to toString() in that it returns the parts of the URL you want, but as you have to pass the parts you want as a bitmask, it's preferable to use toString() instead.
  • isSsl() returns true if the scheme is https, false otherwise, e.g.

$secure = $uri->isSsl();

  • isInternal() returns true if the URL is within the Joomla instance (including the administrator area), false otherwise. Note that this is a static function, and you pass the URL as a string, e.g.

$internal = Uri::isInternal("myurl.org");

  • current() returns the URL of the current page, minus any query string or fragment, e.g.

$currentURL = Uri::current();

and is basically equivalent to

$uri = Uri::getInstance();
$uri->toString(array('scheme','host','port','path'));

External URLs

Usually if you're including an external URL in your website you will just specify it as a string, but there may be occasions where using the Uri class to manipulate parts of a URL could be useful. In this case you can do something like:

$joomla = Uri::getInstance("//www.joomla.org");
$joomla->setScheme("https");
$joomla->setPath("/announcements");
$joomlaNews = $joomla->toString();  // https://www.joomla.org/announcements
echo "<a href='$joomlaNews'>Joomla news</a><br>";

Joomla uses the PHP parse-url method to parse the URL, so you need to be careful to include appropriate slashes in the URL and path.

Internal Static URLs

To output a URL link to a file within the Joomla instance use:

$url = Uri::root() . 'path/from/joomla/root/to/file.typ';

For example, to make a URL which points to a file picture.jpg in the Joomla images folder use:

$url = Uri::root() . 'images/picture.jpg';

The advantage of this approach is that no changes need to be made if you change the name of your Joomla site or domain, such as moving from a development environment, via testing to live, and particularly if you want to display absolute URLs on your live site.

Internal Dynamic URLs

To create a URL which points to an item which is managed by a Joomla component com_example use an approach such as:

use Joomla\CMS\Router\Route;
$url = Route::_("index.php?option=com_example&view=showitem&id=14");
// or in the old naming convention:
$url = JRoute::_("index.php?option=com_example&view=showitem&id=14");

This is a bit trickier; you have to know what parameters to set in the query part of the URL. However, if you set up (even temporarily) a Menu Item which points to the appropriate view of the item type which you want to display, you should see in the Link field the parameters which you should add in the Route::_() call.

(Although this method's name is an underscore, there's nothing special about it – it's just an ordinary function).

Joomla Site Routing

The reason that using Route::_() is so important is that it will handle the conversion to SEF (Search Engine Friendly) URLs for the Joomla site.

The piece of Joomla code which converts between the "internal URL format" (with query parameters defining the option, view, id, etc) and the SEF format (consisting of URL segments) is known as the Router, and this has 2 key methods.

  1. The build() method takes as input an array of the URL query variables, and based on these creates segments of the SEF URL. As the query variables are processed in sequence to produce the SEF URL segments they are removed from the input array. The Route::_() method gets an instance of the site Router class and calls build() to generate the SEF URL so that it can be displayed in an HTML link.
  2. The parse() method does the opposite. Whenever a user clicks on an SEF link Joomla will receive an HTTP GET request with a SEF URL. Joomla then obtains an instance of the site Router class and calls parse() passing an array of the URL segments. The Router code processes each of the segments in turn and generates the equivalent query variables, which are then set as PHP $_GET variables so that the Joomla code can call Factory::getApplication()->input->get('id') etc. to access the variables as if they'd been query parameters with the HTTP GET request.

If you find that the URL returned from Route::_() still has query parameters then it may be that they are superfluous and you can omit them. However, there are circumstances where it may not be possible to remove all query parameters (specifically the Itemid parameter relating to the Menu Item).

Even if you're not using SEF on your site, calling Route::_() will still cause some routing to be performed. For example, on a multilingual site you may find the lang parameter set on output, even though it wasn't set on your input parameter.

Route::_() Parameters

In addition to the input URL Route::_() takes the following parameters:

  1. $xhtml (default = true) – if true then the URL is passed through the PHP function htmlspecialchars() to convert special characters, such as & to & and < to < etc. Spaces in URLs always get converted to %20, regardless of this parameter.
  1. $tls (default = self::TLS_IGNORE) – defines whether the output URL should be http or https or just the same as the current page. There are 3 possible values:
    1. Route::TLS_IGNORE (value 0) – if an absolute URL is requested, then the scheme (http or https) is set to the same as the current HTTP request
    2. Route::TLS_FORCE (value 1) – the scheme is set to https and an absolute URL is returned (regardless of the setting of the $absolute parameter).
    3. Route::TLS_DISABLE (value 2) – the scheme is set to http and an absolute URL is returned (regardless of the setting of the $absolute parameter).
  2. $absolute (default = false) – if true (or overridden by the $tls parameter) then an absolute URL is returned which includes the scheme, domain and port. If false, a root relative URL is output (where just the scheme, domain and port are missing).

Administrator Considerations

Since SEF URLs aren't implemented on the Administrator Backend there's less of a need to use Route::_(), but it's standard practice to do so.

Since Joomla 3.9 the Route::link() method has been available, which allows you to obtain an SEF URL to a site page when you're on the administrator application. You pass site as the $client parameter, and the other parameters are as for Route::_(), e.g.

use Joomla\CMS\Router\Route;
$url = Route::link("site", "index.php?option=com_example&view=showitem&id=14);

Joomla Standard Query Parameters

The table below lists the more common query parameters which are used in constructing URLs with Route::_(). It is not a comprehensive list.

Query Parameter Description
option The component (e.g. "com_contact") associated with the webpage you want to link to
view The view which the component displays on that page (e.g. "article" for com_content)
layout The layout PHP file (in tmpl directory under the view) to be used
id The id of the item to be shown
catid The id of the category associated with the item
Itemid The id of the Menu Item which points to the webpage you want to link to
lang The language code
task In general the task parameter is of the form firstpart.secondpart and for a component called com_example Joomla will try to run an instance method called secondpart() of a controller class ExampleControllerFirstpart in a file firstpart.php in the com_example's controllers directory.
tmpl The template PHP file to use (instead of index.php). Commonly used with modals in the Administrator Backend, by specifying tmpl=component to display the template component.php file in the modal iframe, which doesn't output the toolbar menu etc.
format The output format (html, json, jsonapi, feed, xml, raw, image) expected. This controls which view file will be run or what kind of content the controller should send as response. The output format by default is html.

Sample Module Code

Below is the code for a simple Joomla module which you can install and run to demonstrate use of some of the functionality described above. If you are unsure about development and installing a Joomla module then following the tutorial at Creating a simple module will help.

The code assumes that you have an article with id=1 in your Joomla instance, and an image in a file picture.jpg in the images folder; change the relevant lines of code appropriately if this is not the case.

The code can also easily be adapted to be an Administrator module and include a call to the Route::link() function.

In a folder mod_uri_demo create the following two files:

mod_uri_demo.xml

<?xml version="1.0" encoding="utf-8"?>
<extension type="module" version="3.1" client="site" method="upgrade">
    <name>URI demo</name>
    <version>1.0.1</version>
    <description>Code demonstrating use of Joomla URI class</description>
    <files>
        <filename module="mod_uri_demo">mod_uri_demo.php</filename>
    </files>
</extension>

mod_uri_demo.php

<?php
defined('_JEXEC') or die('Restricted Access');

use Joomla\CMS\Uri\Uri;
use Joomla\CMS\Router\Route;

// current URI
$uri = Uri::getInstance();
echo  "Page URI is: " . $uri->toString() . "<br>";
echo  "Scheme: " . $uri->getScheme() . ", Host: " . $uri->getHost() . " , Path: " . $uri->getPath() . "<br>";

// base() and root()
echo  "URI base(): " . $uri->base() . ", pathonly: " . $uri->base(true) . "<br>";
echo  "URI root(): " . $uri->root() . ", pathonly: " . $uri->root(true) . "<br>";

// External webpage
$joomla = Uri::getInstance("//www.joomla.org");
$joomla->setScheme("https");
$joomla->setPath("/announcements");
$joomlaNews = $joomla->toString();
echo "<a href='$joomlaNews'>Joomla news</a><br>";

// static internal address - put picture.jpg in images folder
echo '<img src="' . Uri::root() . 'images/picture.jpg" alt="Link to images/picture.jpg"><br>';

// link to article with id=1
$article1 = Route::_("index.php?option=com_content&view=article&id=1");
echo "URL for article 1: $article1<br>";
echo "<a href='$article1'>First article</a><br>";

Zip up the mod_uri_demo directory to create mod_uri_demo.zip.

Within your Joomla Administrator, go to Install  Extensions and via the Upload Package File tab select this zip file to install this sample mod_uri_demo module.

Make this module visible by editing it (click on it within the Modules page) then:

  1. making its status Published
  2. selecting a position on the page for it to be shown
  3. on the menu assignment tab specify the pages it should appear on

When you visit a site web page you should see the module in your selected position, and it should present a number of URLs and links demonstrating use of several of the Uri and Route class functions.

Related Material

On the topic of SEF URLs, see Search Engine Friendly URLs and Supporting SEF URLs in Your Component.

A custom router is developed in steps Adding an Alias, Using the Language Filter Facility and Adding Associations of the MVC Component Development tutorial.