URL mapping/dispatch

When Artaengine is uses as a framework for an application. The web-server is set to send all requests to one PHP file, except for requests to resource files such as images, CSSes and JavaScripts. The PHP file which gets all the requests starts Artaengine. At this point Artaengine prepares the demanded resources based on the application configuration then reads the URL mapping dictionary and dispatches the request to a factory(handler). This tutorial explains the process.

Factories - basic

What is a factory?

Not to be confused with factory patterns. In an Artaengine application a factory is a PHP class method or a function which responses to a request. In other words a handler for a URL or a group of URLs.

A factory class can inherit from the Response class. A factory method/function is where we write the PHP codes in response to one or a set of requests. When a factory inherits from Response class, methods for preparing and sending back a response are within the factory context, for example sending a text, template, JSON, ...

Creating a factory

  • Create a PHP file inside the factories directory . Factory classes can only be created inside the directory(or a sub-directory) set as factories directory in the application configuration.
  • Create a class inside the PHP file. The name of the class should be exactly the same as the PHP file (case sensitive).
  • The factory class can inherit from Response, Response comes with Artaengine library.
    class ClassName extends Response {
    
    }
    
  • Add the methods that are going to be handling the requests. A factory method must be public and the first argument is always a Request object(implementing IRequest) . Other arguments depend on the URL and will be explained later. ‎
    class Home extends Response {
    
        public function index($request) {
    
        }
    
        public function factory2($request, $userId) {
    
        }
    }
    
  • That's it! now write the codes to handle the request...

No need to say that this is a normal class, your class, you may implement it as you wish. The only thing is that the public methods which you map to a URL are called by Artaengine when the URL is requested.

Mapping

URLs are mapped to factories in a dictionary that is either an XML file or a PHP array inside a PHP file. In this tutorials we will call it factories.xml or factories.php.

This is how an empty dictionary must look like.

<?xml version="1.0" encoding="UTF-8"?>
<configure>

  <!-- mappings are placed here -->

</configure>
<?php
$configure = array(
  /* mappings are placed here */
);
?>

Selecting XML or PHP is a matter of taste and there is no performance differences, because Artaengine builder creates a more efficient cached version of the map.

The mapping configs are explained below, they must be placed where shown in the above sample.

See as: PHP or XML or XML and PHP

Mapping static URL paths

Maps BASE_URL to method index of class Home in Home.php located inside the factories directory

  <route
      path="/"
      factory="Home.index"
      />
    array(
        'path' => '/',
        'factory' => 'Home.index'
    ),

Maps BASE_URL/about to method about of class Home in Home.php.

  <route
      path="/about"
      factory="Home.about"
      />
    array(
        'path' => '/about',
        'factory' => 'Home.about'
    ),

Maps BASE_URL/about/ to method aboutWithTrailingSlash of class Home. A URL with and without trailing slash are considered different. To reverse this behavior set slash = on under section [arta].

  <route
      path="/about/"
      factory="Home.aboutWithTrailingSlash"
      />
    array(
        'path' => '/about/',
        'factory' => 'Home.aboutWithTrailingSlash'
    ),

Maps BASE_URL/legamorphs/rabbits/lion-head to method lionHead of class Rabbits.

  <route
      path="/legamorphs/rabbits/lion-head"
      factory="Rabbits.lionHead"
      />
    array(
        'path' => '/legamorphs/rabbits/lion-head',
        'factory' => 'Rabbits.lionHead'
    ),

When file-name and class-name are different

It is possible to have a class-name that is in a PHP file with a different name. By adding the file-name with a dot before class-name:
Maps BASE_URL/something to method methodName of class ClassName in FileName.php inside factories directory .

  <route
      path="/something"
      factory="FileName.ClassName.methodName"
      />
    array(
        'path' => '/something',
        'factory' => 'FileName.ClassName.methodName'
    ),

Having sub-directories inside factories directory

