Skip to content


Writing a PHP5 MVC Framework Part3: Intregrating CI Router to Obullo and Learning SSC Pattern

Alpha 2 version Core Changes:

- deprecated database pattern rewrited new loader::database() functionality
- added get_config, register_base, register, register_static functions to common.php
- added routes.php (config route file) to /application/config/ folder
- added new functionality a Library Class like Model
- added /extends folder and Ob_user.php (super static user class)
- added Ob.php and SSC (super static class) Class.
- Model, Controller and Library class extended to ob class.
- added asn_to_libraries(); func to loader::library()
- loader extended to user class , added loader::pear(); function.
- added show404(); error function to Errors.php
- added Php5 OB_Router, OB_Config and OB_URI classes that derived from CI Libraries.
- changed $this->db->prepare function as $this->db->prep();

Directory structure:

Directory Structure

Directory Structure

Understanding MVC-SSC:
SSC (Super Static Controllers) pattern a new term that i found in the php world.Look at (http://develturk.com/2009/09/25/new-term-in-the-php-world-introducing-new-php-mvc-ssc-pattern/)
We have three main classes; Controller , Model and Library which extends to Ob class.ob , user, loader and SSC classes means a big php SSC scope, we can call none static functions ($this->class->method) inside from static functions (class::method) using these classes.

Look at controller php it extends to ob class.


<?php
if( !defined('BASE') ) exit('Access Denied!');

/**
 * Obullo Framework (c) 2009.
 *
 * PHP5 MVC-min Framework software for PHP 5.2.4 or newer
 * Derived from Code Igniter
 *
 * @package         obullo
 * @filename        base/libraries/Controller.php        
 * @author          obullo.com
 * @copyright       Ersin Güvenç (c) 2009.
 * @since           Version 1.0
 * @filesource
 * @license
 */

 /**
 * Obullo Controller
 * 
 * @package         Obullo 
 * @subpackage      Base.libraries     
 * @category        Libraries
 * @version         1.0
 * @version         1.1 renamed Register as base_register
 * @version         1.2 added extend to ob
 */   
 
Class Controller extends ob
{
    
    function __construct()       
    {   
        $this->ob_init();
        
        parent::__construct();
    }

    function ob_init()
    {
      // Load Automatically None Static Classes.

        $Classes = array(
                            'config'  => 'Config',
                            'input'   => 'Input',
                            'uri'     => 'URI',
                            );
        
        foreach ($Classes as $public_var => $Class)
        {
            $this->$public_var = base_register($Class);
        }
      
      // from now on we can none static classes like this
      // like this $this->class->function(); 
    
    } //end function.

         
} //end class.
  
  
?>

Look at model class also it extends to ob class.


<?php
if( !defined('BASE') ) exit('Access Denied!');

/**
 * Obullo Framework (c) 2009.
 *
 * PHP5 MVC Framework software for PHP 5.2.4 or newer
 *
 * @package         Obullo
 * @author          Obullo.com  
 * @subpackage      Base.libraries        
 * @copyright       Copyright (c) 2009 Ersin Güvenç.
 * @license         http://www.opensource.org/licenses/gpl-3.0.html GPL  
 * @since           Version 1.0 @alpha
 * @filesource
 */ 
 
/**
 * Model Class.
 *
 * Main model class.
 *
 * @package         Obullo 
 * @subpackage      Base.libraries     
 * @category        Libraries
 * @version         0.1
 * @version         0.2 added extend to ob
 */                    

Class Model extends ob {

public $myself;   // called model

    function __construct()
    {
        // assign obullo libraries to all called models
        $this->_asn_lib(); 
        
        // this is just called model name 
        $this->myself = ucfirst(get_class($this));
    }
    
    function _asn_lib()
    {
        $OB = ob::instance();
        
        // declared objects
        $dec_ob = array_keys(get_object_vars($OB));       
       
        foreach ($dec_ob as $key)                                
        {   
            if( ! isset($this->$key) AND $key != $this->myself) // this is wrong 
            {
                $this->$key = $OB->$key;
            }
            
        }
        
        
    } // end func.
    
    
}
// End Model Class

And open base/libraries/Ob.php we extends to new SSC class, this class our super static controller and we define every system functions here.Ssc makes easier our life because of we don’t need write every time like this codes: $this->input->post()

look at SSC (Ob.php)


<?php
if( !defined('BASE') ) exit('Access Denied!');

/**
 * Obullo Framework (c) 2009.
 *
 * PHP5 MVC-min Framework software for PHP 5.2.4 or newer
 * Derived from Code Igniter
 *
 * @package         obullo
 * @filename        base/libraries/Controller.php        
 * @author          obullo.com
 * @copyright       Ersin Güvenç (c) 2009.
 * @since           Version 1.0
 * @filesource
 * @license
 */

/**
*  o SSC Pattern (c) 2009 Ersin Güvenç
*  o We use Super Static Controllers  
*  o for prevent long writing ($this->navigation->nav_level1())
*  o we just write like this user::nav_level1();
*/
 
/**
 * Obullo Super Static Controller (SSC)
 * 
 * We put all static main codes here
 * Like cookie , session, register
 * Goal of the SSC to get all static functions
 * like this ob::instance(), ob::session_set(), 
 * ob::cookie_get(),ob::dbconnect() you can 
 * also use $this var inside from static
 * functions.
 * 
 * @version 0.1
 * @version 0.2 added core functions like ob::register
 * @version 0.3 moved some func to common.php like 
 *              ob::register functions
 */
 
Class SSC extends loader 
{
    /**
    * Gets a config item
    *
    * @access    public
    * @return    mixed
    */
    public function config_item($item)
    {
        static $config_item = array();

        if ( ! isset($config_item[$item]))
        {
            $config =& get_config();

            if ( ! isset($config[$item]))
            {
                return FALSE;
            }
            $config_item[$item] = $config[$item];
        }

        return $config_item[$item];
    }
   
    // get current database settings
    static function config_db_item(){}
    
    static function config_set(){}
    // $this->config->site_url();
    static function config_url(){}
    static function config_baseurl(){}
    // $this->config->system_url();
    static function config_system(){}
   

    /**
    * ob::input_post();
    * 
    * @author Ersin Güvenç
    * @param mixed $key form field
    * @version 1.0
    * @return void
    */
    public function post($key)
    {
        return $this->input->post($key);    
    }
    public function get($key)
    {
        return $this->input->get($key); 
    }
   
    // identical CI $this->input->get_both
    static function both($key,$bool){}
    
    // identical CI $this->input->get_post
    static function xss(){}
    
    /**
    * ob::input_ip();
    * Validate ip address
    * @param mixed $key ip addres
    * @version 1.0
    * @return void
    */
    public function ip()
    {
        return $this->input->ip();
    }
    
    public function input_server($key){}
    

    public function user_agent(){echo 'ok';} 
    
    // sessions
    public function session_set($key,$array = NULL)
    {
        // kullanıcı ilan edicek 
        // OB_Session::session_set sadece bunu yaz.
        
    }
    
    public function session_set_userdata($array = NULL){}
    
    public function session_userdata($array = NULL){}
    
    public function session_flashdata($array = NULL){}
    
    // cookies..
    public function cookie_get(){}
    
    public function cookie_set(){}
   
    
    // language class
    // otomatik yada kullanıcı tarafından yukleniyor.
    // load library ile
    public function lang(){}

    
    // redirect function
    public function redirect(){}
    
}  // end ssc class.
 
 
Class OBException extends CommonException {}  

 /**
 * Obullo Super Object (c) 2009
 * 
 * @version 0.1
 * @version 0.2 added core functions like ob::register
 * @version 0.3 added extending to SSC, moved register
 *              functions to common.php
 */
 
Class ob extends SSC
{
    /**
    * Obullo instance
    * 
    * @var object
    */
    private static $instance;

    /**
    * Construct func.
    * @return void
    */
    public function __construct()
    {
        self::$instance = $this;
        
        parent::__construct();
    }

    /**
    * ob::instance();
    * 
    * Get the Obullo Super Object Every Where
    *  
    * @author Ersin Güvenç
    * @version 1.0 
    * @version 1.1 getInstance renamed and moved into ob class
    * @return object
    */
    static function instance()
    {
        return self::$instance;
    } 
    
    
    /**
    * ob::dbconnect();
    * Factory and Connect to database driver
    * Get pdo database handle
    * 
    * @author Ersin Güvenç
    * @version 1.0
    * @version 1.1 moved into ob class
    * @return object - pdo database handle
    */
    static function dbconnect()
    {
        return OB_DBFactory::Connect();
    }
    
} // end class.


?>

Forexample we define $this->input->post() function into SSC class and we can call it as ob::post(); instead of $this->input->post() code.This functionality especially for developers but we have a Global user class that the loader extends to it, and this means users also can define their custom static functions inside to user super static class.

Normally in Code Igniter you must write below the codes for every controllers.

<?php
class Test extends Controller {

    var $base;
    var $base_img;
    var $css;
    var $css_print;
    var $password_salt;
    
    function Test() {
        
        parent::Controller();

        $this->base = $this->config->item('base_url');
        $this->base_img = $this->config->item('base_image_url');
        $this->css = $this->config->item('css');
        $this->css_print = $this->config->item('css_print');
        
    }

?>

But in obullo you don’t need write them everytime, SSC Pattern makes your life to easier.You will just write parent::__user(); (top constructor for every controllers)


Class Test extends Controller
{
    function __construct()
    {
        parent::__construct();

        // top constructor for every controllers.
        parent::__user();
        
    }    

}

Look at Global user class /extends/Ob_user.php (user class).
Users put their common special functions here and “user” functions works everytime for every controller..


<?php
  
  /**
  * OBULLO USER DEFINED COMMON FUNCTIONS
  * 
  * o SSC Pattern (c) 2009 Ersin Güvenç
  * o We use Super Static Controllers 
  * o for prevent long writing ($this->navigation->nav_level1())
  * o we just write user::nav_level1();
  *  
  * Just Put your common special functions here !!
  * "user" functions works everytime for every controller
  * So you should put your common functions in
  * your application which interested in like
  * this categories..  
  * 
  *       o site navigation menu func.,
  *       o authentication functions
  *       o module functions
  *       o 
  * 
  * it will work like this ob_user::yourfunction
  */

  Class user
  {
      
      public $base_url = 'http://localhost/obullo/';
      public $base_img;
      public $base_css;
                   
      /**
      * parent::__user();
      * User common __construct for all controllers
      */
      function __user()
      {
          // ALSO YOU CAN load your static classes like this !
          // loader::library('mystatic_class',true);
          // loader::library('mystatic_class2',true);
          
          loader::library('navigation');
          //loader::library('session');

          
          echo 'this my top __Constructor for all controllers ! It comes from /application/extends/Ob_user.php<br />';
      }
      
      // SSC Pattern (c) 2009 Ersin Güvenç
      // We use super static controllers 
      // for prevent long writing ($this->navigation->nav_level1())
      // we just write user::nav_level1();
      public function nav_level1()
      {
          return $this->navigation->nav_level1().'<br />';
      }
      
      public function nav_level2()
      {
          return $this->navigation->nav_level2().'<br />';
      }  
      
  } // end class.
  
  
?>

New Library functionality of Obullo:
I added a Library functionality to obullo like Model class.This means extending to Library class again makes your life to easier. You don’t need to write get_instance() function (in CI) or ob::instance() (in Obullo) for every user Library files.Just you will extend to main Library class and you will write parent::_construct() like a model.

You can also call static functions from the library files.Like SSC class functions ob::ip(); or Global user class functions user::nav_level1();

Look at the example library file.(application/libraries/mylibrary.php)


<?php

  Class mylibrary extends Library 
  {
      function __construct()
      {
          parent::__construct();
                  
          loader::database();
          
          // you don't need it if you declare it before in test controller
          // parent::__user();  
          
      }
   
      function test_ssc()
      {
          
          echo '<br />'.$this->base_url.' <-- this comes from ob_user.php<br />';
          
          // I can use db class directly from my lib.
          // WITHOUT ci = &get_instance() func unlike CI
          echo '<br /><b>i can use db functions directly from library.(Without get_instance() func.)</b><br />';
          $this->db->drivers();
        
          echo '<br /><b>i can use static functions from library:</b> '.ob::ip().'<br />';
        
          // My Super Static Class Functions
          // Look at application/extends/Ob_user.php
          user::nav_level1();
          echo '<br />';
          user::nav_level2();
        
      }
      
  }

?>

Integrating Code Igniter Router and URI classes to Obullo:
We need to a router functionality for our framework.I used CI libraries and i just convert php4 functions to php5.

Like this


 Class RouterException extends CommonException {} 

 /**
 * Router Class
 * Derived from Code Igniter library
 * Parses URIs and determines routing 
 *
 * @package     Obullo
 * @subpackage  Libraries
 * @category    URI
 * @author      Code Igniter - ExpressionEngine Dev Team
 * @author      Ersin Güvenç
 * @link        
 */
class OB_Router {

    public $config;    
    public $routes              = array();
    public $error_routes        = array();
    public $class               = '';
    public $method              = 'index';
    public $directory           = '';
    public $uri_protocol        = 'auto';
    public $default_controller;
    
    /**
    * Constructor
    *
    * Runs the route mapping function.
    */
    function __construct()
    {
        $this->config = base_register('Config');
        $this->uri    = base_register('URI');
        $this->_set_routing();
        // log_message('debug', "Router Class Initialized");
    }
.
.
.
.

Now we can integrate Router and URI classes into index.php file.
index.php


<?php

/**
 * Obullo Framework (c) 2009.
 *
 * PHP5 MVC-min Software for PHP 5.2.4 or newer
 * Derived from Code Igniter.
 * 
 * @package         obullo
 * @filesource      index.php        
 * @author          obullo.com
 * @copyright       Ersin Güvenç (c) 2009.
 * @since           Version 1.0 @alpha
 * @license         http://www.opensource.org/licenses/gpl-3.0.html GPL 
 */
                              
/* ---------------------------------------------------------------------------*/                               

header('Content-type: text/html;charset=UTF-8'); 

Class CommonException extends Exception {}  

// Base paths
define('DS',DIRECTORY_SEPARATOR);
define('BASE', 'base'.DS);            
define('APP',  'application'.DS);   
define('EXT',  '.php');
define('MODEL', 'application'.DS.'controllers'.DS);
define('VIEW', 'application'.DS.'controllers'.DS);
define('CONTROLLER', 'application'.DS.'controllers'.DS);
define('SELF', pathinfo(__FILE__, PATHINFO_BASENAME));  

require (BASE.'libraries'.DS.'Registry'.EXT); 
require (BASE.'libraries'.DS.'Library_factory'.EXT); 
require (BASE.'Common'.EXT);    
require (BASE.'libraries'.DS.'Errors'.EXT); 

$Config = base_register('Config');
$Uri    = base_register('URI');
$Router = base_register('Router');

//echo 'class: '.$Router->fetch_class().'<br />';
//echo 'method: '.$Router->fetch_method();  exit;

$GLOBALS['c']   = $Router->fetch_class();  // Get requested controller
$GLOBALS['m']   = $Router->fetch_method(); // Get requested method

// Check the controller exists or not
if ( ! file_exists(APP.'controllers'.DS.$GLOBALS['c'].DS.$GLOBALS['c'].EXT))
{
    new CommonException('Unable to load your default controller.
    Please make sure the controller specified in your Routes.php file is valid.');
}

require (BASE.'libraries'.DS.'Loader'.EXT);
require (BASE.'libraries'.DS.'Ob'.EXT);
require (BASE.'libraries'.DS.'Controller'.EXT);
require (BASE.'libraries'.DS.'Library'.EXT); 
require (BASE.'libraries'.DS.'Model'.EXT);

// call the controller.
require (CONTROLLER.$GLOBALS['c'].DS.$GLOBALS['c'].EXT);


if ( ! class_exists($GLOBALS['c'])
    OR $GLOBALS['m'] == 'controller'
    OR strncmp($GLOBALS['m'], '_', 1) == 0
    OR in_array(strtolower($GLOBALS['m']), array_map('strtolower', get_class_methods('Controller')))
    )
{
    show_404("{$GLOBALS['c']}/{$GLOBALS['m']}");
}


// If Everyting ok !
$OB = new $GLOBALS['c']();


// Check method exist or not
if ( ! in_array(strtolower($GLOBALS['m']), array_map('strtolower', get_class_methods($OB))))
{
    show_404("{$GLOBALS['c']}/{$GLOBALS['m']}"); 
}

// Call the requested method.
// Any URI segments present (besides the class/function) will be passed to the method for convenience
call_user_func_array(array($OB, $GLOBALS['m']), array_slice($Uri->rsegments, 2));


?>

I added router class and methods inside to GLOBAL variables because of we use current controller name and method in everywhere.Especially loader class use $GLOBALS['c'] (controller name) in Loader.php library and model functions.


<?php

$GLOBALS['c']   = $Router->fetch_class();  // Get requested controller
$GLOBALS['m']   = $Router->fetch_method(); // Get requested method

?>

Look at also Loader.php

Run the index.php (test controller.)

Click to Link !

index.php result

index.php result

Integrated Router Class to Obullo.

Integrated CI Router to Obullo

Integrated CI Router to Obullo

Download Obullo Framework 1.0 @alpha 2

FacebookDiggDeliciousGoogle BookmarksTechnorati FavoritesYahoo BookmarksWebnewsTechnotizieLinkatopiaPingStumbleUponTwitterShare

Posted in php articles.

Tagged with , , , , , , , .


9 Responses

Stay in touch with the conversation, subscribe to the RSS feed for comments on this post.

  1. Way says

    Absolute fantastic work. I’m a big fan of your MVC Framework series and the SSC is a really interesting thing. I’m looking forward to the next part(s).
    Keep going ;)

  2. Ignas says

    I found this series today and I must say – it’s very interesting and I hope you’ll continue to work on this :) Thanks man!

  3. Neoman says

    Good job! keep working :)

  4. way says

    What’s about Part 4? What can I expect?
    A session and authentification class would be very nice. I wonder, in part 2 there already was a session class!?

  5. ersin says

    im working on obullo style directory routing

    CI directory route: /class/method/arguments…
    Obullo will be like this: /directory/class/method/arguments..

    and about part2′s session class it was just an example and it was very basic.I will integrate CI session class to Obullo because of its very secure.

    So part 4 subjects:
    - Advanced Routing
    - Session Class Integration
    - Calling session functions with SSC

  6. xtc2xl says

    Sexy, you kicking ass. Very nice lightweight framework taking advantage of new methods ;)

  7. Ignas says

    I can’t wait to read part4 :)

  8. ersin says

    you should wait it i will also tell integrating CI active record with PDO :)

  9. Namaless says

    Thanks for releasing your framework..

    Codeigniter is great Framework but not used the power of php5 ^_^

    Download and test it :-)



Some HTML is OK

or, reply to this post via trackback.