Compound.js + Backbone.js + doT.js

I like the minimalist and clean solutions and I always look for something like this… hmm, for example doT.js. It is really cool JS template engine. It is quick and small, and user friendly.

So, the Backbone.js is very popular framework. It is not only MVC framework it even has a nice API and it has good references. I don’t want to introduce it because it has well documentation and you can find on the internet many blog-posts and articles about it.

I created one simple Node.js + Compound.js + Backbone.js + doT.js sample application and I would like to show how easy is build “full” 🙂 MVC applicataion which one is use the MVC on the client and server side too.

Ok. First I generated with Compound.js one new controller.

 compound g controller testbackbone  

then I created routings into the config/routes.js

   //testbackbone controller's routings  
   map.get('testbackbone', 'testbackbone#index');    
   map.post('person_url', 'testbackbone#person_url');    
   map.get('person_load/:id', 'testbackbone#person_load');   

I created new layout into the app/layouts/testbackbone_layout.ejs (the naming is important, because the default layout name is the same as your controller name + “_layout” + file extension)

 <!DOCTYPE html>  
 <html lang="en">  
   <head>  
     <title><%= title %></title>  
     <%- stylesheet_link_tag('bootstrap', 'application', 'bootstrap-responsive') %>  
     <%- javascript_include_tag('http://ajax.googleapis.com/ajax/libs/jquery/1.8.3/jquery.min.js', 'bootstrap', 'rails', 'underscore-min', 'backbone-min', 'doT', 'application') %>  
     <%- csrf_meta_tag() %>  
      <style>  
           body {  
                margin: 0;  
                padding: 0;  
           }  
           #mycanvas {  
                display: block;  
                border: 1px solid black;  
           }  
      </style>  
   </head>  
   <body>  
     <div class="container">  
       <% var flash = request.flash('info').pop(); if (flash) { %>  
         <div class="alert alert-info">  
           <a class="close" data-dismiss="alert">×</a>  
           <%- flash %>  
         </div>  
       <% } %>  

       <% flash = request.flash('error').pop(); if (flash) { %>  
         <div class="alert alert-error">  
           <a class="close" data-dismiss="alert">×</a>  
           <%- flash %>  
         </div>  
       <% }; %>  

       <%- body %>  

       <hr />  
       <footer>  
         <p>Blabla</p>  
       </footer>  
     </div>  
   </body>  
 </html>  

this layout will load the JavaScript files but first you shoul download the backbone.js and doT.js and save these to the public/javascripts directory.

Ok, I created the controller methods:

 load('application');  
   
 /**  
  *   
  * testbackbone#index  
  */  
 action('index', function() {  
   console.log(req.params);  
   
   render({  
     title: "testbackbone#index",  
     csrfToken: req.csrfToken  
   });  
 });  
   
   
   
 /**  
  *   
  * testbackbone#simple data saver method  
  */  
 action('person_url', function() {  
   console.log(req.params);  
   
   this.id = req.params.id;  
   send({name: this.name, id: 1});  
 });  
   
   
 /**  
  *   
  * testbackbone#person_load  
  */  
 action('person_load', function() {  
   console.log(req.params.id);  
   if (req.params.id == 100) {  
     send({name: "Wanda", id: 100, age: 20, weight: 120, mobile_number: 555555, email: "test@blabla.com"});  
   } else {  
     send({name: "Joe", id: 1, age: 22, weight: 120, mobile_number: 22222222, email: "test2@blabla.com"});  
   }  
 });  

then I created ejs template:

(The authenticity_token is important because when the Backbone.js use POST method to save data and without this token your request will be forbidden.)

 Test Node+Compound+Backbone+doT 🙂 <br />   
   
 <input type="hidden" id="authenticity_token" value="<%= csrfToken %>" />  
   
 <pre></pre>  
 <script type="text/x-dot-template" id="person_template">  
  <label>Search</label>  
   Name: <input type="text" id="name" value="{{=it.name}}"/><br />  
   Age: <input type="text" id="age" value="{{=it.age}}"/><br />  
   Weight: <input type="text" id="weight" value="{{=it.weight}}"/><br />  
   Mobile number: <input type="text" id="mobile_number" value="{{=it.mobile_number}}"/><br />  
   Email: <input type="text" id="email" value="{{=it.email}}"/><br />  
   
  <input type="button" id="save_button" value="Save" />  
  <input type="button" id="load_button" value="Load" />  
 </script>  
   
 <div id="person_container"></div>  
   
 <%- javascript_include_tag('backbone_model/person_model') %>  
 <%- javascript_include_tag('backbone_view/person_view') %>  
   

