Controller
Controllers handle incoming HTTP requests and return responses. All controllers must extend CController and are stored in the controllers/ directory.
Basic Controller
A minimal controller with a single action:
<?php
class Controller_Example extends CController {
public function index() {
return c::response('Hello, World!');
}
}
This controller handles requests to /example and /example/index.
See Routing for details on how URLs map to controllers and methods.
File Naming
Controller classes follow the underscore-to-directory naming convention. The Controller_ prefix maps to the controllers/ directory, and each subsequent segment maps to a subdirectory or filename (lowercase).
| Class Name | File Path |
|---|---|
Controller_Home |
controllers/home.php |
Controller_App_Home |
controllers/app/home.php |
Controller_Admin_Setting_Plan |
controllers/admin/setting/plan.php |
Method Visibility
Only public methods are accessible via URL. Use protected or private for internal helper methods that should not be routable.
<?php
class Controller_Example extends CController {
public function index() {
// Accessible via /example/index ✓
$data = $this->loadData();
return c::response($data);
}
protected function loadData() {
// NOT accessible via URL ✗ (returns 404)
return 'internal data';
}
}
Magic methods (__construct, __call, etc.) and internal controller methods (callAction, middleware, getMiddleware) are also blocked from URL access.
Returning Responses
Controllers can return different types of responses:
CApp (Page Builder)
The most common pattern in CF. CApp is a page builder object that renders a full HTML page with the configured theme, navigation, and assets.
<?php
class Controller_App_Dashboard extends CController {
public function index() {
$app = c::app();
$app->title('Dashboard');
$app->setView('dashboard');
return $app;
}
}
You can also build the page programmatically by adding elements:
<?php
class Controller_App_User extends CController {
public function index() {
$app = c::app();
$app->title('Users');
$table = $app->addTable();
$table->setDataFromModel(UserModel::class);
$table->addColumn('name')->setLabel('Name');
$table->addColumn('email')->setLabel('Email');
return $app;
}
}
Note: Using
echo $app->render()is deprecated. Always usereturn $app.
Plain Response
Return a simple text or HTML response:
<?php
public function health() {
return c::response('OK');
}
public function page() {
return c::response('<h1>Hello</h1>', 200, ['Content-Type' => 'text/html']);
}
JSON Response
Return JSON data for API endpoints:
<?php
public function apiUsers() {
$users = UserModel::all();
return c::response()->json([
'status' => 'success',
'data' => $users->toArray(),
]);
}
View Response
Return a rendered Blade or PHP view:
<?php
public function about() {
return c::view('about', [
'title' => 'About Us',
'team' => TeamModel::all(),
]);
}
Redirect
Redirect to another URL or controller:
<?php
public function index() {
return c::redirect('app/home');
}
public function store() {
// ... process form
return c::redirect()->back();
}
Abort
Return an error response:
<?php
public function show($id) {
$item = ItemModel::find($id);
if (!$item) {
c::abort(404);
}
// ...
}
Authentication
By default, when auth.enable is true in config/app.php, all pages require login and will redirect unauthenticated users to the login page. To make a page publicly accessible, disable authentication using setLoginRequired(false):
<?php
class Controller_Home extends CController {
public function index() {
$app = c::app();
$app->setLoginRequired(false);
$app->addView('landing');
return $app;
}
}
Available methods on CApp:
| Method | Description |
|---|---|
setLoginRequired(false) |
Disable auth check for the current request |
setLoginRequired(true) |
Enable auth check (default when auth.enable is true) |
disableAuth() |
Alias for setLoginRequired(false) |
enableAuth() |
Alias for setLoginRequired(true) |
isLoginRequired() |
Check if auth is currently required |
For base controllers that handle multiple public pages, set it in the constructor:
<?php
class MyApp_Controller_PublicController extends CController {
public function __construct() {
parent::__construct();
c::app()->setLoginRequired(false);
}
}
Middleware
Register middleware in the controller constructor. Middleware runs before the controller action is executed.
<?php
class Controller_Api_Data extends CController {
public function __construct() {
parent::__construct();
$this->middleware(MyApp_Middleware_AuthApi::class);
}
public function index() {
// Only accessible if middleware passes
}
}
Restricting Middleware to Specific Methods
Use only() or except() to limit which methods the middleware applies to:
<?php
class Controller_Admin extends CController {
public function __construct() {
parent::__construct();
// Only apply to 'store' and 'update' methods
$this->middleware(MyApp_Middleware_VerifyCsrf::class)
->only(['store', 'update']);
// Apply to all methods except 'index'
$this->middleware(MyApp_Middleware_RequireAdmin::class)
->except('index');
}
}
Constructor
Use the constructor for setup that applies to all methods in the controller, such as registering middleware or configuring the application instance.
Always call parent::__construct() first:
<?php
class Controller_Docs extends CController {
public function __construct() {
parent::__construct();
c::app()->setLoginRequired(false);
c::app()->setTheme('docs-theme');
}
public function index() {
// Theme and login settings are already applied
}
}
Base Controllers
For shared behavior across multiple controllers, create a base controller class in your application's libraries/ directory:
<?php
// libraries/MyApp/Controller/AppController.php
class MyApp_Controller_AppController extends CController {
public function __construct() {
parent::__construct();
c::app()->setLoginRequired(true);
c::manager()->theme()->setTheme('my-theme');
}
}
Then extend it in your controllers:
<?php
class Controller_App_Home extends MyApp_Controller_AppController {
public function index() {
$app = c::app();
$app->title('Home');
// Theme and login are already configured by the base class
return $app;
}
}
Registering Assets
Register CSS and JavaScript assets from within a controller:
<?php
public function index() {
$app = c::app();
CManager::registerCss('my-app/dashboard.css');
CManager::registerJs('my-app/dashboard.js');
// Or using the shorthand
c::manager()->registerCss('build/main.css');
c::manager()->registerJs('build/main.js');
return $app;
}
Controller URL Helper
Get the URL that maps to a controller class:
<?php
class Controller_App_User extends CController {
public function index() {
// Get the base URL for this controller
$url = static::controllerUrl();
// Returns: http://example.com/app/user/
}
}
HTTP Verb Prefixes
Restrict a controller method to specific HTTP verbs by prefixing the method name. See Routing - HTTP Verb Prefixes for full details.
<?php
class Controller_Api_Product extends CController {
public function getList() {
// GET /api/product/list
}
public function postCreate() {
// POST /api/product/create
}
public function deleteRemove($id) {
// DELETE /api/product/remove/5
}
}