If the PHP file is inside a sub-directories of factories directory then:

Maps BASE_URL/something to methodName of ClassName in www/app-dir/factories-dir/path1/path2/FileName.php

  <route
      path="/something"
      factory="path1.path2.FileName.ClassName.methodName"
      />
    array(
        'path' => '/something',
        'factory' => 'path1.path2.FileName.ClassName.methodName'
    ),

"OR" Operator ...

Use ? as operator OR inside a route:

In this example BASE_URL/home, BASE_URL/index, BASE_URL/index.html and BASE_URL/index.php are mapped to Home.php

  <route
      path="/home?index?index.html?index.php"
      factory="Home.index"
      />
    array(
        'path' => '/home?index?index.html?index.php',
        'factory' => 'Home.index'
    ),

Parameters in URL

When defining a route if a path starts with : it means that the path is not fixed and can be any thing.

In a URL/factory map a URL can have any number of unknown paths, this paths are send to the factory as arguments. In the route definition, each unknown path is defined after a : with a label. The label is just to make it readable and is ignored by Artaengine.

Maps BASE_URL/users/unknown-string to method byId of class Users.

  <route
      path="/users/:id"
      factory="Users.byId"
      />
    array(
        'path' => '/users/:id',
        'factory' => 'Users.byId'
    ),

unknown-string can be anything and User.byId gets the request:

class User extends Response {

    public function byId($request, $userId) {
        /* $userId is the unknown part of the URL */
    }
}

Maps BASE_URL/news/{yy}/{mm}/{dd}/morning to News.morning. Paths inside { } are variable strings.

  <route
      path="/news/:yy/:mm/:dd/morning"
      factory="News.morning"
      />
    array(
        'path' => '/news/:yy/:mm/:dd/morning',
        'factory' => 'News.morning'
    ),

Factory:

class News extends Response {

    public function morning($request, $year, $month, $day) {
        /* check if date is valid then show news */
    }
}

Parts of a route path can be fixed and parts can be unknown if a * is placed inside the path string for example /test1/fix1*fix2 is a match for BASE_UR/test1/fix1-fix2 and BASE_UR/test1/fix100000fix2/

Maps BASE_URL/documents/{doc-nom}/page{page-no} to Documents.page:

  <route
      path="/documents/:doc/page*"
      factory="Documents.page"
      />
    array(
        'path' => '/documents/:doc/page*',
        'factory' => 'Documents.page'
    ),

Factory:

class Documents extends Response {

    public function page($request, $docNom, $pageNom) {

    }
}

Factory class/method as parameters inside the URL

It is possible to dynamically define the factory class-name, method-name or both within a URL.

If the route has unknown path(s) each unknown path can be used as a factory class-name or a method-name by using the unknown path index. Following the examples:

Maps BASE_URL/ajax/{variable1}/{variable2}/{variable3} to method action of any class which is specified inside URL first variable path. So the factory responsible to handle BASE_URL/ajax/Users/update/7 will be Users.action.

  <route
      path="/ajax/:class/:act/:id"
      factory="1.action"
      />
    array(
        'path' => '/ajax/:class/:act/:id',
        'factory' => '1.action'
    ),

Note: The variable paths used as factory class or/and method names are not included in the factory arguments:

class Users extends Response {

    public function action($request, $action, $id) {

    }
}

Maps BASE_URL/ajax/{variable1}/{variable2}/{variable3}/{variable4}/{variable5} to a factory where the class-name is {variable2} and method is {variable4}.

  <route
      path="/ajax/:dummy/:class/:model/:method/:id"
      factory="2.4"
      />
    array(
        'path' => '/ajax/:dummy/:class/:model/:method/:id',
        'factory' => '2.4'
    ),

Factory for BASE_URL/ajax/dummy/Users/User/update/1:

class Users extends Response {

    public function update($request, $dummy, $model, $id) {

    }
}

Factory class/method inside the query-string

