Controllers act as the traffic cop between a request (typically initiated by a user) and the different tiers of the application (represented by models and views). When a request is received by the application, it can be routed to an action on a server side controller. Once the response is sent back to the requestor, the corresponding client-side controller action will be triggered. An action can be any public method on the controller with the correct signature.

Server Side Controller Synopsis
  1. <?php
  2. namespace MyApplication\Controllers;
  4. use DblEj\Application\IMvcWebApplication;
  5. use DblEj\Communication\Http\Request;
  6. use DblEj\Mvc\ControllerBase;
  7. class MyController extends ControllerBase
  8. {
  9.    public function DefaultAction(Request $request, IMvcWebApplication $app)
  10.    {
  11.         return $this->createResponseFromRequest($request, $app);
  12.    }
  13.    public function MyOtherAction(Request $request, IMvcWebApplication $app)
  14.    {
  15.         //It is common for an action to perform some operation and then to redirect to the default action,
  16.         //which usually shows the default template for this controller.
  17.       return $this->DefaultAction($request, $app);
  18.    }
  19. }
  20. ?>
Server side controller action signature
  1. \DblEj\Communication\Http\ISitePageResponse ActionName(Request $request, IMvcWebApplication $app)
Client side controller action signature
  1. void ActionName(Array args)

Server side Controllers

Flow of a typical server side controller action:
Receive request from applicationRetrieve (and potentially update) data and expose it to the rendering engineFind the correct View to use for this requestRespond with information about the View and the data
What a typical server side controller might look like.
  1. <?php
  2. namespace MyAppNamespace\Controllers;
  4. use DblEj\Application\IMvcWebApplication;
  5. use DblEj\Communication\Http\Request;
  6. use DblEj\Mvc\ControllerBase;
  7. use MyAppNamespace\FunctionalModel\Product;
  8. use MyAppNamespace\FunctionalModel\Category;
  10. //hypothetical controller for a product page on an ecommerce website
  11. class Product extends ControllerBase
  12. {
  13.    /*
  14.     * The default action shows a web page for a product, based on a GET variable named SelectedProductId.
  15.     * Also being shown on this page is an index of all top-level product categories.
  16.     */
  17.    public function DefaultAction(Request $request, IMvcWebApplication $app)
  18.    {
  19.       //get value of HTTP GET variable SelectedProductId
  20.       $selectedProductId = $request->GetInputInteger("SelectedProductId");
  22.       //load the Functional Model that represents the requested product
  23.       if ($selectedProductId)
  24.       {
  25.           $selectedProduct = new Product($selectedProductId);
  26.       } else {
  27.           $selectedProduct=null;
  28.       }
  30.       //Get all top level categories, sorted by DisplayOrder
  31.       $allTopLevelCategories = Category::Filter("ParentCategoryId is null", "DisplayOrder");
  33.       //create a single model that encapsulates all of the data we want to expose to the Presentation Template
  34.       $arrayModel = new ArrayModel(["CATEGORIES"=>$allTopLevelCategories,"PRODUCT"=>$selectedProduct]);
  36.       //return a SitePageResponse which includes the rendered Presentation Template
  37.         return $this->createResponseFromRequest($request, $app, $arrayModel);
  38.    }
  39. }
  40. ?>

Relationship between server side controllers and views

In most common scenarios, once a controller has gathered any data needed for the presentation layer, it can use the convenience method createResponseFromRequest() to handle the remaining tasks, which include...

  • find the correct MVC view (a \DblEj\Mvc\SitePage, in this case)
  • expose data to the template rendering engine that the controller has gathered for the presentation layer
  • create and return a SitePageResponse
  • The controller doesn't actually render the view. It returns a SitePageResponse that encapsulates a view that is rendered later by the application.
Controller's createResponseFromRequest convnience method
  1. DblEj\Communication\Http\ISitePageResponse ControllerBase::createResponseFromRequest(Request $request, IMvcWebApplication $app, \DblEj\Data\IModel $dataModel=null, \DblEj\Presentation\RenderOptions $options=null,Headers $headers=null)

By default, createResponseFromRequest returns [a response that encapsulates] a view by the same name as itself.
So, for example, the response from an action on a controller named \MyAppNamespace\Controllers\EditProfile in a file named EditProfile.php would include a Site Page which uses the EditProfile.tpl Presentation Template and the EditProfile.css Presentation Stylesheet.
This is illustrated in the following table

Controller Presentation Template Presentation Stylesheet
Controllers/EditProfile.php Presentation/Templates/EditProfile.tpl Presentation/Stylesheets/EditProfile.css
You can change the Presentation Template and Stylesheet to be used on a page-by-page basis by editing the SiteStructure.syrp configuration file.

Controllers do not have to use createResponseFromRequest. They can return an instance of any IView implementer. This allows controllers to handle requests in complex and unique situations.

Client Side Controllers

In modern Web applications, much like traditional MVC applications, the lifetime of the application does not cease immediately after returning the view. The application often continues to update the view based on user input or dynamic data (models) retrieved via XHR or Web sockets. Applications also sometimes update the data models and persist their updated state via XHR. Therefore, in an ActiveWAFL MVC Web application there is the server-side controller as well as a controller for the client-side.

Flow of a typical client side controller action
Server ResponseSet up event handlers to respond to user interactionUser inputRetrieve/update client side modelsUpdate stale views/view contentUser input → ...
Example client-side controller to add a product to the cart
  1. Namespace("MyAppNamespace.Controllers");
  3. ActiveWaflWeb.Controllers.Product = DblEj.Mvc.ControllerBase.extend({
  4.    DefaultAction: function(args)
  5.    {
  6.       //get value of HTTP GET variable SelectedProductId
  7.       var selectedProductId = args["SelectedProductId"];
  9.       $("MyButton")
  10.          .AddClickHandler
  11.          (
  12.             function()
  13.             {
  14.                 AddToCart(selectedProductId);
  15.             }
  16.          );
  17.    }
  18. });