Developers
The basics
The handful of things every extension touches: reading the request, writing the response, finding configuration, translating strings, working with the current user, tagging things, handling dates, running scheduled work, and seeing what went wrong.
The examples through this section build one small component: com_bookings,
which lets a lab take reservations on its instruments. It is the ordinary
shape of the work — a list, a form, a save, a nightly tidy-up — and it
touches every page here.
Each of these is reached through a facade — Request, Response,
Config, Lang, User, Date — which is a short name in the root
namespace standing in for an object in the application container.
In this section
- Requests — reading input safely, and what the request knows about itself.
- Responses — headers, content, and sending.
- Redirect —
App::redirect(), and what it does to the rest of your method. - Config — global, component, plugin and module configuration.
- Languages — INI files, key naming,
Lang::txt(), and overrides. - Users & profiles — the current user, other users, extended profile fields, and group membership.
- Tags — attaching tags to your component's objects.
- Debugging — debug mode, dumping variables, and the logs.
- Scheduled tasks — registering work for the cron runner.
- Dates — the one subject where getting it wrong is silent: the platform stores and compares in UTC and converts only for display.
A worked shape
Most controller tasks look like this, and touch four of the above in a dozen lines:
namespace Components\Bookings\Site\Controllers;
use Hubzero\Component\SiteController;
use Components\Bookings\Models\Booking;
use Request;
use Notify;
use Config;
use Route;
use Lang;
use Date;
use App;
class Bookings extends SiteController
{
public function saveTask()
{
// Every write is guarded by the form token
Request::checkToken();
$fields = Request::getArray('fields', array(), 'post');
$row = Booking::oneOrNew($fields['id'])->set($fields);
// The member typed a local time; the column holds UTC
$row->set('starts', Date::of($fields['starts'], Config::get('offset'))->toSql());
if (!$row->save())
{
Notify::error($row->getError());
return $this->editTask($row);
}
App::redirect(
Route::url('index.php?option=' . $this->_option),
Lang::txt('COM_BOOKINGS_BOOKING_SAVED')
);
}
}
Input arrives typed rather than raw, the write is guarded by the token, the date is read in the hub's time zone and written in UTC, the message is a language key that must exist in the component's own INI file, and the redirect ends the request.
Four of those five have a silent failure mode. Miss the token check and the task still works. Miss the time zone and the booking still saves. Miss the language key and the page still renders. Miss the redirect and the member still sees their booking. Each chapter says what that looks like.
Rewritten and checked against 2.4-main @ 348f0057c2 on 2026-09-10.