To specify the factory class-name and/or method-name inside a query-string, put qs: before the class/method name when assigning a value to the factory key/tag of a route. The class/method name specified after qs: is the key of $_GET. For example factory=qs:c.qs:m means $_GET['c'] holds class-name and $_GET['m'] holds method-name.

Maps BASE_URL/ajax/{variable1}/{variable2}?class={variable3}&method={variable4} to a factory where class-name is {variable3} and method is {variable4}.

  <route
      path="/ajax/:action/:id"
      factory="qs:class.qs:method"
      />
    array(
        'path' => '/ajax/:action/:id',
        'factory' => 'qs:class.qs:method'
    ),

Factory for BASE_URL/ajax/update/7?class=Users&method=action:

class Users extends Response {

    public function action($request, $action, $id) {

    }
}

Trailing slash

http://my-app/path
http://my-app/path/

Depending on the configuration, URL-mapping can see this two URLs different, treating them differently or see them as they are the same.

The behavior is set in the application configuration (ini file or PHP array) by key slash = on or slash = off under section [arta]. Default is off.

  • Trailing slash matters.
  • Trailing slash is ignored.

Routes and AJAXable

A route can be restricted to only AJAX calls:

  <route
      path="/ajax/:class/:method"
      factory="1.2"
      ajax="True"
      />
    array(
        'path' => '/ajax/:class/:method',
        'factory' => '1.2',
        'ajax' => True
    ),

Means when a request matches the route it will only be handled by the factory if:

$_SERVER['HTTP_X_REQUESTED_WITH'] === 'xmlhttprequest'

This works well when throwing a request with a JavaScript framework like jQuery.

If request is not AJAX it will be handled by notajax event handler which will be explained later in this tutorial.

Routes and robots.txt

By adding robots=false to a route make search engines ignore URLs covered by the route.

  <route
      path="/ajax/:class/:method"
      factory="1.2"
      ajax="True"
      robots="False"
      />
    array(
        'path' => '/ajax/:class/:method',
        'factory' => '1.2',
        'ajax' => True,
        'robots' => False
    ),

On build-out robots.txt will be created inside the application directory. Artaengine build-out would require write permission to application directory to be able to create this file. Make robots.txt visible, for example put the following line inside .htaccess:

RewriteRule robots.txt robots.txt [L]

Permissions

Artaengine can be sensitive to user authentication and permissions and check them on certain things. Artaengine employs class Skinner to check current user permissions against required permissions.

In an Artaengine application permissions can be set inside the URL/factory mapping file on:

Artaengine will automatically check the permissions and call appropriate handlers in case of inconsistency. Special events and handlers will be explained later in this tutorial. Rare but it is also possible to manually check permissions with class Skinner .

The following shows how Artaengine checks permissions, by default Artaengine employs principal class Skinner to check and approve permissions. However keep in mind that it is possible to implement your own principal class with your rules. The last section will show how to implement your own principal class.

User authentication and permissions

No matter how the application authentication system is implemented, what Skinner cares about is to find key user_data inside $_SESSION which is not empty. If key is not found or is empty it will consider that the user is unauthorized and will call the unauthorized event handler instead of proceeding.

Artaengine will consider user_data to be an array and if user_data['permissions'] (array) and/or user_data['group']['name'] (string) are existing then the set will be considered as permission tokens and will be compared against the required permissions. Below is an example of what Artaengine principal will recognize and use:

/* USER AUTHENTICATION - for example check login form data with database */
/* IF USER AUTHENTICATION VALID THEN */
/* this is all that is required: */
$_SESSION['user_data'] = array(
    'permissions' => array(
        'permission token name1' => 'permission token id1',
        'permission token name2' => 'permission token id2',
    ),
    'group' => array(
        'name' => 'User group name',
    ),
);
/* A MORE REAL WORLD STRUCTURE WOULD LOOK LIKE: */
/* AFTER READING DATABASE PERMISSIONS WOULD BE:
$permissions = array(
    'clients.read'   => 1,
    'clients.add'    => 2,
    'clients.update' => 3,
    'clients.delete' => 4,
);
*/
$_SESSION['user_data'] = array(
    'username'    => $user->email,
    'name'        => $user->fullName,
    'permissions' => $permissions,
    'group'       => array(
        'id'          => $user->UserGroup->id,
        'name'        => $user->UserGroup->name,
        'description' => $user->UserGroup->description
    ),
);

