(Document-)Controller

As noted in Hello World! and Templates document controllers are used to generate dynamic
content. The term controller refers to the MVC pattern within the Adventure PHP Framework as in
several other products. However, the APF goes beyond that introducing the HMVC pattern to create UIs along
with the Page controller.

The HMVC pattern has several advantages over the MVC pattern. It enables you to define highly
granular elements of your web page or application that can be easily reused within the current or other projects.
From a software design perspective, the dependencies between different components - using the MVC pattern
normally leads to heavy logic within controllers taking care of the whole application - can be reduced significantly.

In order to let a controller generate dynamic content it must be referred within a Templates. This can
be done by adding

APF template

<@controller
class="..."
@>

at the top of the template. The class attribute contains the fully-qualified class name of the controller
implementation (e.g. VENDOR\pres\controller\NavigationController). During transformation the page controller
executes the transformContent() method.

In order to keep the controller code clean and easy to read it is recommended to limit output generation or view
logic to a minimum. In case a more complex logic is necessary to generate dynamic content it may be a good idea
to create a separate tag that encapsulates the logic.

As a rule of thumb, controllers are recommended as long as view logic and the complexity of dynamic data that is
displayed is limited. As soon as the controller is required to gear into creation or manipulation of the DOM tree
or the data structure to display is more complex data custom tags should be implemented.

Moreover, only one concern should be handled by one controller especially because the APF uses the
HMVC-Pattern. In case more that one functionality is contained, you should consider to separate the
component into two separate components.

transformContent() is used by the Page controller during transformation of the page in order to
execute the functionality of the current DOM element. The content of the class except this basic structure is
subjected to the developer.

As you may take from the API documentation the BaseDocumentController class includes several methods
that help you implementing dynamic functionality. These are:

getDocument():
Returns a reference on the current DOM node. This enables you to access the entire tree using the methods
getChildren() and getParentObject().

getTemplate($name):
Returns a reference on a template object (instance of TemplateTag) defined within the current document.

getForm($name):
Returns a reference on a form object (instance of HtmlFormTag) defined within the current document.

getLabel($name):
Returns a reference on a label object (instance of LanguageLabelTag) defined within the current document.

getIterator():
Returns a reference on an iterator object (instance of HtmlIteratorTag) defined within the current document.

getNodeById($id):
Returns a reference on any DOM node that defines attribute dom-id with the applied $id value.
To obtain a DOM node (e.g. template) within the entire DOM tree using a unique ID the tag definition must be as
follows:

APF template

<html:template name="..." dom-id="xyz">
...
</html:template>

The template can then be obtained within a controller as follows:

PHP code

$template = &$this->getNodeById('xyz');

placeHolderExists($name):
Checks, whether a place holder exists within the current document.

templatePlaceHolderExists(TemplateTag &$template, $name):
Checks, whether a place holder exists within the applied template instance of the current document.

setPlaceHolder($key, $value):
Fills a place holder with the applied value.

setPlaceHolders(array $placeHolderValues):
Fills a list of place holders with the applied values.

Moreover, the BaseDocumentController inherits all attributes and functions of the class APFObject.

Besides, each document controller instance contains a reference on the current DOM node the
controller is responsible for transformation. The reference can be retrieved using the
$this->getDocument() method. Using this reference, you can access the document's
foo attribute via

One common use case of a document controller is filling the META information within an HTML header. As an example,
the title and the current date should be filled for a dynamic web page. For this reason, let us first define the
HTML structure and the necessary place holders:

The document controller referred to within the templates implements the transformContent() method and a
getTitle() method to evaluate the value for the current page. The source code of the class is as follows:

Using the <html:template /> tags you can easily create lists within a controller by iterating over the
list of items.

<html:template /> tags are only suitable to display content with only one hierarchy level (e.g. lists
of products with prices). In case a <html:template /> tag is no longer sufficient and the display
creation requires nesting of different templates it is recommended to create a custom tag that handles the display of
an entire list element or the whole list in one. Further notes can be found with in tutorial
Implementation of tags.

Please note the following template that was defined to display products along with their price as a table:

Within transformContent() the list of products is retrieved by the internal function getProducts().
The loop is used to fill the product information into the template and to collect the output of the template
transformation within a buffer. Later one, the result is passed to the products place holder to create the
final output.

For more complex use cases document controllers can also be created with the
DIServiceManager. This offers a lot of advantages
compared to the classic approach:

Dependent objects (e.g. business services, domain objects) can be configured easily and applied to the controller.
This avoids redundant code and improves testability of the controller since the implementation no longer defines
explicit code-based dependencies.

Using static and dynamic configuration facilities of an APFDIService controllers can be configured
easily for different use cases. A controller's behaviour can therefor be influenced by a simple configuration
parameter and can thus be re-used within different applications.

In order to create controllers via the DIServiceManager an adaption of the controller declaration is
necessary. Here, the implementation is no longer referred to by the class attribute but using a service
declaration:

The namespace attribute names the namespace of the service definition, service declares the
service definition that contains the document controller. Details on addressing services can be taken from chapter
Services.

In order to use the service declaration please create a service configuration accordingly. Details on the scheme of
service configurations can be read about in section
Configuration.

The following code box contains a sample configuration that applies a static parameter to the controller
(E-Mail):

In order to provide a state-of-the-art web experience and to continuously improve our services we are using
cookies. By using this web page you agree to the use of cookies. For more information, please refer to
our Privacy policy.