… then I created two new directory under the public/javascript directory these two directory will be contain the Backbone.js model and view classes.
…these directory names are “backbone_model” and “backbone_view”.

This is my public directory structure:

mypublicjsdir

So now, the clint side – at first I created Backbone model + collection and view.

The model:

person_model.js:

 /**  
  * Person Model  
  * @type @exp;Backbone@pro;Model@call;extend  
  */  
 var Person = Backbone.Model.extend({  
   // We can pass it default values.  
   defaults: {  
     name: null,  
     age: 0,  
     weight: 0,  
     mobile_number: null,  
     email: null,  
     authenticity_token: $('#authenticity_token').val()  
   },  
   url: function() {  
     return this.id ? '/person_url/' + this.id : '/person_url';  
   }  
 });  

 var PersonCollection = Backbone.Collection.extend({  
   model: Person,  
   url: function() {  
     return this.id ? '/person_load/' + this.id : '/person_load';  
   }  
 });  

The view:

person_view.js:

 /*  
  Person view  
  */  
 (function() {  
   PersonView = Backbone.View.extend({  
     initialize: function() {  
       this.person_collection = new PersonCollection();  
       this.render();  
     },  
     render: function() {  
       //the user ID - it is just sample  
       this.person_collection.id = 1;  
         
       // backbone.js fetch method  
       this.person_collection.fetch({  
         success: function(collection, response) {  
           //doT.js templates  
           var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
           document.getElementById('person_container').innerHTML = pagefn(response);  
         }  
       });  
     },  
     events: {  
       //button events  
       "click #save_button": "doSave",  
       "click #load_button": "doLoad"  
     },  
     doSave: function(event) {  
         
       var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
       console.log(pagefn);  
       //init Person model  
       var newPerson = new Person({  
           
         name: $("#name").val(),  
         age: $("#age").val(),  
         weight: $("#weight").val(),  
         mobile_number: $("#mobile_number").val(),  
         email: $("#email").val()  
       });  
       newPerson.set({isActive: true});  
       newPerson.save();  
     },  
     doLoad: function(event) {  
       //load item by user ID  
       this.person_collection.id = 100;  
       //the backbone.js fetching  
       this.person_collection.fetch({  
         //generating doT.js template  
         success: function(collection, response) {  
           var pagefn = doT.template(document.getElementById('person_template').text, undefined);  
           document.getElementById('person_container').innerHTML = pagefn(response);  
         }  
       });  
     }  
   });  
   
   var person_view = new PersonView({el: $("#person_container")});  
   
 }).call(this);  

I think it is easy. You only call the Backbone.js model’s fetch method and url method and the doT template engine will replace template variables.

The doT template engine is very flexible, for example you can customize its compilation settings.

That’s it. 🙂

Advertisements
Posted in Uncategorized | Tagged , , , | Leave a comment

Compound.js – file uploading

The file uploading process (upload, remove uploaded file etc.) is easy with Node.js and Compound.js. I used ejs template engine and Ubuntu Linux.

1. I added two new routing into the routes.js:

 map.get('upload_form', 'upload_controller#upload_form');  
 map.post('upload_file', 'upload_controller#upload_file');   

2. I added into the app/controllers/upload_controller.js  two new functions:

upload_form – it show upload form.