The group name and the permission array keys are the only important things for the Skinner principal. Also they are only seen as string tokens no matter what they mean.

Putting permissions on URLs

The below examples demonstrate how to put permissions on URLs:

The factory will handle the URL(s) only if a user has signed in (user_data exists and is not empty) the user permissions and group are ignored in this case:

    <route
          path="/myportal/profile"
          factory="User.profile"
          permission="True"
          />
    array(
          'path' => '/myportal/profile',
          'factory' => 'User.profile',
          'permission' => True
    ),

The factory will handle the URL(s) only if user has signed in and
$_SESSION['user_data']['group']['name'] === 'Admin' or
isset($_SESSION['user_data']['permissions']['Admin']):

    <route
          path="/admin/Clients/:action/:id"
          factory="Clients.action"
          permission="Admin"
          />
    array(
          'path' => '/admin/Clients/:action/:id',
          'factory' => 'Clients.action',
          'permission' => 'Admin'
    ),

The factory will handle the URL(s) only if user has signed in and all client.add, client.delete and client.read tokens are defined by $_SESSION['user_data']['permissions'] as array keys. One of the tokens may be $_SESSION['user_data']['group']['name']:

    <route
          path="/admin/Clients/:action/:id"
          factory="Clients.action"
          permission="client.add, client.delete, client.read"
          />
    array(
          'path' => '/admin/Clients/:action/:id',
          'factory' => 'Clients.action',
          'permission' => 'client.add, client.delete, client.read'
    ),

If not authenticated then handle will be given to unauthorized and if not all required permissions exists in the session user_data structure then handle will be given to illegal instead of the factory which should have handled the request. This special events will be explained later within this tutorial.

Putting permissions on factories

Sometimes when defining a route the factory is unknown because it is a part of the route URL so different factories can be mapped to a route and if each factory would require different permission configs then putting permissions on the route would not make sense.

To define permissions exclusively on a factory class or on a factory class.method permission tag is used for XML dictionaries and permissions array for PHP dictionaries as shown in examples below:

A URL will be mapped to any method of class Photo only if the user has signed in:

    <permission
        factory="Photos"
        permission="True"
        />
$configure = array(
    /* ROUTES ARE DEFINED HERE */

    'permissions' => array
        /* FACTORY AND CLASS PERMISSIONS ARE DEFINED HERE */
        array(
              'factory' => 'Photos',
              'permission' => True
        ),
    ),
);

A URL will be mapped to Users.update only if the user has signed in and has users.read, users.update permissions:

  <permission
      factory="Users.update"
      permission="users.read, users.update"
      />
    'permissions' => array
        array(
              'factory' => 'Users.update',
              'permission' => 'users.read, users.update'
        ),
    ),

If not authenticated then handle will be given to unauthorized and if not all required permissions exists in the session user_data structure then handle will be given to illegal. This special events will be explained later within this tutorial.

Putting permissions on classes

Beside putting permissions on URLs and factories permissions can be defined on any other PHP class which are used inside the application, if they are loaded via autoload. Normally in an Artaengine application when a class is not included, the autoload will be called. Below examples show how to put permissions on classes:

Permission on class:

  <permission
      class="MyClass"
      permission="True"
      />
$configure = array(
    /* ROUTES ARE DEFINED HERE */

    'permissions' => array
        /* FACTORY AND CLASS PERMISSIONS ARE DEFINED HERE */
        array(
              'class' => 'MyClass',
              'permission' => True
        ),
    ),
);

