04. Views

URL Mapping and Templating - the View

Zedek url maps to controller, method and arguments as shown below: http://mywebsite.com/controller/method/id/?arg1=val1&arg2=val2...&argn=valn

The engines/ folder contains all the controller mapping directories such that for the example above the controller name is used to create a folder in the engines folder:

/zedek/engines/controller

This contains a controller.php file which has a class in it named CController which in turn extends the abstract class ZController within the /core/controller.php file. the methods of this class are mapped to the url.

within the controller folder is a 'views' folder which houses browser accessible files:

/zedek/engines/controller/view/

The files within the view folder are rendered to the browser.

Creating a view

Lets illustrate this with a url:

http://localhost/foo/bar

Create a folder within the /zedek/core/engines/

/zedek/engines/foo/

within the folder create a file:

/zedek/engines/foo/controller.php

and a folder:

/zedek/engines/foo/views/

within the controller.php enter the following code:

<?php
  namespace __zf__;
  CController extends ZController {
    function method bar(){
    }
  }

this will create a blank page.

*this may be done automatically by calling CController::create("appName"). To do so ensure the /zedek/engines folder is writable.

Create a template and render

within the function bar() enter the folowing code:

self::render();

the CController::render([], string, false) method returns a ZView object. this can take 3 arguments with the first 2 placed in any order, may be entered singly or left as default. Argument 3 is the name of the theme to be used in rendering the view. If left empty it defaults to the default theme set in the global config file.

In the default state ie ZView with no arguments attempts to find a view file within the views folder that matches the method (bar.html). If it doesn't find this it attempts to find an index.html, where this fails it returns a page not found message.

the code should look like this now:

<?php
  namespace __zf__;
  CController extends ZController {
    function method bar(){
      self::render();
    }
  }

To render a specific view within the refernce controller create the view file and render

self::render("view");

You may also call a view from another controller:

self::render("view@otherController");

where otherController specifies the name of the alternate controller from which to call the view

Next we create a bar.html file in the view folder:

/zedek/engines/foo/view/bar.html

next we pass an array into the ZView object:

<?php
  namespace __zf__;
  CController extends ZController {
    function bar(){
      $array = array(
        'application'=>"My New app", 
      ); 
     self::render($array);
    }
  }

with this we can enter some template variables into the bar.html file

<h1>{{application}}</h1>

and when we view the url once more in the browser we should see: My New app in h1 formatting

Special methods

To return a view to the browser one of severl methods may be called. These are explained below.

render

CController::render($view='method', $template=array());

when this method is called on a controller as:

self::render();

it returned a themed view corresponding to the theme set in the config.json file. The view returned where no argument is passed maps to a html theme file in the views folder that that has the same name as the method. Where this is not found a "page not found" message is returned or a 404 error.

Two arguments may be passed being a string and an array. Where a string is passed say 'foo' the render view attempts to find a html file within the views folder that matched that string. Where it doesnt it returns a page not found message. The array on the other hand holds templating information. This is explained furher down.

display

This acts like the render function but returns the view with no themeing information.

dynamic

This acts like the render function but maps to php files in the views folder allowing for the creation of dynamic view files.

Rendering alternate themes

Alternate themes may be rendered other than the default theme by passing a third argument (string) to the render function.

Control Structure

Rendering simple if else staements

The syntax here is similar to the popular ternary. It is done in the view and seeks to check for the value of a string in the template array and a response based on that. heres an example:

{%if [foo] == bar ? something : something else %}

if the view finds a valid value for $template["foo"] which is set to "bar" then it will print out something else it will print our something else.

Rendering simple single dimensional loops

The syntax here borrows from the javascript object loop:

{%for item in items : do something with {{item}} %}

Rendering data aloops

The loop rendering engine was designed with database read arrays in mind, these are usually multi dimensional arrays with keys in the lowest level. Lets illustrate this.

If we have a database table with student entries for a school with columns - id, name, parent, class, teacher we may pull all required entries out with a query such as:

SELECT * FROM students;

the result may then be captured in array which will be called $students (or what ever variable name). Next we pass that array into our templating array:

<?php
  namespace __zf__;
  CController extends ZController {

    function bar(){

      $students = .... //however we pull the array from the database
      $array = array(
        'application'=>"My New app", 
        'students'=>$students, //the key can have whatever name we choose
      );

      self::render($array);
    }

  }

In the view file we would then enter code which loops with syntax

    {%foreach items as item: <markup></markup> %}.

*Note that item may be arbitrarily set but the list has to correspond to the key assigned to the array we are looping through.

In the markup also we may reference row cell values by using corresponding column names such as item.column_name.

The example below will make these clearer. Within the bar.html enter the following code:

<ul>
{%foreach students as student: 
  <li>{{student.name}} belongs to class {{student.class}}. His teacher is {{student.teacher}}</li>
endfor%}
</ul>

This will loop through and return all corresponding database entries.

Purpose

The purpose of the looping template is to reduce markup within the controller whose main purpose is url mapping.

Custom views

The template rendering does not always have to map to the method name. For example where you have conditions for rendering views. In this case you may pass the name of the custom view and have it returned instead of the methodName.html.

Using the same example above the code would be:

<?php
  namespace __zf__;
  CController extends ZController {
    function bar(){
      self::render('custom');
    }
  }

for this to work right you have to create the corresponding custom view to be rendered which in this case will be:

/zedek/engines/foo/view/custom.html

When this is done the custom.html will take precedence over the bar.html file when accessing the url from the browser.

Displaying unformatted HTML

The render function ensures that the theme information is returned to the screen, and this is mainly the header and footer files in the theme. One may decide to return markup without these as in the case where there is a need to create a unique home or landing page. In this case you may use the method display() as shown below:

<?php
  namespace __zf__;
  CController extends ZController {
    function bar(){
      self::display();
    }
  }

The display function otherwise works the same way as the render() function except for the theme information being sent along.

Displaying markup with embedded PHP

I am not sure why you would want to do this, but I can bet the one or two special reasons for this will pop up at some point. To achieve this create a php file in the view folder and to render this use the code below:

<?php
  namespace __zf__;
  CController extends ZController {
    function bar(){
      self::dynamic('custom_name_without_extension');
    }
  }

and it will return any printed values from the PHP file. This also allows you access templating using the a variable $self which is of the standard class.

The Controller:

<?php
  namespace __zf__;
  CController extends ZController {
    function bar(){
      self::dynamic(['foo'=>"bar"]);
    }
  }

The view:

print $self->foo