Developers

Services

The framework registers a small set of long-lived objects in the application container at boot: a cache store, a filesystem, a session, an event dispatcher. Extensions reach them through facades rather than constructing them, so that a hub can swap the implementation without touching extension code.

That indirection is the point, and it is also the thing that surprises people. A service can be configured into a do-nothing version, and the do-nothing version accepts every call and answers plausibly rather than raising. Nothing in this section fails loudly.

Service What it silently does nothing about
Cache With caching off, and in the administrator application always, the store is None: every put() succeeds and every get() misses
Session get() and has() return the default when no session is active, rather than raising
Events An event nothing listens to returns an empty array, which is what a disabled plugin also returns
Filesystem The None adapter exists for tests; write() returning false is the only signal a write failed
Server serve() returns false rather than throwing, and checks nothing about permissions

So test the return value, and do not build anything that depends on a service having remembered something.

How a service gets there

Each service is registered by a service provider under core/bootstrap/, one directory per client (Site, Administrator, Api, Cli). The provider binds a closure to a key on the container; the closure runs the first time something asks for that key, and its result is cached for the rest of the request.

	public function register()
	{
		$this->app['cache'] = function($app)
		{
			return new Manager($app);
		};

		$this->app['cache.store'] = function($app)
		{
			$handler = !$app['config']->get('caching') ? 'none' : $app['config']->get('cache_handler');

			if ($app->isAdmin())
			{
				$handler = 'none';
			}

			return $app['cache']->storage($handler);
		};
	}

Because the closure reads $app['config'], the service you get back depends on the hub's configuration. The cache store above is a real file cache on a hub with caching turned on and a do-nothing None store on one without. The service providers chapter covers the registration mechanism itself; the chapters here cover what each service does once you have it.

Reaching a service

Two ways, and they return the same object:

$filesystem = App::get('filesystem');

// or, through the facade
Filesystem::exists($path);

Prefer the facade. It is shorter, and a test can put a double in the container under the same key and the facade will pick it up.

Not every client registers every service. Cache, Session, Module, Pathway, Notify, Document and Html are site and administrator only; App, Config, Request, Response, Event, Route, User, Lang, Log, Date, Plugin and Filesystem exist everywhere. Each client's list is its own aliases.php.

In this section

  • Cache — the cache store, its drivers, and the group convention that makes Cache::clean() selective.
  • Filesystem — reading, writing, and listing files through an adapter, and the macros that extend it.
  • Session — per-visitor storage, namespaces, and the form token that guards every write.
  • Events — the dispatcher, how a plugin group becomes a listener, and what Event::trigger() gives back.
  • Server — serving a file off disk as a download.

Configuration, requests, responses, language, dates and users are covered in the basics.

Rewritten and checked against 2.4-main @ 348f0057c2 on 2026-09-10.