add route generation

This commit is contained in:
Bernhard Posselt
2014-05-07 20:37:31 +02:00
parent 2daa876cf2
commit 70c09dd4ab
3 changed files with 249 additions and 3 deletions

View File

@@ -1,4 +1,172 @@
===========
Controllers
===========
.. sectionauthor:: Bernhard Posselt <dev@bernhard-posselt.com>
.. sectionauthor:: Bernhard Posselt <dev@bernhard-posselt.com>
Controllers are used to connect :doc:`routes <routes>` with app logic. Think of it as callbacks that are executed once a request has come in. Controllers are defined inside the **controllers/** directory.
Connecting a controller with a route
====================================
Getting request parameters
==========================
Parameters can be passed in many ways:
* Extracted from the URL using curly braces like **{key}** inside the URL (see :doc:`routes`)
* Appended to the URL as a GET request (e.g. ?something=true)
* application/x-www-form-urlencoded from a form or jQuery
* application/json from a POST, PATCH or PUT request
All those parameters can easily be accessed by adding them to the controller method:
.. code-block:: php
<?php
namespace OCA\MyApp\Controller;
use \OCP\AppFramework\Controller;
class PageController extends Controller {
// this method will be executed with the id and name parameter taken
// from the request
public function doSomething($id, $name) {
}
}
Casting parameters
------------------
URL, GET and application/x-www-form-urlencoded have the problem that every parameter is a string, meaning that *?doMore=false* would be passed in as the string *'false'* which is not what one would expect. To cast these to the correct types, simply add PHPDoc to hint the types:
.. code-block:: php
<?php
namespace OCA\MyApp\Controller;
use \OCP\AppFramework\Controller;
class PageController extends Controller {
/**
* @param int $id
* @param bool $doMore
* @param float $value
*/
public function doSomething($id, $doMore, $value) {
// GET /index.php/apps/myapp?id=3&doMore=false&value=3.5
// => $id = 3
// $doMore = false
// $value = 3.5
}
}
The following types will be casted:
* **bool** or **bolean**
* **float**
* **int** or **integer**
JSON parameters
---------------
It is possible to pass JSON using a POST, PUT or PATCH request. To do that the **Content-Type** header has to be set to **application/json**. The JSON is being parsed as an array and the first level keys will be used to pass in the arguments, e.g.::
POST /index.php/apps/myapp/authors
{
"name": "test",
"number": 3,
"publisher": true,
"customFields": {
"mail": "test@example.com",
"address": "Somewhere"
}
}
.. code-block:: php
<?php
namespace OCA\MyApp\Controller;
use \OCP\AppFramework\Controller;
class PageController extends Controller {
public function create($name, $number, $publisher, $customFields) {
// $name = 'test'
// $number = 3
// $publisher = true
// $customFields = array("mail" => "test@example.com", "address" => "Somewhere")
}
}
Headers, files, cookies and session information
-----------------------------------------------
Responses
=========
JSON
----
Templates
---------
Redirects
---------
Downloads
---------
Creating custom responses
-------------------------
Responders
----------
Serializers
-----------
Authentication
==============
By default every controller method enforces the maximum security, which is:
* Ensure that the user is admin
* Ensure that the user is logged in
* Check the CSRF token
Most of the time though it makes sense to also allow normal users to access the page and the PageController->index() method should not check the CSRF token because it has not yet been sent to the client and because of that can't work.
To turn off checks the following *Annotations* can be added before the controller:
* **@NoAdminRequired**: Also users that are not admins can access the page
* **@NoCSRFRequired**: Don't check the CSRF token (use this wisely since you might create a security hole, to understand what it does see :doc:`../general/security`)
* **@PublicPage**: Everyone can access that page without having to log in
A controller method that turns of all checks would look like this:
.. code-block:: php
<?php
namespace OCA\MyApp\Controller;
use \OCP\IRequest;
use \OCP\AppFramework\Controller;
class PageController extends Controller {
/**
* @NoAdminRequired
* @NoCSRFRequired
* @PublicPage
*/
public function freeForAll() {
}
}

View File

@@ -31,7 +31,7 @@ Afterwards the following steps are performed:
Router
------
The router parses the :doc:`apps routing files <routes>` (:file:`appinfo/routes.php`), inspects the request's **method** and **url**, queries the controller from the :doc:`container` and then passes control to the dispatcher. The dispatcher is responsible for running the hooks (called Middleware) before and after the controller, executing the controller method and rendering the output.
The router parses the :doc:`app's routing files <routes>` (:file:`appinfo/routes.php`), inspects the request's **method** and **url**, queries the controller from the :doc:`container` and then passes control to the dispatcher. The dispatcher is responsible for running the hooks (called Middleware) before and after the controller, executing the controller method and rendering the output.
Middleware
----------

View File

@@ -148,4 +148,82 @@ can be abbreviated by using the **resources** key:
'routes' => array(
// your other routes here
)
));
));
Using the URLGenerator
========================
Sometimes its useful to turn a route into a URL to make the code independent from the url design or generate an URL for an image in **img/**. For that specific usecase the ServerContainer provides a service that can be used in your container:
.. code-block:: php
<?php
namespace OCA\MyApp\AppInfo;
use \OCP\AppFramework\App;
use \OCA\MyApp\Controller\PageController;
class Application extends App {
public function __construct(array $urlParams=array()){
parent::__construct('myapp', $urlParams);
$container = $this->getContainer();
/**
* Controllers
*/
$container->registerService('PageController', function($c) {
return new PageController(
$c->query('AppName'),
$c->query('Request'),
// inject the URLGenerator into the page controller
$c->query('ServerContainer')->getURLGenerator()
);
});
}
}
Inside the PageController the URL generator can now be used to generate an URL for a redirect:
.. code-block:: php
<?php
namespace OCA\MyApp\Controller;
use \OCP\IRequest;
use \OCP\IURLGenerator;
use \OCP\AppFramework\Controller;
use \OCP\AppFramework\Http\RedirectResponse;
class PageController extends Controller {
private $urlGenerator;
public function __construct($appName, IRequest $request,
IURLGenerator $urlGenerator) {
parent::__construct($appName, $request);
$this->urlGenerator = $urlGenerator;
}
/**
* redirect to /apps/news/myapp/authors/3
*/
public function redirect() {
// route name: author_api#do_something route
// route url: /apps/news/myapp/authors/{id}
// # need to be replaced with a . due to limitations and prefix
// with your app id
$route = 'myapp.author_api.do_something';
$parameters = array('id' => 3);
$url = $this->urlGenerator->linkToRoute($route, $parameters);
return new RedirectResponse($url);
}
}