Sometimes, you need to have your plugins respond to asynchronous requests using client-side (JavaScript) code,
or you need to provide a “callback URL” (e.g. when implementing an OAuth2 authentication scheme, interfacing with a
payments processor service, etc). DO NOT use arbitrarily named .php files which will be accessed directly over the
web; this is a terrible and insecure practice. The best way to do that is by using Joomla's com_ajax
component.
com_ajax is a special core component built into Joomla. By itself, it can't do much. Its job is to let non-component, first-class Joomla extension types (modules, plugins, and templates) handle requests and return results either as JSON or as any arbitrary format.
For plugins, you would need to load a URL like this:
index.php?option=com_ajax&group=system&plugin=example&method=something&format=raw
. If you
are working in the backend you obviously need to use administrator/index.php
.
As you can see, the plugin you will be using is specified by the group
and plugin
URL
parameters.
The way this works is that com_ajax will make sure your plugin is loaded, then fire the plugin event
onAjax
, where Methodname
Methodname
is the value
of the method
URL parameter. In the example above, it would fire the plugin event
onAjaxSomething
. The event must return a result.
If you use format=raw, one of the following will happen:
-
If you throw an exception or return a Throwable, it will set the HTTP status to the throwable's status code and return a body similar to "RuntimeException:Your throwable's message".
-
If you return a scalar (string, null, integer, float) it will return its string representation.
-
If you return an object or array it will try to first cast it as an array, then
implode()
it into a string. This is quite useless, so please don't do that.
If you use format=json it will try to convert your data to a JSON representation using Joomla's
Joomla\CMS\Response\JsonResponse
class. The returned JSON object has the following
keys:
- success
-
Boolean true if your method has neither thrown an exception, nor returned a Throwable. Boolean false otherwise.
- message
-
Only when success is false. If your method threw an exception, or returned a Throwable object: the message of that throwable. Otherwise, this key is not set.
- messages
-
Any enqueued Joomla! application messages. The messages are categorised by type, therefore they may be returned out of order. For example:
messages: { "warning": [ "Some warning", "Another warning" ], "error": [ "The code went belly up. Whoopsie!" ] }
- data
-
Only when success is true. The data returned by your method.
Practical limitations
The com_ajax component will not pass any data to the plugin event. If you need the request data you must go through the Joomla application's input object.
The event name is not guaranteed to be unique to your plugin, since the naming scheme is very simplistic:
onAjax
. It is strongly recommended to use two precautions to avoid
mishaps with third party plugins:Methodname
-
Use a method which is highly specific to your plugin e.g. have your URL
method
parameter set to something likeacmePaymentsPayPalCallback
instead of justcallback
. The former will fire the event namedonAjaxAcmePaymentsPayPalCallback
which is reasonably guaranteed to be unique across plugins installed on the site, the latter will fire the event namedonAjaxCallback
which is reasonably NOT guaranteed to be unique. This protects your plugin from getting interfered with by other people's plugins. -
Check the
option
,group
, andplugin
URL parameters. If the option is not com_ajax, and/or the group and plugin don't match your plugin do not return anything. This protects other people's plugins from getting interference by your plugin.
Do take into consideration the context of the call to your plugin. If it's a third party service calling your plugin through com_ajax directly, not by redirecting the user's browser, you will not have the same session as the user. Therefore, you cannot retrieve any session data. There are workarounds to that. You could store data in a temporary table, under a randomly generated key, and pass that key to the third party service (provided that it passes that key back to you). If the user's browser is redirected back to a com_ajax URL do remember that you MUST redirect the user to a page of the site that makes sense. Otherwise, they will reasonably assume something got broken.
If you are relying on GET or POST data to do something you MUST assume the worst: this is invalid data, sent by a malicious user trying to hack the site unless positively proven otherwise. This is an integral part of the software design principle called defensive programming. It's not paranoia, it's a fact of life. People will try to find exploits in your code. White hats will do that to help you improve the security of your software. Black hats will do that to break your software for profit and/or fame. It doesn't matter if your software is a niche plugin used on exactly one site that barely anyone visits. This does not mean someone won't try to hack it, it only means it will most likely take longer. So, as the old Russian proverb goes “trust, but verify”.