upload_file – it will handle the uploaded file.

 /**  
  *   
  * show upload form  
  */  
 action('upload_form', function () {   
  render({  
   title: "upload_controller#upload_form"  
  });  
 });  

 /**  
  *   
  * save uploaded file, error handling
  */  
 action('upload_file', function () {   

   var fs = require('fs');  

   this.file_name = req.body.file_name;  
   this.uploaded_file_tmp = req.files.file.path;  
   this.uploaded_file_type = req.files.file.type;  
   this.uploaded_file_name = req.files.file.name;  
   var new_file = "/home/yourhomedir/compound_test/uploaded_files/"+this.uploaded_file_name;  

   fs.rename( this.uploaded_file_tmp, new_file, function(err){  
    if(err) console.log(err);  
     console.log("moved");  
   });  

   console.log(this.uploaded_file_type);  
     render({  
       title: "upload_controller#upload_file"  
   });  
 });  

3. Don’t remember you should create the upload directory and you should set the correct permissions.

 cd compound_test  
 chmod uploaded_files  
 sudo chmod 0777 -R /home/yourhomedir/compound_test/uploaded_files/  

4. I created ejs template files into the /views/upload_controller directory

upload_form.ejs:

 <% var form = formFor('upload_test', {action: 'upload_file', method: 'POST', id: "upload-form", class: 'form-horizontal', enctype: 'multipart/form-data'}) %>  

 <%- form.begin() %>  
   <%- include _form_upload %>  

   <div class="form-actions">  
     <%- form.submit('<i class="icon-ok icon-white"></i> Save & upload file', {class: 'btn btn-primary'}) %>  
   </div>  

 <%- form.end() %>  

_form_upload.ejs:

 <%- form.label('file_name', 'File name') %>   
 <%- form.input('file_name') %>  

 <%- form.label('file', 'File') %>   
 <%- form.file('file') %>  

So, I think that’s it It should be work. 🙂

Posted in Uncategorized | Tagged , , , , | 2 Comments

Install Doctrine2 using Composer

Doctrine2 is one of the top PHP 5.2+ ORM, or rather, it is an Object Document Mapper (OrientDB), Database Abstraction Layer, Migration tool, Object Relational Mapper. I most frequently use Doctrine2 with Symfony2 but it’s possible to use it without Symfony2. I would like to show how you can install it and how you can configure its command line tool.

So, I used Composer to install Doctrine2. I created the new directory and installed the Composer.

 mkdir test_doctrine  
 cd test_directory  
 curl -s https://getcomposer.org/installer | php  

then I created composer.json file:

 {  
     "require": {  
         "doctrine/orm": "*"  
     }  
 }  

After that you can install the Doctrine2 you just use command:

 php composer.phar install  

This command will create directory “vendor” and it should install all Doctrine2 component as well as the Symfony2 command line component.

If you need Doctrine2 command line tool then you have to create “cli-config.php” into your root directory.

cli-config.php

 <?php  
 require_once "vendor/autoload.php";  

 use Doctrine\ORM\Tools\Setup;  
 use Doctrine\ORM\EntityManager;  

 $paths = array("Entities");  
 $isDevMode = false;  

 // the connection configuration  
 $dbParams = array(  
   'driver'  => 'pdo_mysql',  
   'user'   => 'username',  
   'password' => 'password',  
   'dbname'  => 'testdatabase',  
 );  

 // Any way to access the EntityManager from your application  
 $config = Setup::createAnnotationMetadataConfiguration($paths, $isDevMode);  
 $em = EntityManager::create($dbParams, $config);  

 $helperSet = new \Symfony\Component\Console\Helper\HelperSet(array(  
   'db' => new \Doctrine\DBAL\Tools\Console\Helper\ConnectionHelper($em->getConnection()),  
   'em' => new \Doctrine\ORM\Tools\Console\Helper\EntityManagerHelper($em)  
 ));  

..and you should create your model directory:

 mkdir Entities  

After that you can generate your first entity classes with command:

 ./vendor/bin/doctrine orm:convert-mapping --from-database annotation Entities  

The last parameter is your entity DIR name.

Doctrine2 is a complex ORM but I think you should use it in your no-frameworks projects because it has very good generators and cache system.

If you want to know more information from Doctrine2 configuration you should look this URL: http://docs.doctrine-project.org/en/latest/reference/configuration.html

