Controller
Controller
UglyDuckling covers 90% of use cases through JSON resources. When business logic becomes too complex for a JSON resource, you implement a controller.
A controller in UglyDuckling works similarly to a controller in any MVC framework. It implements getRequest() and postRequest() methods, validates and filters incoming parameters, queries the database, and exposes data to a view file.
Controller skeleton
class MyController extends BaseController {
public function __construct() {
parent::__construct();
$this->classCompleteName = __CLASS__;
$this->className = 'MyController';
$this->chapter = 'Website';
$this->templateFile = 'websitetemplate';
$this->viewFile = 'src/Chapters/Website/Views/MyController';
$this->controllerPointer = $this;
$this->appTitle = 'My website title';
}
public function check_authorization_get_request() {
return true;
}
public $get_validation_rules = ['authorid' => 'required|integer'];
public $get_filter_rules = ['authorid' => 'trim'];
public function getRequest() {
}
public function check_authorization_post_request() {
return true;
}
public $post_validation_rules = ['title' => 'required|max_len,255'];
public $post_filter_rules = ['title' => 'trim|sanitize_string'];
public function postRequest() {
}
}Constructor
A controller must extend BaseController. The constructor sets several properties that the framework uses to route requests, load templates, and render views.
| Property | Description |
|---|---|
$this->classCompleteName |
Fully qualified class name (__CLASS__). Useful in shared view and template files to identify which controller was called. |
$this->className |
Short class name. Same use as above. |
$this->chapter |
The chapter (domain folder) the controller belongs to. Controllers live at src/Chapters/{Chapter}/Controllers/. |
$this->templateFile |
Name of the template file inside src/Templates/ (without .php). |
$this->viewFile |
Path prefix for the view file. The framework appends Get.php, Post.php, GetError.php, or PostError.php depending on the request. |
$this->controllerPointer |
A reference to $this. Required for the template to access controller properties. |
$this->appTitle |
Application title, typically used in the <title> tag of the template. |
public function __construct() {
parent::__construct();
$this->classCompleteName = __CLASS__;
$this->className = 'MyController';
$this->chapter = 'Website';
$this->templateFile = 'websitetemplate';
$this->viewFile = 'src/Chapters/Website/Views/MyController';
$this->controllerPointer = $this;
$this->appTitle = 'My website title';
}Each controller must also be registered in index_controllers.php with a URL slug that maps to the controller class. The slug corresponds to the CONTROLLER_NAME constant:
const CONTROLLER_NAME = 'mycontroller';
// → reachable at www.myapplication.com/mycontroller.htmlGET request
check_authorization_get_request
Override this method to restrict which users can make a GET request to this controller. Return true to allow, false to deny.
Check by session group:
public function check_authorization_get_request() {
return isset($_SESSION['group'])
&& in_array($_SESSION['group'], ['readergroup', 'writergroup']);
}Check ownership via the database:
public function check_authorization_get_request() {
$bookDao = new BookDao();
$bookDao->setDBH($this->dbconnection->getDBH());
$mybook = $bookDao->getOneByFields(['id' => $this->getParameters['id']]);
return $mybook->author_id === $_SESSION['user_id'];
}Validation and filter rules
Declare $get_validation_rules and $get_filter_rules as public properties to validate and filter GET parameters before getRequest() is called. The framework runs these automatically and populates $this->getParameters with the cleaned values.
public $get_validation_rules = ['authorid' => 'required|integer'];
public $get_filter_rules = ['authorid' => 'trim'];Multiple rules for the same field are separated by a pipe. Rules that take a parameter use a comma:
public $get_validation_rules = [
'id' => 'required|integer',
'slug' => 'required|alpha_numeric_dash|max_len,100',
];
public $get_filter_rules = [
'id' => 'trim',
'slug' => 'trim|sanitize_string|lowercase',
];See Validation for the full list of available rules and filters.
getRequest
Override this method to query the database and prepare data for the view. Every property you assign on $this becomes a variable available in the view file.
public function getRequest() {
$bookDao = new BookDao();
$bookDao->setDBH($this->dbconnection->getDBH());
$this->books = $bookDao->getByFields(['author_id' => $this->getParameters['authorid']]);
$this->author = 'William Shakespeare';
}View file
The view file renders the data prepared by getRequest(). It is loaded from the path defined in $this->viewFile with Get.php appended — e.g. src/Chapters/Website/Views/MyControllerGet.php.
<h4><?= $author ?></h4>
<ul>
<?php foreach ($books as $book): ?>
<li><?= htmlspecialchars($book->title) ?></li>
<?php endforeach; ?>
</ul>Handling validation errors
When GET parameters fail validation the framework calls show_get_error_page() instead of getRequest() and loads MyControllerGetError.php as the view. Override the method to prepare any data the error view needs. The validation error message is available in $this->readableErrors.
public function show_get_error_page() {
$this->errorMessage = $this->readableErrors;
}<div class="alert alert-danger"><?= htmlspecialchars($errorMessage) ?></div>POST request
check_authorization_post_request
Same concept as the GET version, but for POST requests. Return true to allow, false to deny.
public function check_authorization_post_request() {
return isset($_SESSION['group'])
&& in_array($_SESSION['group'], ['readergroup', 'writergroup']);
}Validation and filter rules
Declare $post_validation_rules and $post_filter_rules to validate and filter POST parameters before postRequest() is called. Validated values are available in $this->postParameters.
public $post_validation_rules = [
'title' => 'required|max_len,255',
'email' => 'required|valid_email',
'price' => 'required|float|min_numeric,0',
'avatar' => 'required_file|extension,jpg;jpeg;png;gif',
];
public $post_filter_rules = [
'title' => 'trim|sanitize_string',
'email' => 'trim|sanitize_email|lowercase',
'price' => 'trim|sanitize_floats',
];See Validation for the full list of available rules and filters.
postRequest
Override this method to process the submitted data — save to the database, send emails, and so on. Every property assigned on $this is available in the view.
public function postRequest() {
$bookDao = new BookDao();
$bookDao->setDBH($this->dbconnection->getDBH());
$bookDao->insert([
'title' => $this->postParameters['title'],
'author_id' => $_SESSION['user_id'],
]);
$this->redirectToPreviousPage();
}View file
Loaded from $this->viewFile with Post.php appended — e.g. src/Chapters/Website/Views/MyControllerPost.php.
<p>Book saved successfully.</p>Handling validation errors
When POST parameters fail validation the framework calls show_post_error_page() and loads MyControllerPostError.php. The validation error message is available in $this->readableErrors.
public function show_post_error_page() {
$this->errorMessage = $this->readableErrors;
}<div class="alert alert-danger"><?= htmlspecialchars($errorMessage) ?></div>Redirect
After a POST request it is common to redirect rather than render a view. Four helper methods are available:
| Method | Description |
|---|---|
redirectToPreviousPage() |
Redirect to the last GET request the user made. |
redirectToSecondPreviousPage() |
Redirect to the GET request before that. |
redirectToPage($url) |
Redirect to a specific URL. If the constant BASE_PATH is defined it is prepended automatically. |
redirectToDefaultPage() |
Redirect to the application’s default page defined in DEFAULT_PAGE. BASE_PATH is prepended if defined. |
public function postRequest() {
// ... save data ...
$this->setSuccess('Record saved successfully.');
$this->redirectToPreviousPage();
}Flash messages
You can pass a one-request message to the next page using these methods, which persist the value in the session until it is read:
| Method | Description |
|---|---|
setSuccess($msg) |
Green success message. |
setError($msg) |
Red error message. |
setInfo($msg) |
Blue informational message. |
setWarning($msg) |
Yellow warning message. |
The messages are automatically picked up by the messages block in the next controller’s makeAllPresets() and made available in the view.