Debugging Joomla
|
This content was generated with the assistance of AI and should be verified against the official Joomla documentation before being relied on in production. This sub-section’s Joomla bibliography lists the reference material consulted while preparing these pages. |
Debugging a Joomla extension means answering three questions: what did the page do (queries, language strings, request
data, time and memory), where does the code stop and what do the variables hold at that moment, and what did the code
tell us while nobody was watching. Joomla answers the first with the Debug System switch and the System - Debug
plugin, the second with a step debugger such as Xdebug, and the third with its logging framework. This page covers all
three for a developer. The example is the fictitious Tallpine Hiking Club package pkg_tallpine with the component
com_tallpine (namespace Tallpine\Component\Tallpine).
It was written against Joomla 6.2.x on PHP 8.3+ and checked on 2026-10-30 against the Joomla Developer Manual, the
Joomla User Guide and the 6.2-dev branch of joomla-cms. The administrator-side settings are explained field by
field in Global Configuration and System Information, Maintenance and Troubleshooting; the exception style that makes failures visible is in
Error Handling and Legacy APIs. PHP’s own tools (var_dump(),
error_log(), backtraces, Xdebug modes, profiling) are taught in
Debugging and Profiling, and container diagnostics
(docker logs, docker exec, docker debug) in Debugging Containers. They are
not repeated here; this page shows what is specific to Joomla.
The debugging toolbox at a glance
| Question | Tool | Where it lives |
|---|---|---|
How long did the page take, which queries ran, which language string is missing? |
Debug System, Debug Language and the debug console |
Global Configuration › System, plugin System - Debug ( |
Why did the request fail with a 500 error? |
Error Reporting |
Global Configuration › Server and Logging, |
What is in this variable at line 120 of the model? |
Step debugger (Xdebug, DBGp protocol) in an IDE |
PHP extension and an IDE; in Docker a derived image |
What happened in production at 03:12? |
Logging with |
Your extension code, |
Which deprecated API does my code still call? |
Log Deprecated API ( |
Global Configuration › Logging |
Debug System and the JDEBUG constant
Debug System is the debug property of configuration.php, changed under System › Global Configuration › System ›
Debug Settings. At the start of every request Joomla turns it into the PHP constant JDEBUG. Core and extensions test
that constant, which is why a single switch changes so many behaviours:
-
the application starts a profiler and records time marks (
afterRenderand others), and the debug console shows them as the Timeline -
CMSApplication::setupLogging()registers an in-memory logger that collects every log entry of the request, so the console can list them, and lowers the threshold of the core error log from errors only to every priority -
the System - Debug plugin renders the debug console and collects queries, session, request and memory data
-
extensions that guard expensive diagnostics with
if (JDEBUG)run them
The switch is global and affects every visitor’s request, not only yours. The console itself can be limited to some
user groups (see below), but the extra data is collected for every request, which costs memory and time, and the verbose
error pages are visible to everybody when Error Reporting is maximum. Debug System is therefore a development and
staging switch. On the production site of the Tallpine club it stays off and is raised for the minutes it takes to
reproduce a problem.
<?php
// configuration.php of the local Tallpine development site
class JConfig
{
public $debug = true; // Debug System: sets JDEBUG
public $debug_lang = false; // Debug Language
public $debug_lang_const = true; // markers show the translated text; false shows the language key
public $error_reporting = 'maximum'; // 'default', 'none', 'simple' or 'maximum'
public $log_path = '/var/www/html/administrator/logs';
// ... remaining properties unchanged
}
Because the properties are plain PHP, the CLI can set them too, which is useful in a container where the administrator is not reachable. Use quotes around values so the shell does not interpret them.
php cli/joomla.php config:set debug=true error_reporting=maximum
php cli/joomla.php config:get debug
Source: Joomla User Guide: Using the CLI
When the administrator cannot start at all because of a fatal error, edit configuration.php by hand (it is read-only
after installation on most hosts, so the permissions must be changed temporarily), reproduce the error, read the stack
trace, and revert both the values and the permissions. An error that appears only with Debug System on is often a
deprecation promoted to a visible message by maximum; read it before concluding that Debug System caused the problem.
The System - Debug plugin and the debug console
Debug System alone draws nothing. The console is produced by the System - Debug plugin, in the extensions list as
plg_system_debug (element debug, group system, namespace Joomla\Plugin\System\Debug). The plugin is enabled in a
default installation. Since Joomla 4 its console is built on the open-source library php-debugbar: the plugin creates a
DebugBar\DebugBar object, adds Joomla-specific data collectors to it, and renders the bar with a Joomla subclass of
the library’s JavaScript renderer. The 6.2 composer.json requires php-debugbar/php-debugbar at ^2.2.6. The
library’s class names matter when you read the source or when a Composer update changes the bar’s behaviour; the
Joomla-specific collectors live in the plugin’s src/DataCollector folder.
| Collector class | Console tab and content |
|---|---|
|
Joomla information: version, PHP version, database driver, request time, the profile of the application marks |
|
Session: the session registry and the token |
|
Request: GET, POST, cookies and server variables of the current request |
|
Profile and the timeline: each profiler mark with elapsed time and memory |
|
Memory: peak memory use |
|
Queries: every SQL statement with its duration, duplicates, optional call stack, profile and |
|
Language: files loaded, strings used (with the file and line that asked for them) and strings that were not found |
|
User: the identity of the current user |
|
Log: the entries held by the in-memory logger, mapped to message levels |
Plugin options
The plugin’s three tabs map to the fields of debug.xml:
| Field (parameter) | Default | Effect |
|---|---|---|
Allowed Groups ( |
none |
User groups that may see the console. Empty means every visitor, guests included. |
Refresh Assets ( |
on |
With Debug System on, re-evaluates the Web Asset Manager files on each request so a rebuilt CSS or JavaScript file is served at once. See Web Asset Manager. |
Memory, Request, Session, Profile, Queries ( |
show |
Which tabs are drawn. |
Query Traces, Query Profiles, Query Explains ( |
off |
A PHP call stack for each query; the database’s per-statement profile (MySQL |
Track Request History ( |
off |
Stores the data of recent requests in a file store below the cache folder ( |
Language Errors, Language Files, Language Strings ( |
show |
The three language tabs. Strip First, Strip Prefix and Strip Suffix shorten the displayed keys. |
Log Entries ( |
on, off |
Whether log entries appear in the bar, and whether deprecations raised by core code (not only by extensions) are listed. |
How the console is drawn
The plugin is a SubscriberInterface plugin (see
Plugin Development and Events) subscribed to onBeforeCompileHead,
onBeforeRespond, onAfterRespond, onAjaxDebug and the database onAfterDisconnect event. In outline:
-
onBeforeCompileHeadadds the bar’s script and stylesheet to the page, but only whenJDEBUG(or Debug Language) is on, the current user passes the Allowed Groups check and the document is HTML. -
onBeforeRespondcopies the profiler marks into the bar. -
onAfterRespondcollects everything else and inserts the rendered bar into the response body. Ajax requests are skipped, except for request history. -
When the database connection closes (
onAfterDisconnect) the plugin runs the optionalEXPLAINand profile queries, so that diagnostic queries are not counted as the page’s own.
Two consequences follow. A response that is not an HTML document (JSON from the Web Services API, a raw format=raw
view, a download) has no console; read the data in the log or with request history instead. And because the bar is
inserted after rendering, a fatal error that stops the page earlier means no bar at all: the PHP error log and
joomla_core_errors.php are the places to look.
Reading the Queries tab
The Queries tab is the quickest way to see the cost of a model. A list view of com_tallpine that loads each trail’s
category in a loop shows as the same SELECT repeated with different identifiers; the tab flags duplicated statements and
sums the time. The fix is to join the category once in getListQuery() (see
Database API). Turn on Query Explains to see whether the statement uses an index
and Query Traces to find the line of your model that issued it. Statements are shown with their bound values
substituted, which means the tab also reveals data; this is one more reason to restrict the console.
Security of the console
The console exposes the SQL of the site, the request, the session, file paths and the language files. If Allowed Groups
is empty and Debug System is on, every anonymous visitor sees it. A public site therefore follows three rules: keep
Debug System off; if it must be on, select Super Users in Allowed Groups; and never leave maximum error reporting on.
The Ajax endpoint that serves request history requires a valid form token, so it cannot be fetched by a script that
has no session. Also remember that the in-memory logger and the bar hold log messages: do not write secrets or complete
personal data in a log message at any priority.
Debug Language
Debug Language (debug_lang) is a different tool with a similar name. It changes how the language layer returns
strings, so that you can see where each visible text comes from. With it on, Text::_('KEY') returns:
-
**text**when the key exists: the text is wrapped in two asterisks on each side. With the default Debug Language Constant setting (debug_lang_consttrue) the text shown is the translation; set it to No to show the language key (COM_TALLPINE_TRAIL_DISTANCE_LABEL) instead. -
??KEY??when the key is not found, wrapped in question marks, usually showing the key that was requested.
With Debug Language on the debug console is also drawn (the plugin treats Debug Language as a reason to load the bar),
and its Language tabs list the files that were loaded, the strings that were used with the file and line that asked
for them, and the orphans. This is the tool for the German version of the Tallpine site: switch to German, turn on
Debug Language, and every ??...?? is a missing entry in de-DE/com_tallpine.ini.
; language/en-GB/com_tallpine.ini
COM_TALLPINE_TRAIL_DISTANCE_LABEL="Distance (km)"
COM_TALLPINE_TRAIL_ELEVATION_LABEL="Elevation gain (m)"
<?php
use Joomla\CMS\Language\Text;
// With debug_lang on and the German file lacking the key, this prints ??COM_TALLPINE_TRAIL_DIFFICULTY_LABEL??
echo Text::_('COM_TALLPINE_TRAIL_DIFFICULTY_LABEL');
Source: Joomla Manual: Language
Typical findings and their causes:
-
A
**text**that never appears in a template means the text is hard-coded or comes from another source (a module title, article content), not from a language file. -
A
??KEY??that is correct in English but missing in German means the file was not loaded for that language: check thatFactory::getApplication()->getLanguage()->load('com_tallpine', ...)or the extension’s own loading is reached, and that the file name matches the extension element. -
Strings in
.inifiles that contain unescaped double quotes or reserved words make the parser fail and are listed on the Language Errors tab. Debug Language also makes the parser report such files more strictly. -
Strings inside an HTML attribute (a
placeholder, atitle) are broken by the asterisks, which is expected: check them in the console list instead of reading the markup.
Turn Debug Language off before taking screenshots or running end-to-end tests that compare text, since every string is altered. Language files and their loading are explained in Language Files and Internationalisation.
Error reporting and the PHP error log
The page you see is only one of the places where an error can be reported. Joomla’s Error Reporting option maps to
PHP’s error_reporting for the request: default leaves the server’s value, none silences everything, simple
reports errors and warnings, and maximum reports everything including notices and deprecations. The PHP setting
display_errors decides whether messages go to the page; log_errors and error_log decide whether they go to a file.
In a container, send them to standard error so docker compose logs shows them. The official image’s PHP uses
php.ini values you can override with a file in conf.d.
; conf.d/50-tallpine-dev.ini (development only)
display_errors = On
log_errors = On
error_log = /proc/self/fd/2
error_reporting = E_ALL
The Joomla exception handler renders the error page of the active template (error.php); with Debug System on or
Error Reporting maximum, the page also includes the exception class, the file and line and the trace. See
Error, Offline and Component Pages for customising that page and
for why a public site must not show a trace. In production keep errors in the log and show the generic page.
Step debugging with Xdebug
Step debugging stops PHP on a line you choose and lets you inspect variables, evaluate expressions and walk the call
stack, which is the right tool for a controller that redirects to the wrong place or a form filter that changes a value.
The mechanism (the debug mode, port 9003, trigger cookies, xdebug_info()) is explained in
Debugging and Profiling; this section adds the Joomla and
Docker specifics.
The official joomla image does not include Xdebug, and Xdebug slows every request, so build a development image on
top of it and keep it out of production. Joomla’s code lives in /var/www/html inside the image.
# docker/Dockerfile.dev
FROM joomla:6.2-php8.4-apache
# Build tools are needed only while compiling the extension.
RUN apt-get update \
&& apt-get install -y --no-install-recommends $PHPIZE_DEPS \
&& pecl install xdebug-3.5.3 \
&& docker-php-ext-enable xdebug \
&& apt-get purge -y --auto-remove $PHPIZE_DEPS \
&& rm -rf /var/lib/apt/lists/*
COPY docker/xdebug.ini /usr/local/etc/php/conf.d/99-xdebug.ini
; docker/xdebug.ini
xdebug.start_with_request=trigger
xdebug.client_host=host.docker.internal
xdebug.client_port=9003
xdebug.log_level=0
Source: Xdebug: Step Debugging
The ini file deliberately leaves out xdebug.mode: the XDEBUG_MODE environment variable of the container sets it, and
it overrides the ini setting. Extend the Compose file from
Local Development with Docker with a build section, the variable,
the host mapping for Linux hosts and a bind mount of the extension source so edits appear without rebuilding:
# compose.override.yaml
services:
joomla:
build:
context: .
dockerfile: docker/Dockerfile.dev
environment:
XDEBUG_MODE: develop,debug
XDEBUG_CONFIG: client_host=host.docker.internal client_port=9003
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./extensions/com_tallpine/admin:/var/www/html/administrator/components/com_tallpine
- ./extensions/com_tallpine/site:/var/www/html/components/com_tallpine
Source: Xdebug: Step Debugging
Then start the stack with docker compose up -d --build. Docker Desktop resolves host.docker.internal itself; the
extra_hosts line makes it work on Linux. Xdebug opens the connection from the container to your IDE, so the IDE listens
on port 9003 and no port needs to be published for it; a host firewall must allow the incoming connection from the
Docker network. xdebug_info() or php --ri xdebug inside the container, run with docker compose exec joomla, shows
the active mode and the result of the last connection attempt.
The IDE must translate container paths into project paths. A bind mount makes this exact for the extension, while the
rest of Joomla (in the volume) can be mapped to a copy of the core that you keep for reading. A VS Code launch.json
for the PHP Debug extension:
{
"version": "0.2.0",
"configurations": [
{
"name": "Listen for Xdebug (Tallpine)",
"type": "php",
"request": "launch",
"port": 9003,
"pathMappings": {
"/var/www/html/administrator/components/com_tallpine": "${workspaceFolder}/extensions/com_tallpine/admin",
"/var/www/html/components/com_tallpine": "${workspaceFolder}/extensions/com_tallpine/site"
}
}
]
}
PhpStorm uses the same idea under Settings › PHP › Servers with Use path mappings and the server name equal to the
PHP_IDE_CONFIG variable (serverName= followed by the server name) if you set one.
With start_with_request=trigger, a request starts a session only when it carries the trigger. In a browser, set the
XDEBUG_SESSION cookie with a browser extension or add ?XDEBUG_TRIGGER=1 to the URL; Joomla’s SEF router and the
form token are unaffected. For the CLI (the tallpine:import command from
Console Command Plugins) pass the variables to the process:
docker compose exec -e XDEBUG_MODE=debug -e XDEBUG_TRIGGER=1 --user www-data \
joomla php cli/joomla.php tallpine:import --dry-run
Source: Xdebug: Step Debugging
Where to put breakpoints
-
Dispatcher::dispatch()of the component (src/Dispatcher/Dispatcher.php) is where the request enters the extension. -
BaseController::execute()and the task method (save(),publish()) show which task was resolved and whether the token check passed. See Component MVC: The Administrator Side. -
AdminModel::save()andTable::store()are where data is filtered, validated and written. -
A plugin’s event handler method (
onContentPrepare()for a content plugin) shows whether the event reached it; put the breakpoint in the subscriber itself (see Plugin Development and Events).
Pitfalls
-
The IDE never receives a connection. Check
client_host, that the IDE listens on 9003 (Xdebug 2 used 9000), the firewall, and that the request has the trigger. -
Breakpoints are grey. The path mapping is wrong; the debugger sees paths below
/var/www/htmland cannot find the file. -
Everything is slow. Xdebug is loaded in
developmode on every request. UseXDEBUG_MODE=offfor routine work and switch todebugwhen needed. -
Timings look wrong. Time spent stopped at a breakpoint is counted by the profiler, so read the Profile tab only from runs without a debugger attached.
-
Caching hides your change. Clear the cache, or turn off the Joomla cache while debugging; see Caching and Performance. OPcache with a bind mount can serve stale code when
opcache.validate_timestampsis off. -
Never install Xdebug on a production host or in the image you publish. It can expose a debugging port to anyone who can reach the server and slows every request.
Logging with Log::add()
Debugging tools help while you watch; logs help when you are not there. Joomla’s logging framework is the class
Joomla\CMS\Log\Log, a singleton that routes log entries to loggers according to the entry’s priority and category.
<?php
use Joomla\CMS\Log\Log;
Log::add('Closure sync failed for trail 17', Log::ERROR, 'com_tallpine');
Source: Joomla Manual: Logging
The signature in 6.2 is Log::add($entry, $priority = Log::INFO, $category = '', $date = null, array $context = []).
The first argument is the message (a string) or a ready LogEntry; the date defaults to now; the optional $context
array carries extra data for loggers that use it.
Priorities
Priorities are bit flags that follow the severities of RFC 5424 (syslog), defined as constants of Log:
| Constant | Value | Use for |
|---|---|---|
|
1 |
The site is unusable. |
|
2 |
Action must be taken at once. |
|
4 |
A component failed, such as the park-authority API being unreachable for the closure sync. |
|
8 |
An operation failed and the user saw an error. |
|
16 |
Something unexpected that the code handled. |
|
32 |
Normal but significant events. |
|
64 |
Routine information. This is the default priority of |
|
128 |
Detail for developers. |
|
30719 |
Every priority. |
Because they are flags, several priorities are combined with + or | when registering a logger.
Categories
The category is free text. Use the extension’s element name (com_tallpine, plg_task_tallpine_trailsync) so that
your entries do not collide with the others, and use a sub-category when one extension has several concerns
(com_tallpine.sync). Categories are what the Global Configuration options and addLogger() filter on. Core uses some:
system goes to joomla_core_errors.php, deprecated to the deprecation log, databasequery to database logging,
and jerror is special: an entry with the category jerror is also shown to the user in the message area, in
addition to being logged. The Debug console collects every category.
Guard debug messages
Detailed messages at Log::DEBUG should cost nothing when debugging is off. The Manual wraps them in a JDEBUG check:
<?php
if (JDEBUG) {
Log::add(sprintf('Syncing %d closures', \count($closures)), Log::DEBUG, 'com_tallpine.sync');
}
Source: Joomla Manual: Logging
Which files exist and who creates them
In 6.2 the application’s setupLogging() registers these loggers, depending on Global Configuration, and your code can
add more:
| File in the log folder | Written when | Contains |
|---|---|---|
|
always |
Entries in the |
|
Log Deprecated API is on |
Entries in the |
|
Log Almost Everything is on |
Every entry except the deprecation categories ( |
|
Log Priorities and Log Categories are set |
Only entries matching them. Log Category Mode decides whether the listed categories are included or excluded. The categories are split at any character other than letters, digits, underscore, dot and hyphen. |
the name you give |
your code calls |
What you route to it. |
Custom logging with Global Configuration needs no code: put com_tallpine in Log Categories, choose the priorities,
set the mode to Include, and custom-logging.php collects only the Tallpine entries. An administrator can turn it
off, which is why an extension that depends on its log should register its own logger.
Registering your own logger
Log::addLogger($options, $priorities, $categories, $exclude) takes an options array, the priorities to accept, the
categories to include (or to exclude when the fourth argument is true). Register loggers early, for example in the
extension’s boot() method or the plugin’s constructor, and only once per request.
<?php
namespace Tallpine\Component\Tallpine\Administrator\Extension;
use Joomla\CMS\Extension\BootableExtensionInterface;
use Joomla\CMS\Extension\MVCComponent;
use Joomla\CMS\Log\Log;
use Psr\Container\ContainerInterface;
final class TallpineComponent extends MVCComponent implements BootableExtensionInterface
{
public function boot(ContainerInterface $container): void
{
// Our own file, errors and worse, only the com_tallpine category.
Log::addLogger(
[
'text_file' => 'com_tallpine.log.php',
'text_entry_format' => '{DATETIME} {PRIORITY} {CATEGORY} {MESSAGE}',
],
Log::ERROR | Log::CRITICAL | Log::ALERT | Log::EMERGENCY,
['com_tallpine']
);
}
}
Source: Joomla Manual: Logging
The options of the text-file logger:
-
text_file: the file name. It defaults toerror.php. -
text_file_path: the folder; the default is the configured log folder. -
text_file_no_php: when false (the default) the file carries the.phpextension and begins with a line that stops the file from being served when someone requests it by URL. Set it to true only if the folder is not web-accessible and another tool must read the file. -
text_entry_format: the line template. The default is a tab-separated{DATETIME}\t{PRIORITY}\t{CLIENTIP}\t{CATEGORY}\t{MESSAGE}; other placeholders are{TIME}and{DATE}. -
defer: collects entries and writes them at the end of the request.
The priorities argument above uses |; the Manual’s example adds the constants with `, which gives the same result
for distinct flags. Do not add a priority twice with `, which would produce a different number.
Other loggers are selected with the logger option: messagequeue shows entries in the message area, echo prints
them, inmemory keeps them for the request, and there are syslog, database, callback, w3c, formattedtext and
others in libraries/src/Log/Logger. A custom logger class is registered with Log::registerLogger($key, $class) and
must extend Joomla\CMS\Log\Logger.
<?php
use Joomla\CMS\Log\Log;
// Show warnings of the sync in the administrator message area during development.
Log::addLogger(['logger' => 'messagequeue'], Log::WARNING | Log::ERROR, ['com_tallpine.sync']);
Log::add('Closure feed returned 0 items', Log::WARNING, 'com_tallpine.sync');
Source: Joomla Manual: Logging
PSR-3
Log::createDelegatedLogger() returns an object that implements Psr\Log\LoggerInterface, so code and libraries
written against the PSR-3 interface log through Joomla’s routing. A PSR-3 level such as critical() is mapped to the
matching priority, and the category is read from the context array.
<?php
use Joomla\CMS\Log\Log;
$logger = Log::createDelegatedLogger();
$logger->critical('Park authority API unreachable', ['category' => 'plg_task_tallpine_trailsync']);
Source: Joomla Manual: Logging
Logging pitfalls and security
-
Log::add() can throw. If the file cannot be written (permissions, a full disk) the logger raises an exception. In a Docker volume owned by root the log folder is not writable by
www-data; fix the ownership instead of catching everything. -
Logger registered too late. An entry added before a matching logger exists is dropped. Register loggers in
boot()or in the plugin constructor, not in a template. -
Excluded category mode. With Category Mode set to exclude, the categories listed are not logged, and everything else is, which is the opposite of what many administrators expect.
-
Files grow without limit. Joomla does not rotate its log files. Rotate them with
logrotateor a container log driver, or log to standard error from a custom logger in a container. -
Secrets and personal data. Do not log passwords, tokens, the session id or complete form submissions. Log the identifier (
trail 17), not the member’s data. Log files contain client IP addresses, which are personal data under the GDPR; see Privacy and Action Logs. -
Log injection. A message built from user input can add fake lines. Strip newlines and control characters from values that come from requests.
-
Keep the folder outside the web root in a hardened install, as Global Configuration suggests, and rely on the
.phpguard as a second line of defence only. -
Logs are not the audit trail. The Action Logs component records what users did; it is a different, user-facing feature, covered in the same privacy page.
A debugging workflow for com_tallpine
-
Reproduce the problem locally in the Compose stack, with Debug System on, Allowed Groups set to Super Users and Error Reporting
maximum. -
Read the Debug console: the Queries tab for slow or duplicated statements, the Language tab for missing keys, the Log tab for entries that code already wrote.
-
If the console is not enough, start Xdebug with the trigger, set a breakpoint at the controller task and step towards the failing line.
-
Add a
Log::add()call with the extension’s category where the failure would have been visible, and keep it: a production failure will then leave a line. -
Run with Log Deprecated API on and fix every entry that names your files before moving to the next major version; see Deprecations and Preparing for Joomla 7.
-
Turn Debug System and Debug Language off and verify the fix once more with production settings.
Where older books and tutorials are outdated
Older material about debugging Joomla was written for earlier versions, and some of it is now misleading:
-
Joomla 3 tutorials call the debugger Debug Mode and describe a console built into the plugin as a table at the foot of the page; since Joomla 4 the console is a php-debugbar bar with tabs, and the plugin’s options are different.
-
Books and wiki pages written for Joomla 3 use
JLog::add(),JFactory::getApplication()->enqueueMessage()andJDEBUGthrough theJclasses. In Joomla 6 useJoomla\CMS\Log\Log; theJclass aliases are deprecated and log a deprecation (see Error Handling and Legacy APIs). -
Xdebug 2 settings (
xdebug.remote_enable,xdebug.remote_host,xdebug.remote_port9000) were replaced in Xdebug 3 byxdebug.mode,xdebug.client_hostandxdebug.client_port9003. Tutorials with the old names do nothing in current versions. -
Older tutorials turn on Debug System and leave it on. The User Guide and the Manual both position it as a temporary tool, and a public site should restrict the console to Super Users.
-
Developing Extensions for Joomla! 5 (Packt, 2023) and Joomla! 4 Masterclass (Packt, 2023) cover debugging only briefly; for Joomla 5.1 and later the Manual’s logging page, the Joomla 6 source and the Xdebug documentation are the authoritative sources.
-
The legacy wiki at docs.joomla.org still has debugging pages for Joomla 1.5 to 3; the current User Guide and Manual supersede them.