URLs in Joomla

From Joomla! Documentation

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 (eg 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:

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:

(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, eg

$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, eg

$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, eg

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

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

$currentURL = Uri::current();

and is basically equivalent to

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

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 with including 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 like what's below:

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, 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 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.

Router.jpg

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 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.

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 "&amp;" and "<" to "&lt;" 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 then 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 back-end 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::_(), eg:

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 (eg "com_contact") associated with the webpage you want to link to
view The view which the component displays on that page (eg "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 menuitem 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 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.
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 2 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 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.

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.