Implementing controllers
The ApplicationController class
The ApplicationController class is defined to allow the application programmer to add controller behaviours that are common to all application controllers without having the modify the Controller class.
To ensure future compatibility, application writers should not directly modify the Controller class and should not directly inherit from it. Instead, all controllers should be defined to inherit from ApplicationController. Woof! itself does not add any new variables or methods in this class and promises not to modify it in future releases. The wag stubs generator also generates stubs that follows this rule.
Defining a controller class
A minimal controller class definitions takes the following form:
oo::class create SampleController { superclass ApplicationController constructor args { # Very important to pass arguments to parent next {*}$args ...other initialization code... } method index {} { # The default method for the controller ...some code here... } }
As discussed above, the class derives from ApplicationController. The constructor passes any specified arguments to its base class and then completes initialization. It is important to call the base class constructor before using any of the standard objects such as request, session etc. created by the base Controller class.
The initialization steps may include application-specific code as well as some standard Woof! code such as setting up default layout parameters, stylesheets and so on.
Controller class names and namespaces
Controller classes are read into the ::woof::app namespace. One important point to note is that the class name does not have any namespace qualifiers in its definition. Even if the controller is defined to be in a module, the class definition itself should generally not include the namespace. Woof! will automatically instantiate the class into the appropriate namespace based on the module name.
For example, assuming the application URL root is /, the URL /mod1/mod2/my_sample/index corresponds to the index action in controller my_sample in the module mod1::mod2. The corresponding controller implementation will be located under the Woof! directory in the file app/controllers/mod1/mod2/sample_controller.tcl. The controller class as defined in the sample above (without any namespace qualifiers), will be created as ::woof::app::mod1::mod2::MySample.
If at all namespace qualifiers are used, the class name must be fully qualified and begin with ::woof::app and include the module namespaces if any. So the class definition above could have been defined with the fully qualified name ::woof::app::mod1::mod2::MySample but this is not recommended.
The uses command
Controllers may share behaviours through a common base class. To implement this, the common base class must be made available in the source file implementing the controller. To facilitate this, Woof! provides the uses command that can be used to import the base class definition. For example, the file sample_controller.tcl shown above could be modified as shown below:
uses BaseController oo::class create SampleController { superclass BaseController constructor args { Very important to pass arguments to parent next {*}$args ...other initialization code... } method index {} { The default method for the controller ...some code here... } }
Woof! will then look for, and automatically load the file base_controller.tcl.
The argument provided to the uses command must be either an unqualified class name, in which case the corresponding file is expected to be in the same directory as the controller file calling uses, or it must be qualified with a relative namespace, in which case the corresponding file is located relative to the app/controllers directory under the Woof! root.