Agile Toolkit All In One Digest – Part 2

Part 1 of all in one series:
http://webelizer.net/211/agile-toolkit-all-in-one-digest.html

Database Integration

Agile Toolkit features two basic classes for model creation. The class “Model” is a lightweight implementation for NoSQL and non-relational databases. “Model_Table” class provides a more powerful model implementation which can rely on the power of relational database…

Continue reading “Agile Toolkit All In One Digest – Part 2”

Agile Toolkit All In One Digest – Part 1

At this post we are going to provide an abstract of agile toolkit documents…

 

Installation:

Just extract the files!

 

Config:

Agile Toolkit uses an array for defining configuration.

$config['dsn']='mysql://user:secret@localhost/db';
$config['sample']['setting']=123;

 

The method

 api->getConfig('sample/setting',400);

is used to to retrieve config settings. The second argument to this function is a default value, and it’s used extensively throughout Agile Toolkit add-ons and components.

Copy the config-default.php and name it as config.php.

By default Agile Toolkit will read the config.php and config-defaults.php files. The settings in config.php will override the settings in config-defaults.php.

The file config-distrib.php is never loaded. It is a “template” that you can use to make your own copy of config.php.

Continue reading “Agile Toolkit All In One Digest – Part 1”

Agile Toolkit JavaScript Digest

The purpose of JS chains in Agile Toolkit is to provide a glue between JavaScript and PHP. It is NOT to completely replace native JavaScript.

Agile Toolkit offers a better way to organise your JavaScript code. It is by putting it inside a jQuery namespace. The way you call your function will be slightly different:

// Before
myfunc(123);

// After
$.univ().myfunc(123);

// From PHP
$view->js(true)->univ()->myfunc(123);

 

Extending The Universal library

make a .js file in templates/js and put these codes:

$.each({
    myfunc: function(a){
        alert('myfunc: '+a);
    },
    mysum: function(foo,bar){
        return foo+bar+1;
    },
},$.univ._import);

now you can call js like this:

$page->add('Button')->set('Click Me')
    ->js('click')->_load('secret')
    ->univ()->myfunc('hello world');
/////////////////////////
$page->js(true)->_load('j')->univ()->myfunc(123);

Static Includes

If you are including some 3rd party code, they sometimes might not like dynamic loading. Third party code might assume that the on-ready is not yet triggered or do some other kind of magic. Google Maps code, for example, wants to be loaded along with your page.

If this happens, you can specifically instruct Agile Toolkit to put the include inside the HTML.

$this->api->jui->addStaticInclude('myfile');
// or
$this->api->jui->addStaticInclude('http://pathto/cdn/file.js');

You must be mindful to include this on the page, which is loaded directly, and can potentially open other pages through AJAX, requiring this include. If unsure, add this code to your API’s init() method.

If you want to go even more ‘hardcore’ with the include you can do this:

$this->api->template->append('js_include',
    '<script type="text/javascript" src="http://..."></script>'."\n");

Executing any JS code

One of the goals of JS Chains is security. JavaScript injection is a common problem and by having a nice interface between your JavaScript and server backend you become immune to it.

If you think that you know better, you can execute a string of JavaScript code from anywhere like this:

// DANGER: Contains JavaScript injection vulnerability
$view->js(true,"alert('$my_message')");

// SAFE: $my_message is escaped
$view->js(true)->univ()->alert($my_message);

.

 

Agile Toolkit Hooks ad Controllers Digest

There are the following hooks available for the model (at least):

  • beforeLoad($model, $query) – called before loading SQL query is executed. You have a chance to modify that query. This is called for both model->load() and for iterating through model with foreach($model). This hook is great for applying extra options to your SQL query.
  • afterLoad($model) – called after data have been loaded from SQL. You can now access $model->get() and the model will appear to be loaded. Called for both model->load() and iterating. This hook is great for performing data manipulation and normalization.
  • beforeSave($model) – called when $model->save() is called. This is called inside SQL transaction, so database changes you perform here will be rolled back if save would be unsuccessful. This hook is great for performing data modification before it’s been saved. You can check $model->loaded() to see if a new record is being stored or updated
  • beforeInsert($model, $query) – called when inserting new data and after the insert query is being formed. That query is passed as 2nd argument. This hook is great for changing insert query options.
  • afterInsert($model,$id) – called after insertion method is performed successfully, but before model is re-loaded. You can break out of this hook and return a substitute model. Great for overriding how model is reloaded after insert.
  • beforeModify($model,$query) – called before update SQL query is executed. This hook is great for changing update query options.
  • afterModify($model) – called after SQL query is executed but before reloading has taken place. Note that if you access set() / get() here it will be reloaded by a subsequental reload.
  • afterSave($model) – called after model have been successfully reloaded. This is the last hook to be executed before SQL transaction is finished with commit. Please note taht beforeLoad / afterLoad will also be called during the reloading of a model. This hook is great for hiding some fields from a model after they are being saved such as wiping your password field.

Few more recommendation on query use.

  • to perform additional validation use beforeSave().
  • to measure speed of your query use beforeInsert / afterInsert and beforeModify and afterModify respectively.
  • beforeLoad will be called once per query, but afterLoad may be called several times when iterating through results.
  • apply SQL options in beforeLoad, beforeInsert and beforeModify
  • if you want to divert the query to a different database connection beforeLoad, beforeInsert and beforeModify are good place, but you must enhance DSQL to support switching before databsae handles. If this is what you need, please discuss on Agile Toolkit Development Forum.

 

class Model_Book extends Model_Table {
  function init(){
    parent::init();

    $this->addHook('beforeSave,afterLoad',$this);
  }

  function beforeSave(){
    // manually update some fields before saving. This is to create a indexable field for full-text search
    $this['book_search_field'] = $this['title'].' '.$this['descr'].' '.$this['author_name'];

    // let's also perform some validation
    if(strlen($this['book_name']<10))throw $this->exception('Name of the book is too short');

    // normalization will modify field to match some internal rules
    $this['book_url']=$this['book_url'] ?: preg_replace('/[^a-zA-Z0-9]/','-',trim($this['name']));
  }
  function afterLoad(){
    $this['name'] = $this->api->_($this['name']); // wraps name through localization function
  }
}

======