Download the PHP package anax/controller without Composer
On this page you can find all versions of the php package anax/controller. It is possible to download/install these versions without Composer. Possible dependencies are resolved automatically.
Download anax/controller
More information about anax/controller
Files in anax/controller
Package controller
Short Description Anax Controller module, with sample starter controllers.
License MIT
Homepage https://dbwebb.se/anax
Informations about the package controller
Anax Controller
Anax Controller is a collection of sample utility controllers, use them as scaffold (copy and modify) when creating your own controllers.
The controller can be useful code structure when building a site, as an alternative to ordinary route callbacks.
Table of content
- Class, interface, trait
- Exceptions
- App style or di style
- Mounting a controller class on the router
- How route path maps to controller/action
- Returning values from a controller method
- Returning a page from the controller method
- Send arguments to a controller method
- The initialize method
- The catchAll method
- Additional controller class members
Class, interface, trait
The following classes, interfaces and traits exists.
The following are used as is.
Class, interface, trait | Description |
---|---|
Anax\Controller\DevelopmentController |
To aid debugging and visualising Anax internals. |
Anax\Controller\ErrorhandlerController |
General error handler controller presenting a error page when a route is not found or throws an exception, only for internal routes. |
Anax\Controller\FlatFileContentController |
A rough implementation of a flat file content controller reading markdown files from content/ ant formatting into html and displaying in a page. |
The following are sample controllers that exists as samples, to copy and paste, when you build your own controller.
Class, interface, trait | Description |
---|---|
Anax\Controller\SampleAppController |
Implementation of a controller class that is injected with $app by the router. |
Anax\Controller\SampleController |
Implementation of a controller class that is injected with $di by the router. |
Anax\Controller\SampleJsonController |
Implementation of a controller class that is injected with $di by the router and returns json responses. |
Exceptions
There are no module specific exceptions.
It is common to use router exceptions when a route callback fails for some reason. Here are router exceptions that creates appropriate HTTP responses.
Exception | What |
---|---|
Anax\Route\Exception\ForbiddenException |
Results in a 304. |
Anax\Route\Exception\NotFoundException |
Results in a 404. |
Anax\Route\Exception\InternalErrorException |
Results in a 500. |
App style or di style
A controller class might need access to the framework service container which is implemented in $app
or $di
. The router injects the service container automatically, based on if the controller class has implementet a known interface.
The router injects $app
if the controller class implements Anax\Commons\AppInjectableInterface
.
The router injects $di
if the controller class implements Anax\Commons\ContainerInjectableInterface
.
To implement this behaviour a controller class should use the utilities provided by the module anax/commons
and create a controller class like this.
This is a app-style injection controller.
This is a di-style injection controller.
The service container will then be available as $this->app
or $this->di
, depending on the interface used.
Mounting a controller class on the router
A controller class is mounted on a route path, a mount point, in the router. This is done by adding a configuration file to the router.
This is a sample of how the DevelopmentController is mounted on a mount point dev/
. The file is stored as 600_development.php
in the directory config/router/
.
The configuration file states the mount point to be dev
and the controller class to be \Anax\Controller\DevelopmentController
.
You can review the content of the directory config/router
to see more examples on how the controller class can be mounted to a mount point in the router.
How route path maps to controller/action
All requests below the mount point will be forwarded to the mounted controller to deal with. When the controller fails to deal with a request, the router will treat the path as a NotFoundException.
Each method in the controller can map a route path, a controller action. Here follows some samples on how a controller method (action) can be referenced through a route path.
Lets say that the controller SampleAppController
is mounted on the mount point app
, then the following would be true.
Route path | Controller method (action) |
---|---|
app |
indexAction() |
app/index |
indexAction() , usually you avoid using the /index part when creating an url to this action, thus only linking to app/ . |
app/info |
infoAction() |
app/dump-some-data |
dumpSomeDataAction() |
The Action
part is needed, it tells the router that this controller method should be treated as a callable controller action and mapped to the route path.
The method name is mapped to the route path, except the Action
part which is removed. The method infoAction()
is mapped to the route path info
, the method dumpSomeDataAction()
is mapped to the route path dump-some-data
.
Specify what HTTP method to support
You can add the HTTP method at the end of the method name, then the HTTP request method must also be mapped, before the controller method is matched by the router.
Route path | HTTP method | Controller method (action) |
---|---|---|
app/create |
ANY | createAction() |
app/create |
GET | createActionGet() |
app/create |
POST | createActionPost() |
app/create |
PUT | createActionPut() |
app/create |
PATCH | createActionPatch() |
app/create |
DELETE | createActionDelete() |
Define a controller method (action)
Here are some samples on how to create a controller method.
This method maps to the route path app
or app/index
on any HTTP request method.
This method maps to the route path app/info
on GET HTTP request method.
The following two methods maps both the same route path app/create
, the first maps only GET requests and the second maps only POST request.
Returning values from a controller method
Each controller method can return a response.
When nothing is returned, the router treats this as a no operation and continues to find the next handler that can deal with the request.
When any value is returned, the controller treats this as the handler successfully dealt with the request and promplty returns the response to the caller.
The returned value is converted into an instance of the Anax response class.
When a controller method returns a string, the content of that string will be the response body. In the following example an page containing the body as Some kind of response
.
The controller method can return a JSON response by wrapping an array in an array. This is the converted into a JSON response by the Anax response class.
Note that the type hinted return type now is : array
instead of : string
.
You can optionally send a response status code.
Returning a page from the controller method
A controller method can add views to a page and then render it. The render phase results in a response object which is returned. Here is a sample controller method that creates and returns a rendered page (app style).
Note that the type hinted return type now is : object
instead of : string
or : array
.
Send arguments to a controller method
A controller method can take arguments, the arguments are mapped from the route path, like this.
mountpoint/action/argument1/argument2/argument3
So, if we want to create a controller method that replies to a route path like app/view/<id>
, which could be app/view/1
or app/view/42
, then we create a method that takes one argument, like this.
The method can take as many arguments as you need.
The initialize method
Sometimes you have a need to bootstrap the controller, you have some common startup code that you want to execute before any of the actual action callbacks are carried out.
That code should not be created in the constructor. Avoid using a constructor for the controller class. The reason is how the controller class is used and inspected by the router. The router must create a object of the controller, before it actually knows that the controller should be called. You should therefore avoid using a constructor and instead use the method initialize()
The router will always call the controller method initialize()
, if it is defined by the controller class.
The method can be defined like this.
Use the method to store the state in the class properties, for example create the connection to the database or create and initiate a set of objects.
The catchAll method
When the router fails to find a matching action, it will look for a method catchAll()
and call it, if it is defined. This method can be used to handle error cases, or it can be used to create a controller which has a single method that deals with all incoming route paths, independent of the actual route path.
Here is a template to use when creating your own catchAll()
.
The catchAll()
can take the arguments as a variadic variable ...$args
meaning that it can take any number of arguments and they are all stored in the array $args
.
You can review the following real life examples of using the catchAll()
in a controller.
Anax\Controller\DevelopmentController
Anax\Controller\ErrorController
Anax\Controller\FlatFileContentController
There is also a more powerful module for flat file content in anax/content
, you can review its controller here.
Additional controller class members
You can furthermore create any public, protected or private method and property within the controller class, besides these mentioned special controller methods.
This makes it possible to add common code, used in several controller actions, within class methods. Thus the controller enables some code reuse and allows for a proper code structure.
Thin or fat controller
The general idea is to have a thin controller, that is, small amount of code that glues together the framework with the model classes.
When your controller grows, take some time to thick if the code can be broken out into other (model) classes that are used by the controller.
A fat controller is the opposite of a thin controller. It has a large amount of code and logic in it.
Avoid fatness and break out your code in small usable classes, each class having a obvious and clear responsibility.
How to unit test a controller
A controller class can be unit tested like any other class. However, since a controller class is a glue between the framwork and your application (model) classes, it might need some preparations and even som fixtures, to make it easier.
A controller method that does not use the framework service container is pretty straightforward to test. Here is a sample of such a unit test (phpunit).
When you have a controller needing the service container you might want to use a setUp()
to setup the controller like it would be set up by the router.
Then you can add more test cases for each controller action, and if you have some internal controller methods or fail testing you want to add unit tests for.
As an example, you might want to review the test class SampleAppController
. it contains samples usable when creating your own test class for a controller.
License
This software carries a MIT license. See LICENSE.txt for details.