Butler Documentation Wiki

Welcome to the Butler's oficial documentation. If you find something confusing or with a lack of explanation, please, send an email to info@ivgam.com. We try to solve it as soon as possible. Thanks for your collaboration and we hope that this wiki helps you.

Configuration

Databases /app/databases.ini

Butler provides a multi-instance configuration that allows you to define all the connections that you need. This configuration is inside the file /app/databases.ini and have the next structure:

Every block defines one instance. By default, Butler access to the intance with the name: local. For create the database connection, Buler use PDO adapters plus a singleton pattern, that ensure no open more the one connection for the same instance. And what happens with the destructor? Don't worry, PDO close the connection automatically in the destructor method.

For more information about the creation of instances and query execution, click here.

Routes

By default, Butlers works with a generic router that use the next sintax http://mydomain.com/controller/task , where controller is the result of remove the suffix _controller of our controller, and task, the name of the public method that we like to execute.

However, it's possible that we like to create custom routes. For this, Butler have one file, /app/config/routes.php, where we can define all the routes that we need. This file, use the next structure.

Where...

  • controller: Name of the controller that resolve the route (fullname of the class)
  • url: An internal name (usefull for the debug)
  • regex: The rule that provides the match of the URL
  • params: An array that defines all the params that this route receives. If the regex have parenthesis statements ((.*):), the params will be filled in order of resolution in the regex match. If we define a value in this array, is the default value (if isn't filled by the regex matches, will have this value).
  • task: The public method of the controller that we like to execute
  • resource: The shortname of the controller (Error_controller => error)
  • cacheable: Defines if this route can be cached
Every position of the array defines one route. The array index, is only a name, an identifier, doesn't have any specific use more than remember who's who.
This file operates like a funnel: the routes that are in the top have more preference that the routes defined in the bottom. Said this if one URL matches with more than one route, the route that will be resolved is the first one. This can also been defined as: we need to define the more specific routes at the begging of the file and the more generic routes at the end of the file.

Variables

The environment vars of Butler are defined in the /app/configuration.ini file. In it, we can define all the vars that we need and create groups for the different environments. The configuration result is saved in the class Fw_Register, that provides a method called getConfig($name), that returns the value of the config var with the name $name. By default, the vars the we define are the vars that are in the config block plus the variables that are in the current enviroment block (test, prod, integration...). If the same var is defined in the config block and in the current environment block, the var overrides their value with the value defined in the var of the current environment block.

Access Control List (ACL) /app/acl.ini

The access management was configured in the /app/acl.ini file, that provides a hierarchy of roles, resources and subresources, and their respectives permissions.

The definition of this terms is something like:

  • Role: Type of user
  • Resource: Controllers Group
  • Subresource: Everyone of the controllers that we have in the application

And below...the steps for made this file:

  1. Inside the roles block, we list all the roles that we like to provide in our platform, assign it to everyone which is their parent. If is a root role, we asign a blank value ("").
  2. Inside the resources block, we list all the groups of controllers that we like to create, assign it a null value.
  3. The next step is the subresources block. In it, we list all the controllers that we have in the application and we assign to which block they belong.
  4. The last step is create one block for every role and inside, we list all the permissions createing strings like: role.resourceOrSubresource.task = allow/deny
    • In role we put one of the roles that we define in the first block.
    • In resourceOrSubresource a resource or subresource.
    • In task, one of the public methods that are inside the subresource or all, that determinates the entire set of public method that we can execute inside this resource/subresource.
    • If we assign a allow value, we allow the access. If we assign a deny value, we deny the access.

Below, an example of a posible acl.ini file.

Scripts

Butler provides a place to concentrate all the scripts (CSS & JS) that will be needed in our requests. For do this, use 4 files, 2 for the frontend (/app/config/frontscripts.php & /app/config/frontstyles.php) and 2 for the backend (/app/config/frontscripts.php & /app/config/frontstyles.php). All the CSS that we define in this files will be included at the end of the <header> tag and all JS just before the close of the <body> tag.

Below, an example of the content of this files:

/app/config/frontscripts.php
/app/config/frontstyles.php
/app/config/backscripts.php
/app/config/backstyles.php

Request to Response

Start /public/index.php

All the requests that receives the server are rewrited to point to the index.php file that are present in the public folder. Don't worry if your virtualhost doesn't point directly to the public folder, because Butler have another .htaccess file in the root folder that rewrites the request to the public folder.

Root folder /.htaccess file

When we are sure that we are in the public folder, we force to execute the index.php file. This rule only have effect if the resource that the user solicite via URL doesn't exists, because if the resource exists (for example a css or js file), Butler allows the direct access to this file.

/public/.htaccess

Loading Classes /app/config/autoloader.php

The automatic class loading use the next rules:

Type Classname Pattern Filename Pattern Path
Controller MyControllerName_Controller mycontrollername.controller.php /app/controllers/
Model MyControllerModel_Controller mymodelname.model.php /app/models/
Helper MyHelperName_Controller myhelpername.controller.php /app/helpers/
The core classes are automatically loaded and are inside the /libs/fw folder.
For load vendor libraries, you need to modifiy the /app/autoloader.php file, for ensure that all the classes can be founded for the application.

Initialize /app/bootstrap.php

After set all the global vars and define the class autoloader, the execution path cross through the /app/bootstrap.php file, that provide a place to define all the functions that we need to execute for ensure a good initialization of our application. When the bootstrap file is called, all the functions that start with init_, will be executed in the same order that are defined in the file

By default, Butler provides initialization functions that initialize the database, global vars, the error_handler and the debugger.

Dispatching /libs/fw/class/dispatcher.class.php

We are initialized! Now, we need to dispatch our request. For this, Butler use the Fw_Dispatcher, that is the responsable of process the request. In it, Butler, instance the Router, the MVC and manage the Request Cache.

Routing /libs/fw/class/router.class.php

The Dispatcher file can't know alone which is the controller that we need for process the current request. For this, needs the help of the Router, that centralize all the route rules of our application. By default, use the next one:

http:/mydomain.com/controller/task/param1/params2/.../paramN

If we like to define another type of routing, we must to extend/modify the Fw_Router class. If we only need to create that some URL's have an specific behaviour, we can create custom routes in the routes file (view Configuration/Routes).

Caching

By default, the cache is not enabled. If we like to enable id, we only need to change the value of the cache_mode configuration var to true, that is inside the /app/config/configuration.ini file.

When the cache is enabled, all the routes that have the cacheable field to true in the /app/config/routes.php file, creates a file that will be returned for all the request to this route. This field expires in the beggining of the next hour.

All the cache files are genereted in the /app/cache folder and contains all the request html with the exception of the debug bar. The name pattern of this files is controller_task_Y_m_d_H_p_urlparams.cache, where controller is the controller's name, task the name of the method executed, Y_m_d_H the year, month, day and hour separated by _ and urlparams the result of separate via _ all the params of the URL that aren't part of the $_GET.

The parameters used in the cache file name, are the parameters that are part of the route.
For example: http://mydomain.com/controller/task/2?p1=v1, generates the controller_task_2013_07_05_12_p_2.cache file.

MVC

Controllers

The Controllers in Butler doesn't have lots of differences between the generic controller that defines the MVC. In it, we found some task, that are defined using public methods. In this methods, we can call to different Models and Views, creating the custom response that we like to solve the current request.

All the Controllers needs to extend of Fw_Controller and needs to be placed in the /app/controllers folder. Only for extends this class, we obtain the next execution path:

  1. pre
  2. execute
  3. post

The pre method can be extended and allows us to execute a routine before the execution of the task. This routine will be executed in all the tasks of this controller. The same happens with the post post, that allows us to create a post execution routine in all the tasks of this controller.

The other native Fw_Controller methods are public, but is better doesn't extend it, because are very linked with the core functionalities.

Below, an example of a Controller:

/libs/fw/controller/auth.controller.php

Layouts

The Layouts are page renderization structures. In other words, every one of the different styles that have our application. By default, Butler have 3 (blank, admin and defaut), but you can create more or modify the default ones.

We can create all the Layouts that we need and for use it, we only need to assign it in the Controllers constructor (if like to have the same layout for all the tasks of this Controller) or task by task (if we need that only affects to this task).

One of the most important things to take in account is the $html variable, that contains the specific content of our task. In the place that we put this variable, the view will be renderized.

/app/layouts/blank.php

CRUD Controller

Fw_CrudController is a class that extends of Fw_Controller and offer us the posibility to manage the registers of Database Table very easily and useful.

Contains, principaly, 5 functions:

  • Admin:

    Creates a table view that contains fields for create custom filters for show only the records that we like. This search using filters, we can use the next sintax:

    • Exact Search: = num or = 'text'
    • Interval Search: > num , < num, <= num, > date ...
    • Approximate Search: LIKE '%text%' , LIKE 'Text%' ...

    For configure the columns that appears in this view, we need to set the admin_params attribute in the __construct method of our controller, that use the next sintax:

    Title N is the name of the column header in the table view y fieldN is the name/alias of the field in the query that obtain the result of the table.
    An example of the admin view of User_Controller class(/app/controllers/user.controller.php)
  • Edit:

    An example of the edit view of the User_Controller class(/app/controllers/user.controller.php)
  • Add:

    An example of the add view of the User_Controller class (/app/controllers/user.controller.php)
  • Set:
  • Delete:
/libs/fw/controllers/category.controller.php

Models

The Models, like the Controllers, have the traditional structure of a MVC Model. In this case, we found that all the Models needs to extend from the Fw_Model class, that contains the basic methods for access to the table information.

This methods are:

  • delete($id)

  • deleteRow($id)

  • formatSelectCols($cols)

  • getAclDataForSelect($field, $where)

  • getAll($cols, $fetchmode)

  • getData($count, $limit, $limitstart, $cols)

  • getDataForSelect($table, $field, $join, $where)

  • getRow($id, $cols)

  • insert($values)

  • setNMRelationships($nTable, $mTable, $idNTable, $aIdMTable)

  • setRow($values, $id)

  • update($id,$values)

/libs/fw/models/category.model.php

Views

Modules

Core Classes

Fw_Register

Butler provides a Register Pattern that allow you to store variables and objects that after you like to restore. For use it...you only need to do this:

Fw_Db

The Fw_Db class is a factory of database instances that provides a singleton pattern. If one instance is needed before, doesn't create a new one, only return the last one.

All the instances created with this system, are part of the PHP standard Data Objects (PDO). Said this, you can use all the functions that provides this standard library (more info).

For get an instance and execute a query, we need to write something like:

Misc

CCC (Combine Compress and Cache)

Butler offers the posibility of combine, compress and cache all the JS and CSS in only one file (one for every extension). For do it, you only need to go to admin panel and do clic in the option Minify Scripts, that is in the Tools menu. This action will combine all files that we defined in the scripts configuration files (view Configuration/Scripts) and generetes one file for every type of extension and environment (backend and frontend).

By default, this files are generated in the next folders:

  • /public/javascripts/generated/front
  • /public/javascripts/generated/back
  • /public/stylesheets/generated/front
  • /public/stylesheets/generated/back

For use the files generated for the CCC functionality, you only need to set the minify_js and minify_css vars to true in the /app/config/configuration.ini file.
The external JS and CSS (outside the server), and all the files that aren't in the configuration files, aren't in the minified files.
CCC means Combine, Compress and Cache. This means that if you do changes in your scripts you don't view it in your app until you create again your minified files.
The minified action execution generates a new files and deletes the old ones.

DB Dumper

Inside the admin panel, we have the posibility to do a full dump or a only structure dump of the default database that use Butler (local). If you like to do dumps of other instances, you need to change the core a little bit or wait for the next releases.

This functionality is in BETA and doesn't take in account the possibility of have enabled the debug. For this, when we work with the debug_mode enabled and we dump our database, we obtain a SQL file that have, in the end, the HTML of the debug bar.

i18n

The text internationalization of Butler is made with the PHP native function getText(), that also can be called with the minfied alias _(). For use it, you only need to create one folder for every language that you like to use and, inside, the .mo and .po files, that are loaded inside the application in the /app/bootstrap.php file.

For create the .mo and .po files, you can use some applications. However, one of the most easy to use is PoEdit, a lightweight and multi-platform software that allow us parse all the the application and obtain all the texts that we use automatically.

Debugging

Butler provides a Debug Toolbar that allow us to work more confortable in local and test environments. For enable it, you only need to set to true the debug_mode inside the /app/config/configuration.ini file.

After that, in every request, you can view an icon like . If you click it, a toolbar with different sections will be open. Every section can be clicked for obtain more information.

This sections are:

  1. Queries

    In this section we found all the queries that was executed in this request, which is their status, the execution time and how many rows was affected for they.

    The number in parenthesis is the total number of queries executed in the current request.

  2. Memory Usage

    In this section are listed all the files that we load in the current request and, in parenthesis, the max memory used for process the request.

  3. Errors

    When we are developing is very noisy view the notices, warning and errors in the middle of our html. For this, this section groups all of them and we can view it more easy and grouped by error type.

    The number in parenthesis is the total of errors that the error handler found ( notices+warnings+ fatal_errors)

  4. Headers

    All the headers of our request.

  5. Vars

    In this section we found all the vars that cames with the request ($_GET, $_POST, $_COOKIE, $_REQUEST, $_SERVER), the global vars and all the constants that was defined for process the current request. Also, here there are all the vars that we put in the Register (view Fw_Register).

    Sometimes is useful add variable to the Fw_Register and check their values in the debug, because using alternatives like var_dump, we don't know exactly in which place of the DOM appears our result.
  6. Time

    Total time that the server spends for process the request.