Posted in Uncategorized | 2 Comments

Compound.js: Controller, Routing and simple Ajax request

I created one simple sample app that shows  how Compound.js controllers and routings workings.

First you should create new controller with the controller generator:

 compound g controller fruits show profile ajax_get_profile  

This command will generate new controller class and methods into the directory app/controllers. It name will be “fruits” and it will contain three methods.

 load('application');  

 action('show', function () {  
  render({  
   title: "fruits2#show"  
  });  
 });  

 action('profile', function () {  
  render({  
   title: "fruits2#profile"  
  });  
 });  

 action('ajax_get_profile', function () {  
  render({  
   title: "fruits2#ajax_get_profile"  
  });  
 });  

…then I defined the necessary routings in the config/routes.js.

 exports.routes = function (map) {  

   //fruits controller's routings  
   map.get('profile/:name', 'fruits#profile');   
   map.get('ajax_get_profile/:name', 'fruits#ajax_get_profile');   

   //default routings  
   map.all(':controller/:action');  
   map.all(':controller/:action/:id');  
 };  

I made very simple client-side JavaScript. I used jQuery. The JS file name is profile.js and there is in the public/javascripts/profile.js directory.

   
 /*  
  Profile JavaScript methods  
 */  
 (function() {  
   $('#button1').click(function() {  
     var name = $('#test_container').data('name');  
     $.ajax({  
         url: '/ajax_get_profile/' + name,  
         cache:false,  
         success: function(response) {  
             alert(response.name);  
             alert(response.id);  
         }  
     });   
   });  
 }).call(this);  

I created two view files. In this example I used ejs template because this is the default template engine.

1. app/views/profile.ejs:

 <div class="page-header">  

 <h1><%= title %></h1>  

 <%= name %>  

 <br />  

 <span id="test_container" data-name="<%= name %>"></span>  

 <button id="button1" type="button">Test Ajax</button>  

 <%- javascript_include_tag('profile') %>  
 </div>  

2. app/views/show.ejs:

 <div class="page-header">  

 <%= id %>  

 </div>  

I wrote some lines code into the controller methods…

 load('application');  

 /**  
  *   
  * @returns object show fruit by id  
  */  
 action('show', function () {   
  this.id = req.params.id;  
  render({  
   title: "fruits#show",  
   id: this.id,  
  });  
 });  

 /**  
  *   
  * @returns object show fruit profile  
  */  
 action('profile', function () {   
  this.name = req.params.name;  

  render({  
   title: "fruits#profile",  
   name: this.name  
  });  
 });  

 /**  
  *   
  * @returns object ajax_get_profile fruit by id  
  */  
 action('ajax_get_profile', function () {   
  this.name = req.params.name;  
  send({ name: this.name, id: 1 });  
 });  

As you can see, it is very simple you should use the send() method in your ajax controller class. It send a JSON object to the client what you can parse it normally in the client-side JS. (See above.)

You can test it on these URLs:

http://127.0.0.1:3000/profile/banana

http://127.0.0.1:3000/fruits/show/2

and the Ajax action: http://127.0.0.1:3000/ajax_get_profile/bananas (or click on the button :))

Posted in Uncategorized | Tagged , , | 1 Comment

Quick install CakePHP 2.3.0 on Ubuntu 12.10

CakePHP is a most popular PHP framework. I have written a very simple step-by-step user guide how you can install it on Ubuntu 12.10.

1. Download and install CakePHP to your home folder:

 sudo git clone https://github.com/cakephp/cakephp.git  

2. Create symlink:

 sudo ln -s /home/yourhomedirectory/cakephp/ /var/www/cakephp  

3. Modify CakePHP cache dir permissions:

 sudo chgrp -R www-data /var/www/cakephp/app/tmp/  
 sudo chmod -R g+w /var/www/cakephp/app/tmp  

4. If in your Apache2 configuration file not allowed url rewriting  (the url rewrite module is not enabled) you should enable it, first you should list enabled Apache2 modules:

 cd /etc/apache2/mods-enabled  