Permission on class method:

  <permission
      class="Clients.clientList"
      permission="salesman, client, client.read"
      />
    'permissions' => array
        array(
              'factory' => 'Clients.clientList',
              'permission' => 'salesman, client, client.read'
        ),
    ),

If not authenticated then handle will be given to unauthorized and if not all required permissions exists in the session user_data structure then handle will be given to illegal. This special events will be explained later within this tutorial.

Custom principal

You can create your own principal class and use it instead of Skinner:

  • Create a class which implements IPrincipal. You can find IPrincipal.php inside the artaengine/arta/interface/ directory. To get a hint check class Skinner, maybe tweak it?
  • Your principal class will have three static methods (as explained in IPrincipal interface). Based on your rules each method must return IPrincipal::OK if permissions are sufficient, IPrincipal::UNAUTHORIZED if user has not signed in or IPrincipal::ILLEGAL if user does not have permission.
  • Add your class to autoload. If Your principal class and container PHP file have the same name the default Artaengine autoloader can find it. In the application configs add a section autoload and add the path which your class is in it e.g. 1 = APP_DIR/myprincipal-path. Note that the factories directory is not included in the autoload.
  • Register your principal class. In the application configs under section arta add principal = MyPrincipalClassName.

Mapping special events

Six special events can be declared within URL/factory mapping configuration XML or PHP file:

  <notfound factory="Handle.notfound"/>

  <exception factory="Handle.exception"/>

  <unauthorized factory="Handle.unauthorized"/>

  <illegal factory="Handle.illegal"/>

  <nofactory factory="Handle.nofactory"/>

  <notajax factory="Handle.notajax"/>
$configure = array(
    /* ROUTES AND PERMISSIONS ARE DEFINED HERE */

    'notfound' => array(
        'factory' => 'Handle.notfound',
    ),
    'exception' => array(
        'factory' => 'Handle.exception',
    ),
    'nofactory' => array(
        'factory' => 'Handle.nofactory',
    ),
    'notajax' => array(
        'factory' => 'Handle.notajax',
    ),
    'unauthorized' => array(
        'factory' => 'Handle.unauthorized',
    ),
    'illegal' => array(
        'factory' => 'Handle.illegal',
    ),
);

The factory/handle class and methods would be as:

class Handle extends Response {

    public function notfound($request, $url) {
        /* show/do apropriate mesage
           $url is the bad URL requested */
    }

    public function exception($request, $e) {
        /* show/do apropriate mesage
           $e is an ErrorException object */
    }

    public function nofactory($request, $class, $method, $file) {
        /* show/do apropriate mesage
           $class, $method and $file are what/where the factory
           was expceted to be */
    }

    public function notajax($request, $url) {
        /* show/do apropriate mesage */
        die(); // perfect action!
    }

    public function unauthorized($request, $url, $class=Null, $method=Null) {
        /* $url:               when checking URL permissions
           $class and $method: when checking factory/class permissions */
        if($request->isAjax())
            /* redirecting to login page will not work show a message */
        else
            $this->redirect('/login?url='.urlencode($url));
    }

    public function illegal($request, $url, $class=Null, $method=Null) {
        /* show/do apropriate mesage
           $url:               when checking URL permissions
           $class and $method: when checking factory/class permissions */
         */
    }
}

The names and parameters of each event is self explaining, below is a description for each:

  • This is Error 404. When a URL is requested and it is not defined with a route tag this handle will be called and the invalid URL is passed to the method as an argument.
  • When an unhandled error or exception happens this handle is called and the exception or is passed to it. Error are converted to ErrorException objects.
  • When file, class or method of a requested factory does not exist this handle is called. The not existing class-name, method-name and PHP file they where expected to be found in are passed as arguments.
  • This handle is called when access to a URL, factory, class or method requires user to be logged in but is not. The URL, factory, class or method which requested the access are passed as arguments.
  • This handle is called when access to a URL, factory, class or method requires user to be logged in and have specific permission tokens but has not. The URL, factory, class or method which requested the permissions are passed as arguments.

