From Tine 2.0 - Wiki
Application pattern of Tine 2.0
The Tine 2.0 PHP application pattern is easy to understand. You might already have used the MVC design pattern which is similar but not identical to the pattern used for Tine 2.0 applications.
We made only little extension to the standard MVC pattern to suit the special situation Tine 2.0 has, which are explained as follows.
Changes in the 2008/12 release
- more than one controller (you can use one for each model) / new Controller directory
- new Frontend directory
- new Server directory
- new Tinebase bootstrap
- new abstract Frontend/Controller/Backend classes that should be extended by the application classes
- new Exception directory (see: Exceptions)
Single Page Application
Tine 2.0 is a so called Single Page Application (SPA). This means anything is served from a single URL, the index.php. If a login screen is shown or if an application does a complex transactional operation, it's always handled by the index.php.
This layout simplifies the application flow dramatically, as there is no need to figure out the required controllers/actions by the url and there is no need to define rewrite rules. As a consequence we don't use a traditional front controller and only have a light-weight dispatcher in the index.php.
Service Oriented Architecture
Tine 2.0 has a service orientated architecture. The normal views in MVC apps are perfectly convenient for HTML output. However the Tine 2.0 server returns almost no HTML, but is capable to serve the needed data in various representations. Moreover it also receives its actions and data also via various representations.
As a consequence Tine 2.0 applications normally don't have views, but they have fontend classes, e.g. a JSON class. This frontend classes handle all the input and output conversions from and to the the requested format, e.g. JSON.
Multi Back-end Capable
The Tine 2.0 application pattern is designed to support multiple back-ends. This means that the applications records store could consist of totally different types. A simple example is the Addressbook. It's contacts can be fetched from a SQL back-end or from a LDAP back-end.
In the standard MVC pattern the models do the persistence operations on a single persistence instance, which normally means they do all the SQL database handling. This does not fit the Tine 2.0 multi back-end requirement.
As a consequence the Tine 2.0 models are just simple data containers and have nothing to do with persistence. The controllers store and get those simple models via the back-end classes which hide the complexity of the different physical back-ends by implementing a simple public interface.
Example Music Database
Let's draw the UML for a simple music database. The audio database is a iTunes XML file on the one hand and a SQL DB from MythTV on the other hand. For the moment we only access the database by our web frontend, so we only need a JSON frontend. The heart of the application is the controller. That's where all the domain logic and ACL checks are done. Note the model which is passed through all instances.
We follow a save request with a new album from the client. The Zend_Json_Server hands an array to the Music_Json. It creates a Music_Model_Album record and does all the necessary conversions in the data structure. Moreover the Json frontend decides if the create or update action of the controller is to be used.
The controller checks ACL, does the history logging, tagging and relations and all other domain logic. It decides which back-end is in charge and hands over the record to the back-end.
The back-end handles all the complexity of the physical storage and returns a fresh record of the saved album.
File (Class) Names
Music/ Music/Controller.php Music/Exception.php Music/Frontend/Json.php Music/Frontend/Http.php Music/Controller/Album.php Music/Model/ Music/Model/Album.php Music/Backend/ Music/Backend/Album/iTunes.php Music/Backend/Album/mythTV.php Music/Exception/AccessDenied.php Music/Exception/InvalidArgument.php [...]
Each Model corresponds to one ore more back-ends. The function names in the frontend and controller follow a strict name convention.
save<Modelname> (creates or updates a single record) get<Modelname> (gets a single (fully featured) record) search<Modelname>s (searchs a set of (simple) records) delete<Modelname>s (deletes a set of records identified by their ids) update<Modelname>s (same updates one or more fileds in multiple records identified by their ids)
For each Model of the application there should be one corresponding controller.
They should be named like that: <Applicationname>_Controller_<Modelname>
The function names should be like that:
getInstance create update get search searchCount delete
This naming convention (note the singelton pattern) is important for the functionality of the inter-application communication.