Configuration
Canvas follows convention-over-configuration. It works immediately with zero setup - create config files only when you need to override defaults.
Simple Configuration
Canvas works out of the box. Add config files only for custom settings:
// config/database.php
return [
'driver' => 'mysql',
'host' => 'localhost',
'database' => 'canvas',
'username' => 'root',
'password' => '',
];
Automatic Service Discovery
Register configuration through Composer metadata - Canvas discovers and loads it automatically:
// composer.json
{
"extra": {
"discover": {
"canvas": {
"providers": [
{
"class": "Quellabs\\Canvas\\Discover\\DatabaseServiceProvider",
"config": "config/database.php"
}
]
}
}
}
}
Package Auto-Discovery
Install packages - Canvas detects and configures them automatically:
composer require quellabs/canvas-twig # Auto-configures Twig
composer require quellabs/canvas-blade # Auto-configures Blade
composer require quellabs/canvas-redis # Auto-configures Redis
Contextual Configuration
Use different implementations of the same interface in different contexts. The `for()` method creates isolated configuration scopes:
// Same interface, different implementations
$twig = $this->container->for('twig')->get(TemplateEngineInterface::class);
$blade = $this->container->for('blade')->get(TemplateEngineInterface::class);
// Same interface, different storage backends
$redis = $this->container->for('redis')->get(CacheInterface::class);
$file = $this->container->for('file')->get(CacheInterface::class);
Aspect Configuration
Configure aspects through annotation parameters:
/**
* @InterceptWith(CacheAspect::class, ttl=3600, tags={"reports", "admin"})
* @InterceptWith(RateLimitAspect::class, limit=10, window=60)
*/
public function heavyOperation() {
// Cached for 1 hour with tags, rate limited to 10/minute
}
Custom Service Providers
Create discoverable service providers for custom configuration. Access config through the injected config parameter:
class PaymentServiceProvider extends ServiceProvider {
public function supports(string $className, array $context = []): bool {
return
$className === PaymentInterface::class &&
($context['provider'] ?? null) === 'stripe';
}
public function createInstance(string $className, array $dependencies, array $config): object {
return new StripePaymentService($config['api_key']);
}
}
Zero Configuration Example
This works immediately without any setup:
class HomeController extends BaseController {
/**
* @Route("/")
*/
public function index() {
return $this->render('home.tpl');
}
}