Resources

It is possible to map a URL to a server directory path inside the URL/factory mapping file but the recommended way is using Apache rewrite engine.

  <resource
        path="/images"
        directory="browser/resources/images"
        />
$configure = array(
    /* ROUTES, PERMISSIONS AND SPECIAL EVENTS ARE DEFINED HERE */

    'resources' => array
        /* RESOURCES ARE DEFINED HERE */
        array(
              'path' => '/images',
              'directory' => 'browser/resources/images'
        ),
    ),
);

Factories - more

Previously it was shown how to create factories to handler requests. Now we will see what is available within a factory context.

Request

The first argument of a factory is always a Request object . This object provides methods and properties for working with PHP request arrays and URL. Below are examples:

Get value from Post/Get/Session/Cookie. Each of Post, Get, Session or Cookie can be used in the same way:

// get value of $_POST['name'] or get Null if key not exists
$name = $request->Post->name;
$name = $request->Post->get('name');
$name = $request->post('name');
// get value of $_POST['name'] or get 'default-value' if key not exists
$name = $request->Post->get('name', 'default-value');
$name = $request->post('name', 'default-value');
// get value of $_POST['id'] or get 0 if key not exists
// and force the to be integer
$id   = $request->Post->get('id', 0, INT);
$id   = $request->post('id', 0, INT);

Set a value into Post/Get/Session/Cookie:

// $_SESSION['name'] = 'Jeff';
$request->Session->name = 'Jeff';
$request->Session->set('name', 'Jeff');

Check is a key exists in Post/Get/Session/Cookie:

if($request->Get->has('name'))
    echo 'exists';

Get a sub-array of Post/Get/Session/Cookie where key starts with the specified key:

// assume:
$_POST = array(
    'myform-name'  => 'aaaa aaaa',
    'myform-email' => 'aaaa@aaaa.com',
    'myform-age'   => 30,
    'search'       => 'aa',
    'otherkey'     => 'aaa',
);
$myForm = $request->Post->with('myform-');
// $myForm will be
array(
    'myform-name'  => 'aaaa aaaa',
    'myform-email' => 'aaaa@aaaa.com',
    'myform-age'   => 30,
); 

Remove or clear:

$request->Get->remove('name'); // unset($_GET['name']);
$request->Post->clear();       // $_POST = array();
$request->Cookie->remove('name'); // timeout name from cookies
$request->Cookie->clear();        // timeout all cookies

To get BASE_URL:

echo BASE_URL;
echo $request->baseUrl();

Other URL methods:

$var = $request->currentUrl(); // current URL
if($request->isRoot())         // current URL == BASE_URL
    echo 'is root';
// create URL based on BASE_URL
$url = $request->makeRelativeUrl('admin/clients/56');
// create URL based on current URL
$url = $request->makeRelativeUrl('admin/clients/56', 'current');
// number of pathes in URL
$var = $request->pathCount();
$var = $request->path();  // array of pathes
$var = $request->path(0); // first path
$var = $request->path(2); // third path
if($request->isAjax())    // is request AJAX
    echo 'ajax';

To learn more see:

Factory context - Response

A factory class must inherit from Response directly or indirectly. See Response API

Using Response methods:

class Home extends Response {