If “rewrite.load” doesn’t exists you have to create it:

 sudo vim /etc/apache2/mods-enabled/rewrite.load  

Put into this line:

 LoadModule rewrite_module /usr/lib/apache2/modules/mod_rewrite.so  

save this file as name “rewrite.load”

5. Edit your apache2 sites-enabled file:

 sudo vim /etc/apache2/sites-enabled/000-default  

add into these lines

   <Directory /var/www/cakephp/>  
       Options FollowSymLinks  
       AllowOverride All  
     #  Order deny,allow  
     #  Deny from all  
   </Directory>  

6. Restart apache2:

 sudo /etc/init.d/apache2 restart  

7. Check your site on browser

 http://localhost/cakephp/  

Set your database connection and DebugKit.

Posted in Uncategorized | Tagged , | Leave a comment

jQWidgets the awesome JavaScript framework

I’ve used some JavaScript frameworks (for example ExtJS) but I think jQWidgets is a special one. Why? Because it is very complex and well-designed but it is powerful and easy to use.

It isn’t freeware framework but you want to use jQWidgets for a non-profit project that you can use it free. The jQWidgets can cooperate with knockout.js. It has very good documentation and it has a lot of demo applications. It support the JSON (it use json2) and XML and easy to use from server-side programming languages (the demo contains PHP examples). It contain QUnit JavaScript Unit Testing Framework.

So, It was just very short post 🙂 but It will be enough if you see the jQWidgets demo apps… 🙂

Posted in Uncategorized | Leave a comment

Quick, easy, quick :: Slim, Twig, RedBean

I wanted to create one very quick and minimalist PHP environment what contain one PHP framework, one ORM and one template engine. My dream was that the selected framework should be quick, it must support Composer. I was looking for that ORM one is very quick and it support Composer and I was looking for template engine which support caching and it is complex and it has simple template syntax. And I had one more condition that each component have to support PHP namespaces and have to working with PHP 5.3 or higher version.

So, my choice are these tools:

Slim PHP Framework

Why? I think Slim is a very clean and well-designed PHP framework. It has good routing subsystem and it support PHPUnit. And it is very mini and quick.

URL: http://www.slimframework.com/

Twig template engine

Why? I guess Twig is the best PHP Engine now it has well-designed cache system and template syntax.

URL: http://twig.sensiolabs.org/

RedBean ORM

Why? RedBean is easy, complex and very quick ORM it is real lightweight ORM.

URL: http://redbeanphp.com/

How?

I was installing each component with the composer. My composer.json file is something like this:

First I created new project’s direcory.

 mkdir test_project  

I created my composer.json file.

 {  
   "require": {  
     "slim/slim": "2.*",  
     "twig/twig": "1.*",  
     "gabordemooij/redbean": "*"  
   }  
 }  

I updated my project with composer.

 sudo php composer.phar update  

And I created the simple test project.

 <?php  
 require 'vendor/autoload.php';   

 use RedBean_Facade as RedBean;  

 Twig_Autoloader::register();  

 $app = new \Slim\Slim();  

 $app->get('/hello/:name', function ($name) {  

      RedBean::setup('mysql:host=localhost;  
     dbname=test','user','password');  

      $loader = new Twig_Loader_Filesystem('templates');  
      $twig = new Twig_Environment($loader, array(  
        //'cache' => 'cache',  
      ));  

       $row = RedBean::getRow( 'SELECT * FROM book WHERE id = :id',   
     array(':id'=>7)   
   );  

      echo $twig->render('test.html', array('book_title' => $row['title']));  

 });  

 $app->run();  

Well, I created cache directory and template directory and test.html template file.

 <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">  
 <html>  
 <head>  
 <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">  
 <title>My first test page</title>  
 </head>  
 <body>  
   {{ book_title }}  
 </body>  
 </html>  

and the test URL

 http://localhost/test_project/test.php/hello/john  

Thats it. I think these tools are really has high quality and the PHP is a consistent programming language. You can use PHPUnit, PHPCode_Sniffer and more programming tools which make better your coding standards.

Posted in Uncategorized | Tagged , , , , , | 6 Comments