1. Go to this page and download the library: Download joby/smol-context library. Choose the download type require.
2. Extract the ZIP file and open the index.php.
3. Add this code to the index.php.
<?php
require_once('vendor/autoload.php');
/* Start to develop here. Best regards https://php-download.com/ */
joby / smol-context example snippets
use Joby\Smol\Context\Context;
// Register a class (lazy-loaded on first get)
Context::register(App\UserService::class);
// Register a concrete instance
Context::register(new App\Logger());
// Get registered services
$users = Context::get(App\UserService::class);
$logger = Context::get(App\Logger::class);
// Services are cached - same instance every time
assert($logger === Context::get(App\Logger::class));
use Joby\Smol\Context\Context;
// Default: Only retrievable by exact class name
Context::register(App\Services\MysqlDatabase::class);
Context::get(App\Services\MysqlDatabase::class); // ✓ Works
Context::get(App\Contracts\DatabaseInterface::class); // ✗ Throws exception
// Register under a specific interface
Context::register(
App\Services\MysqlDatabase::class,
also: App\Contracts\DatabaseInterface::class
);
Context::get(App\Services\MysqlDatabase::class); // ✓ Works
Context::get(App\Contracts\DatabaseInterface::class); // ✓ Works (same instance)
// Register under multiple interfaces/classes
Context::register(
App\Services\RedisCache::class,
also: [
App\Contracts\CacheInterface::class,
App\Contracts\Storage::class
]
);
Context::get(App\Services\RedisCache::class); // ✓ Works
Context::get(App\Contracts\CacheInterface::class); // ✓ Works (same instance)
Context::get(App\Contracts\Storage::class); // ✓ Works (same instance)
// Register under ALL parent classes and interfaces
Context::register(
App\Services\FileLogger::class,
also: true
);
// Now retrievable by FileLogger, Logger, LoggerInterface, etc.
// Each call creates a new instance
$parser1 = Context::new(App\Parser::class);
$parser2 = Context::new(App\Parser::class);
assert($parser1 !== $parser2);
if (Context::has(App\UserService::class)) {
$users = Context::get(App\UserService::class);
}
use Joby\Smol\Context\Context;
Context::register(App\UserService::class);
Context::register(App\Logger::class);
$result = Context::execute(
function (App\UserService $users, App\Logger $logger): string {
$logger->log('Processing...');
return $users->process();
}
);
use Joby\Smol\Context\Context;
use Joby\Smol\Context\ConfigValue;
use Joby\Smol\Config\Sources\ArraySource;
// Add config source
$runtime = new ArraySource();
$runtime['name'] = 'My Application';
$runtime['host'] = 'localhost';
Context::container()->config->addSource('app', $runtime);
Context::container()->config->addSource('db', $runtime);
// Inject config values into callables
$result = Context::execute(
function (
#[ConfigValue('app/name')] string $appName,
#[ConfigValue('db/host')] string $dbHost,
): string {
return "{$appName} @ {$dbHost}";
}
);
use Joby\Smol\Config\Sources\ArraySource;
Context::register(App\Logger::class);
$config = new ArraySource();
$config['debug'] = true;
Context::container()->config->addSource('app', $config);
Context::execute(
function (
App\Logger $logger,
#[ConfigValue('app/debug')] bool $debug,
): void {
if ($debug) {
$logger->enableDebugMode();
}
}
);
use App\UserService;
use App\Logger;
/**
* @var UserService $users
* @var Logger $logger
*/
$logger->log('Generating report...');
return $users->generateReport();
use Joby\Smol\Context\Context;
Context::register(App\UserService::class);
Context::register(App\Logger::class);
$report = Context::
use App\Logger;
/**
* #[ConfigValue("app/name")]
* @var string $appName
*
* @var Logger $logger
*/
$logger->log("Report for {$appName}");
use Joby\Smol\Context\Context;
Context::register(new App\Logger());
$loggerA = Context::get(App\Logger::class);
// Create isolated scope by cloning
Context::openFromClone();
Context::register(new App\Logger());
$loggerB = Context::get(App\Logger::class);
Context::close();
$loggerC = Context::get(App\Logger::class);
// Back to original scope
assert($loggerA === $loggerC);
assert($loggerA !== $loggerB);
Context::openEmpty();
// Fresh container with no services
Context::register(App\TestLogger::class);
// ... test code ...
Context::close();
$container = new Container();
$container->register(App\MockService::class);
Context::openFromContainer($container);
// Use the custom container
Context::close();
// Clear stack and current container
Context::reset();
// Register services at application bootstrap
Context::register(App\Database::class);
Context::register(App\Logger::class);
// Use throughout request handling
$router->add(
new ExactMatcher('users'),
function (Request $request) {
$db = Context::get(App\Database::class);
return Response::json($db->getUsers());
}
);
// Register implementations under their interfaces
Context::register(
App\Services\PdoDatabase::class,
also: App\Contracts\DatabaseInterface::class
);
Context::register(
App\Services\RedisCache::class,
also: App\Contracts\CacheInterface::class
);
// Route handlers can depend on interfaces
$router->add(
new ExactMatcher('users'),
function (
App\Contracts\DatabaseInterface $db,
App\Contracts\CacheInterface $cache
) {
// Dependencies injected automatically
return Response::json($db->getUsers());
}
);