added controller, DI and classloader part to the app tutorial

This commit is contained in:
Bernhard Posselt
2012-11-28 01:37:18 +01:00
parent ce3eab7f2e
commit 07b7222fe5

View File

@@ -3,7 +3,7 @@ App Tutorial
This will teach you how to get develop your own owncloud app.
Before you start, please check if there already is a similar app you could contribute to. Also, feel free to communicate your idea and plans to the mailing list so other contributors might join in (https://mail.kde.org/mailman/listinfo/owncloud).
Before you start, please check if there already is a similar app you could contribute to. Also, feel free to communicate your idea and plans to the `mailing list <https://mail.kde.org/mailman/listinfo/owncloud>`_ so other contributors might join in.
Getting Started
@@ -49,7 +49,7 @@ To enable your app, simply link it into the apps directory:
or set the apps directory in your :file:`/var/www/owncloud/config.php` (see :doc:`configfile`)
Don't forget to enable it on the apps settings page!
**Don't forget to enable it on the apps settings page!**
Now change into your app directory::
@@ -71,7 +71,171 @@ The following things will need to be changed:
* **namespace OCA\\AppTemplate** to **namespace OCA\\YourAppName**
* The Classpaths in :file:`appinfo/bootstrap.php`
Metainformation
---------------
You will want to set certain metainformation for your application. To do that open the :file:`appinfo/app.php`
App information
---------------
You will want to set certain metainformation for your application. To do that open the :file:`appinfo/app.php` and adjust it to look like this
.. code-block:: php
<?php
require_once \OC_App::getAppPath('yourappname') . '/appinfo/bootstrap.php';
\OCP\App::addNavigationEntry( array(
// the string under which your app will be referenced
// in owncloud, for instance: \OC_App::getAppPath('APP_ID')
'id' => 'yourappname',
// sorting weight for the navigation. The higher the number, the higher
// will it be listed in the navigation
'order' => 74,
// the route that will be shown on startup
'href' => \OC_Helper::linkToRoute('apptemplate_index'),
// the icon that will be shown in the navigation
'icon' => \OCP\Util::imagePath('yourappname', 'example.png' ),
// the title of your application. This will be used in the
// navigation or on the settings page of your app
'name' => \OC_L10N::get('yourappname')->t('Your App')
));
?>
Classloader
-----------
The classloader is configured in :file:`appinfo/bootstrap.php`. The classloader frees you from requiring your classes when you use them. If a class is used and its not yet available, the loader will automatically require the given file.
To add a class to the classloader, simply use something like this:
.. code-block:: php
<?php
// loads the class MyClass from the file folder/myclass.php
\OC::$CLASSPATH['OCA\YourAppName\MyClass'] = 'apps/yourappname/folder/myclass.php';
?>
Dependency Injection
--------------------
Dependency Injection helps you to create testable code. A good overview how it works and what the benefits are can be seen on `Google's Clean Code Talks <http://www.youtube.com/watch?v=RlfLCWKxHJ0>`_
The container is configured in :file:`appinfo/bootstrap.php`. We use Pimple for the container. The documentation on how to use it can be seen on the `Pimple Homepage <http://pimple.sensiolabs.org/>`_
To add your own class simply add a new line inside the **createDIContainer** function:
.. code-block:: php
<?php
$container['MyClass'] = function($c){
return new MyClass($c['SomeOtherClass']);
};
?>
Controllers
-----------
The App Template provides a simple baseclass for adding controllers. Controllers connect your view (templates) with your database and is connected to one or more routes.
The apptemplate comes with several different Controllers. A simple controller would look like:
.. code-block:: php
<?php
namespace OCA\YourApp;
class MyController extends Controller {
/**
* @param Request $request: an instance of the request
* @param API $api: an api wrapper instance
*/
public function __construct($api, $request){
parent::__construct($api, $request);
}
/**
* @brief sets a global system value
* @param array $urlParams: an array with the values, which were matched in
* the routes file
*/
public function myControllerMethod($urlParams=array()){
$value = $this->params('somesetting');
$response = new JSONResponse($this->appName);
$response->setParams(array('value' => $value));
return $response;
}
}
?>
An instance of the api is passed via dependency injection, the same goes for a request instance. POST and GET parameters are abstracted by the Request class and can be accessed via **$this->params('myPostOrGetKey')** in the controller. This has been done to make the app better testable.
If a POST and GET value exist with the same key, the POST value is preferred. You should avoid to have both values with the same key though.
Every controller method has to return a response. All possible reponses can be found in :file:`lib/response.php`. The file contains wrappers for Ownclouds internal template engine and JSON response and is used to create a uniform response object which is testable.
Don't forget to add your controller to the dependency container in :file:`appinfo/bootstrap.php`
.. code-block:: php
<?php
// in the createDIContainer function
$container['MyController'] = function($c){
return new MyController($c['API'], $c['Request']);
};
?>
and to the classloader
.. code-block:: php
<?php
\OC::$CLASSPATH['OCA\YourAppName\MyController'] = 'apps/yourappname/controllers/my.controller.php';
?>
Database Access
---------------
TBD
Routes
------
See also :doc:`routing`
API abstraction layer
---------------------
Owncloud currently has a ton of static methods which is a very bad thing concerning testability. Therefore the app template comes with an api abstraction layer which is located at :file:`lib/api.php`.
If you find yourself in need to use an Owncloud internal static method, add it to the api layer by simply creating a new method like:
.. code-block:: php
<?php
// inside the API class
public function methodName($someParam){
\OCP\Util::methodName($this->appName, $someParam);
}
?>
That way you can easily create unittests with a simple API class mock if you dont want to call Owncloud internal stuff.