Routes & Controllers

Routes

A typical web application consists of both server side and client side code. The glue between those two parts are the URLs. In the case of the own notes application, the following URLs will be used:

  • GET /: Returns the interface in HTML format

  • GET /notes: Returns a list of all notes in JSON format

  • GET /notes/1: Returns a note with the id 1 in JSON format

  • DELETE /notes/1: Deletes a note with the id 1

  • POST /notes: Creates a new note by passing in JSON format

  • PUT /notes/1: Updates a note with the id 1 by passing in JSON format

On the client side we can call these URLs with the following jQuery code:

// example for calling the PUT /notes/1 URL
var baseUrl = OC.generateUrl('/apps/ownnotes');
var note = {
    title: 'New note',
    content: 'This is the note text'
};
var id = 1;
$.ajax({
    url: baseUrl + '/notes/' + id,
    type: 'PUT',
    contentType: 'application/json',
    data: JSON.stringify(note)
}).done(function (response) {
    // handle success
}).fail(function (response, code) {
    // handle failure
});

On the server side, we need to register a callback that is executed once the request comes in. The callback will be a method on a controller and the controller will be connected to the URL with a route .

To do that, we create the routes configuration file: ownnotes/appinfo/routes.php, which you can see the definition for below.

<?php
return [
    'routes' => [
        ['name' => 'page#index', 'url' => '/', 'verb' => 'GET'],
        ['name' => 'note#index', 'url' => '/notes', 'verb' => 'GET'],
        ['name' => 'note#show', 'url' => '/notes/<id>', 'verb' => 'GET'],
        ['name' => 'note#create', 'url' => '/notes', 'verb' => 'POST'],
        ['name' => 'note#update', 'url' => '/notes/<id>', 'verb' => 'PUT'],
        ['name' => 'note#destroy', 'url' => '/notes/<id>', 'verb' => 'DELETE']
    ]
];

A handy feature of routing in ownCloud is that as the final five routes are so similar, they can be abbreviated by adding a resource instead:

<?php
return [
    'resources' => [
        'note' => ['url' => '/notes']
    ],
    'routes' => [
        ['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
    ]
];

Let’s look at the route below first, so that you get a better understanding of how they’re composed.

<?php
return ['routes' => [
    ['name' => 'page#index', 'url' => '/', 'verb' => 'GET']
]];

This route (/) is accessible only via a GET request and is called page#index. When called, the request will be handled by OCA\\OwnNotes\\PageController’s index method. The reason why is defined in the route’s name. The name is composed of the name of a controller and a method on that controller, separated by a hash symbol.

Controllers

The controller, more specifically the controller function, as in other MVC-based frameworks, is the central place of logic for a route (or action). These functions, as you would expect, can return a range of responses to the user, including: JSON, HTML, XML, and plain text; a redirect or 404 Not Found response, or the download of a file.

In the example below, we’ll return an HTML response, based on the contents of a template file, using the TemplateResponse object. The TemplateResponse object renders a template located in an application’s templates directory.

<?php
 namespace OCA\OwnNotes\Controller;

 use OCP\IRequest;
 use OCP\AppFramework\Http\TemplateResponse;
 use OCP\AppFramework\Controller;

 class PageController extends Controller {

     public function __construct($AppName, IRequest $request){
         parent::__construct($AppName, $request);
     }

     /**
      * @NoAdminRequired
      * @NoCSRFRequired
      */
     public function index() {
         // Renders ownnotes/templates/main.php
         return new TemplateResponse('ownnotes', 'main');
     }

 }

The first argument to the constructor specifies which application’s template directory to search. The second argument specifies the template to use, minus file extension (.php). Templates are, effectively, not much more than the original PHP files, which were a combination of PHP and HTML.

The OCP namespace maps to ownCloud/core/lib/public.

The @NoAdminRequired and @NoCSRFRequired annotations in index’s docblock above turn off security checks, as they’re not necessary for this method. See Controllers for more information.

With an initial overview of controllers (and templates) completed, we’ll now create the core of a controller which handles AJAX requests for the application. Create a new controller, called ownnotes/lib/Controller/NoteController.php, with the following content:

<?php
 namespace OCA\OwnNotes\Controller;

 use OCP\IRequest;
 use OCP\AppFramework\Controller;

 class NoteController extends Controller {

     public function __construct($AppName, IRequest $request){
         parent::__construct($AppName, $request);
     }

     /**
      * @NoAdminRequired
      */
     public function index() {
         // empty for now
     }

     /**
      * @NoAdminRequired
      *
      * @param int $id
      */
     public function show($id) {
         // empty for now
     }

     /**
      * @NoAdminRequired
      *
      * @param string $title
      * @param string $content
      */
     public function create($title, $content) {
         // empty for now
     }

     /**
      * @NoAdminRequired
      *
      * @param int $id
      * @param string $title
      * @param string $content
      */
     public function update($id, $title, $content) {
         // empty for now
     }

     /**
      * @NoAdminRequired
      *
      * @param int $id
      */
     public function destroy($id) {
         // empty for now
     }

 }

You can see that it’s largely the same as the PageController, but with a range of CRUD methods. Take special note of show, create, update, and destroy. The parameters to these functions are extracted from the request body and the URL, using the controller method’s variable names.

We’re not going to do anything further in this chapter. However, we’ll flesh out the controller in the next chapter on database interaction.