    public function index($request) {
        /* this is just an example! there is no logic behind
           some actions are in conflict with each other */
        // set status
        $this->setHttpStatus(200);
        // set headers
        $this->Headers
            ->set('Content-Type', 'application/force-download')
            ->set('X-MyHeader',   'MyValue');
        // redirect to BASE_URL
        $this->redirect();
        // redirect to BASE_URL/users
        $this->redirect('/users');
        // output text or array
        $this->write('Show this');
        // output text immidiately without closing the response
        $this->writeX('Show this 1');
        sleep(1);
        $this->writeX('Show this 2');
        sleep(2);
        $this->writeX('Show this 2');
        // output file contents, headers will bet based on file type
        $this->showFile('docs/plan.pdf');
        // ouput file for download
        $this->download('docs/plan.pdf');
        // outut as JSON
        $this->writeJson($array);
        // returns a data structure which is always available for
        // the templates and is added to JSON packs
        $data = $this->arta();
        // $data would be as:
        $data = array(
            'resources' => array(
                'fav' => 'if exists the URL',
                'js'  => array(/* JavaScript files to be included */),
                'css' => array(/* css files to be included */),
                'jsx' => array(/* JavaScript codes to be executed */),
            ),
            'BASE_URL' => BASE_URL,
            'DEBUG' => DEBUG,
        );
        // clear template vars
        $this->clear();
        // get template contents
        $html = $this->get('home/about.xhtml')
        // ouput template contents
        $this->show('home/about.xhtml');
    }
}

Method arta will be explained more in the next tutorial. Browser and front-end control

Factory context - Template variables

Properties which are created on fly on a factory are template variables. This is done by Response setter magic method. properties defined as public, private and protected are not available in template context.

In this example templateMenus, class, method and arta data structure are available in template context, method show will send template to the browser.

class Home extends Response {

    public $menu = array(
        'API',
        'Tutorial',
        'Examples',
    );

    public function __construct() {
        $this->templateMenus = array('API', 'Tutorial', 'Examples',);
    }

    public function api($request, $class=NULL) {
        $this->class = $class;
        $this->selected = 'API';
        // writeTemplate and show are aliases
        // $this->writeTemplate('api/index.xhtml');
        $this->show('api/index.xhtml');
    }
}

Response adds a data structure like below to the template context:

$this->arta = array(
    'resources' => array(
        'fav' => 'if exists the URL',
        'js'  => array(/* JavaScript files to be included */),
        'css' => array(/* css files to be included */),
        'jsx' => array(/* JavaScript codes to be executed */),
    ),
    'BASE_URL' => BASE_URL,
    'DEBUG' => DEBUG,
);

Method arta will be explained more in the next tutorial. Browser and front-end control

Factory context - Objects

Database and template objects (is defined) will available as factory public properties. For example see configure.ini a database object named dbo and a template object named tpl are defined so:

class Users extends Response {

    public function list($request) {
        // PHPTAL or Smarty object
        $phpTalObject = Template::get('tpl');
        $phpTalObject->setForceReparse(True);
    }
}

Factory context - Front-end Properties

There are few properties that if defined as public inside the factory would be used by Response for special meanings:

class Users extends Response {

    public $js = array(
        'jquery',
        'jquery/ui',
    );
    public $css = array(
        'jquery/ui',
    );

    public function index($request) {
        $this->js[]  = 'user/list';
        $this->css[] = 'user/list';
        $this->jsx[] = 'alert("Hello");';
        $this->myarray = array(
            'name' => 'something',
            'data' => array(1,2,3,7),
        );
        // see how arta data structure looks like
        I($this->arta());
        // output template
        // JavaScript, CSS files which should be included
        // are available, jsx an array of JavaScript codes
        // to be ran are available by arta data structure
        $this->show('users/index.xhtml');
        // arta data structure is send beside myarray as JSON:
        $this->writeJson();
    }
}

The name of this properties are fixed and reserved.

The reason of this three arrays is to have a way of controlling application front-end from PHP (from factories). There are classes which create widgets, forms, tables and other HTML strings, sometimes they would want to touch something on the front-end, they can add their file paths and JS codes seeming-less to this variables. When using arta.js for AJAX calls loading the files and running the JS codes will all be done automatically but for a template the programmer must use arta data structure.

To follow this properties and their usage see Browser and front-end control .

Download example

URL mapping/dispatch
TOP