Another very common problem I have seen in Joomla extensions is developers doing something like this:
$something = $_REQUEST['something']; // or, worse, this $whatever = $_SERVER['WHATEVER'];
DO NOT DO THAT. THIS IS A SECURITY ISSUE. There are very few cases where an extension needs access to the raw PHP superglobals, namely if you are writing a security extension and you need to check whether there's potentially malicious data in the request before Joomla sanitizes it. If you are one of the five or so people in the Joomla world writing this kind of software you are unlikely to be reading this. If you are about to say that you have a different, legitimate use case: you do NOT; you just don't know how to use Joomla's input class. Sorry.
Joomla already provides an Input class which can return the filtered and sanitised values of a request or environment parameter. Moreover, it allows other parts of your code and plugins to modify or override the input parameters.
The correct way to get something would be something like this:
$something = \Joomla\CMS\Factory::getApplication()->input->request->getCmd('something', 'default');
If the object you are working with has its own input property use that instead of the global input object shown above. Dispatchers and Controllers do have their own input object which can of course be overridden during instantiation.
If the object you are working with has its own property which gives you access to the application use that instead of going through the CMS Factory. This makes your code reusable and testable across applications.
Do NOT get input variables from your Model or View classes. Your Controller should be the only point where you use the input object to retrieve input parameters. You can pass these values to your model by setting its state. Likewise, your view should only ever read the model's state, not the input directly. This makes your code reusable and testable. It also lets you make changes in the naming of your input parameters only making a change in your controller (and possibly your dispatcher) instead of trying to hunt down random uses spread throughout your code. It also makes you think about the data flow in your application which makes it infinitely easier to debug it.
You should not use the entire request superglobal (e.g.
$this->input->getCmd('something')
or
$this->input->request->getCmd('something')
) if you
know that a specific piece of data can only come as GET or POST data.
Instead, be specific, e.g.
$this->input->get->getCmd('something')
for GET
data and $this->input->post->getCmd('something')
for POST data. This prevents input shading. If the
same input is present in $_GET, $_POST, $_ENV, $_COOKIE and $_SERVER you
will only get one value in the request. Which one? It depends on the PHP
configuration (request_order
and
variables_order
configuration keys). While on
most servers it's GP (Get and Post, i.e. POST data
overrides GET data) it could actually be anything with unpredictable
consequences for your extension. For example, some servers may stupidly
include cookies in request_order, thereby allowing a hacker to set a
cookie on a victim's browser to make your extension do something other
than the user's reasonable expectation, e.g. delete or modify a
different record than what they were trying to delete / edit.
Do not assume that the data you get from the input object is of a
specific scalar type. For example,
$this->input->getInt('something')
may return an
integer, null (the default value) or an array of
integers. The latter is something that you are unlikely to
have come across but that's the way the get()
method of
Joomla's input object works. Always check the type of the data you
receive, always assume that there is a hacker trying to inject invalid
data trying to trip your code up, always assume that any kind of
filtering or sanitization may fail to work the way you assume it
works.
If you want to access the $_SERVER and $_ENV superglobals; don't.
Instead go through $this->input->server
and
$this->input->env
. For example, if I want to get the
contents of the HTTP header X-Foo-Bar I should do
$this->input->server->getString('HTTP_X_FOO_BAR');
.
Remember that Joomla can and will apply its text filters when you
use getString
. If you want to get the raw data use
getRaw
or getArray
—
neither method applies any filtering.
Even though you can access the $_FILES superglobal with the input
object — DO NOT DO THAT! You should
never handle file uploads directly in your code. Always go through
Joomla's \Joomla\CMS\Filesystem\File::upload()
method. Do remember that, by default, it will try to prevent unsafe
files from being uploaded. If you have a VERY good reason to allow
“unsafe” files (e.g. you expect that a ZIP file containing PHP files
will be used with your extension) and have taken responsible measures to
prevent security issues you can of course set its
$allowUnsafe
parameter to true
. If you need
your extension to allow uploading of files with extensions or MIME types
which are not media you can of course use custom file upload
configuration in your own extension. This means that the excuse you may
have had for using $_FILES directly is completely invalid so please
don't let me see you ever accessing superglobals again.