Wednesday, May 5, 2010

CodeIgniter Helpers – How to write your own?

Find yourself again and again doing CI or are you just getting started in to your next big project ? Get this book by Rob Foster. This is an easy-to-follow guide consisting of a number of projects that enable you to develop full-featured applications at a fast pace. CodeIgniter Web Application Blueprints

What is here:
         -> What is a codeigniter helper? an example
         -> Creating your own codeigniter helper, create a helper which will have a function to Check Ajax requests
         -> Accessing sessions/models from within Helpers
         -> A tip on how to load codeigniter models from within another model.

From CI site
Helpers, as the name suggests, help you with tasks. Each helper file is simply a collection of functions in a particular category. There are URL Helpers, that assist in creating links, there are Form Helpers that help you create form elements, Text Helpers perform various text formatting routines, Cookie Helpers set and read cookies, File Helpers help you deal with files, etc.

A helper can be loaded anywhere within your controller functions (or even within your View files, although that's not a good practice), as long as you load it before you use it.
Let me give you and example:
in controller, model or view you have to first load the helper you want to use with following line:
$this->load->helper('name');
where ‘name’ === is helper file residing in ===>  application/helpers/name_helper.php (custom helper if exists)
or system/helpers/name_helper.php (bundled with codeigniter)

name’ is the name you want for your helper, then a _ (underscore) & helper.php, the codeigniter’s way.
if you want to look at a sample: go check system/helpers folder, they come bundled with codeigniter. Here’s a snippet from: system/helpers/url_helper.php
<?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');

if ( ! function_exists('site_url'))
{
    function site_url($uri = '')
    {
        $CI =& get_instance();
        //every time you need to use codeigniter system libraries or functions or model you’d do this      through the get_instance
        return $CI->config->site_url($uri);       
    }
}
Remember, when you used this site_url() function?? okay what you did was:
loaded the helper at your controller construction or where ever you needed using,  $this->load->helper('url');and simply echo site_url(); or like that. 

How to write your own helper  : Check Ajax Request using Codeigniter Helper

Yesterday, while going through my current project, I was calling lots of controller actions with jQuery Ajax and i was in need to check whether the call/request is made through Ajax or not in the controllers. Since i needed a way to use this facility in lots of controllers, i thought helpers would come handy here.
Rather than just copy/pasting the same lines of code in every controllers or at times you may need to use same functions in models & views too, it is good practice to make this function have some separate space in helpers (but not a good practice to load helper in views, see above, from CI site). So you should be clear at first whether your function need a place in helper or not??? Ask yourself  and decide for your work, if the frequency of your function call is going to be maximum, sure create a new helper or extend existing one. I decided to create one in my case.
Okay let’s make our Ajax request checker?? isAjax() function, residing in useful helper. When i Googled around for checking Ajax request i found a three line snippet here CHECK FOR AJAX REQUEST, i’ll will be implementing this for our purpose here. It goes like this:
function isAjax() {
return (isset($_SERVER['HTTP_X_REQUESTED_WITH']) &&
($_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest'));
}
The Helper:
system/application/helpers/useful_helper.php
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
//secure your snippet from external access
function isAjax() {  
           return ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');  
      }
?>
Using in Controller: application/controllers/somecontroller.php
function submit_form(){
//function you call when you submit your form through Ajax. 
$this->load->helper('useful'); //load our just defined helper
if(isAjax()){
          echo ‘The request is made throug ajax. success!’ ;
          //do your stuffs
          exit;
       }     
}
 
Accessing session/models from within Helpers
<?php if (!defined('BASEPATH')) exit('No direct script access allowed');
      function isAjax() {  
           return ( isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == 'XMLHttpRequest');  
      }
     function check_login(){     
      //$userId = $this->session->userdata('userid); this line will not work here <<-----
       // you'd access your session variables through get_instance() as below
       $CI =& get_instance();
       //now session access through this instance
       $userId = $CI->session->userdata('userid);
       if ($userid < 0 ) {
              return 0; //user not logged in
           }
      else {
             return 1; user session exists, must be logged in 
           }
      }
  function hello_model_world(){     
        //or if you decided to load & use you models here
        //$this->load->model('Hello_model');   <---- this will not work too.
        //use as 
         $CI =& get_instance(); //first get instance
         $CI->load->model('Hello_model');  //then load model through instance.  
         //and calling a model function
         $data = $CI->Hello_model->display_this(‘hello world!’);
        //assuming your model returns capitalizing the initial letters of the words
         return $data; //will give Hello World! 
      }
?>
Now, you can easily load your helper in controllers & models and use it as regular helpers.

Extra tip about loading codeigniter model from another models:

You see how handy the $CI =& get_instance(); is in helpers. okay, let me add a quick tips talking about this, what if at times you needed to find out a way to load another models in your current model?? Ok here’s the solution:
<?php
class Test_model extends Model {
function Test_model()
    {
        //Call the Model constructor
        parent::Model();
    }
function do_something(){
//you wanted to load another model called Hello_model here in this function in this model class
//it’s okay
//use
         $CI =& get_instance(); //first get instance
         $CI->load->model('Hello_model'); //then load model
         $data = $CI->Hello_model->display_this(‘hello world!’); //call functions
         //do anything with this $data        
}
}
?>


Happy Coding.
Regards


Monday, May 3, 2010

Hello World – CodeIgniter Model – A Simple Bookmark Manager

Continued from Hello World – CodeIgniter!

I’ve been a bit busy with my development works. Talking about codeigniter,i will discuss today on how we can use it to access MySql database, insert data into tables, retrieve and display them, at times delete them. We’ll create a very simple Bookmark Manager App (just for the sake of understanding models in codeigniter, i’ve added code over the last article )

  what we’ll do today 

-1. if you don’t have codeigniter yet, download it from ci site.
0.rename extracted CodeIgniter zip folder to ci & add it to your server root - xampp/htdocs or wamp/www  folder
1. Database Design: create database & table representing our Bookmark Storage requirement & save some configuration setting so that codeigniter recognizes which database we want to work on.
2. Model: describe the database accessing logic (called business logic, it’s where the real business goes, your data will be your business & you’ll build logic over this business) – CRUD – create, retrieve, update, delete actions, in Models of the codeigniter
3. Controller: use the Controller to access data from the Model & pass them to View so that it can display them.
4. View: Create a simple View with HTML forms, that helps user with CRUD operations
5. Test

1. Create Database named ci_test going to http://localhost/phpMyAdmin, click on this database, there are zero tables yet.  copy paste the table structure by going to SQL link. and Go.

CREATE TABLE IF NOT EXISTS `bookmarks` (
  `bookmark_id` int(11) NOT NULL AUTO_INCREMENT,
  `url` varchar(255) NOT NULL,
  `description` text NOT NULL,
  `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`bookmark_id`),
  UNIQUE KEY `url` (`url`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 ;

http://localhost/phpMyadmin Interface: Create table from SQL

You created your database & table.

Open application/config/database.php and change as followings

$db['default']['hostname'] = "localhost";  //hostname
$db['default']['username'] = "root";          //default user name in local dev environment
$db['default']['password'] = "";                 //default password is blank
$db['default']['database'] = "ci_test";       //our database
$db['default']['dbdriver'] = "mysql";          //we are going to use MySql database

leave others as default for now. Now you told codeigniter to use our database in the application we are going to build.

2. Defining Model (a PHP class that’ll wrap our relation database model to Object Oriented style)

Here Bookmarks_Model  is a  PHP class, file name bookmarks_model.php & with some methods inside it inside the Models folder,
filename: Application/Models/bookmarks_model.php
the relation between file name & class name is
classname = ucfirst($filename)  without .php extension ok //first letter uppercase

it will look like this

 

<?php
class Bookmarks_model extends Model {

    var $url   = '';
    var $description = '';   

    function Bookmarks_model()
    {
        // Call the Model constructor
        parent::Model();
    }
    function get_last_ten_entries()
    {
        $query = $this->db->get('bookmarks', 10);
        return $query->result();
    }

    function save($u,$d)
    {       
        $this->url = $u;
        $this->description = $d;               
        $this->db->insert('bookmarks', $this);       
    }
    function delete($id)
    {       
        $this->db->where('bookmark_id', $id);
        $this->db->delete('bookmarks');        

    }

    function update_entry()
    {
        $this->url  = $_POST['url'];
        $this->description = $_POST['desc']; 
        $this->db->update('bookmarks', $this, array('bookmarks_id' => $_POST['id']));
    }

}
?>

 3. Inside Controller

Here Hello is a  PHP class, file name helllo.php & with some methods inside it inside the controller folder. controller & function inside it are the only way user can interact with our system, that’s why we can say controller has control over the flow of the application, we’ll access this controller later as:  http://localhost/ci/index.php/hello and each function inside it as – see comment in the code.

The naming convention for filename & class name is
classname = ucfirst($filename)  without .php extension

filename: application/controllers/hello.php 

<?php

  class Hello extends Controller {
  function Hello()
    {       
        parent::Controller();
        $this->load->database();//load database library  
        $this->load->model('Bookmarks_model'); //load just defined model
    }

    function index($data='') { 
      //accessed from url when typed http://localhost/ci/index.php/hello
      $bookmarks=$this->Bookmarks_model->get_last_ten_entries();     
      //call the function inside model which returns last ten entries
      $data['bookmarks']=$bookmarks;                  
      //create $data array with the values returned from the model function
      $this->load->view("hello_view",$data);
      //load the view named hello_view.php passing $data to it.
    }

    function save()
    {     
     //accessed from url when typed http://localhost/ci/index.php/hello/save
     //retrieve data from the form post method
     $u=$this->input->post('url');    
     $d=$this->input->post('desc');            
     //check for validity
    if ($u==''&& $d==''){       
        echo "Invalid, Entry";               
    }
    else{       
    //if valid data, call the function of the model which will save our data
    //to database   
     $this->Bookmarks_model->save($u,$d);   
     echo "Thanks, Link Added!";        
    }
  }
  function del($id)
    {
    //del function is receiving data from URL
    //accessed from url when typed http://localhost/ci/index.php/hello/___id___
    //___id___ is the promary key of the data   
    //delete data by passing primary key  
    $this->Bookmarks_model->delete($id);
    echo "Thanks, Link Deleted!";                
  }
  }
?>

4. the view
no naming convention for a view. build your own but you should make it easier to link your controller action to view memorable. just remember you’ll load (like used to include) views using filename without extension in controller. if you like extension see user guide for more $this->load->view options.

filename: application/views/hello_view.php 

<h1>Bookmark Manager </h1>
//simple php for each loop to iterate throug our data
//remember $bookmarks was passed from the controller as index of the $data variable, which is accessed here as an array of object.
//if you want to view the structure of the $bookmarks array uncomment the line below this.
//print_r($bookmarks);
//initially the array will be blank, but will show it’s structure after you add some data using the form.

<?php foreach($bookmarks as $b) : ?>

<?php echo $b->description;?><br>
<a target='_blank' href='<?php echo $b->url;?>'><?php echo $b->url;?></a>
<a href='<?php echo base_url() .'hello/del/'. $b->bookmark_id;?>'> Del</a>
<hr>
<?php endforeach; ?>
<br><br>

//html form to help add data to the database

//the action of the form is defined as the save method of the hello controller.
// base_url() function gives the root path of this project
//defined in application/config/config.php as
//$config['base_url']    = http://localhost/ci/index.php/;

<form method="post" action="<?php echo base_url() .'hello/save'; ?>">
Url:<input type='text' name='url' > <br>
Description:<input type='text' name='desc' > <br>
<input type="submit" value="Add">
</form>

5. Now go test the application you just created.

 


Let’s memories $data flow in Codeigniter once

Model –  to – Controller – to – View   flow i.e.
from database to – [ PHP code to/Data Manipulation ] – HTML presentation

1. Go through the user guide, remember this, when you see the terms Model, View & Controller – you just keep focused in the PHP Classes inside  the folders named Models, Controllers & Views within the system/application folder of the codeigniter.

 

ci-mvc

Model – PHP files, each file, each class for each table in database or group as you like, application/models,
View – PHP files, each file, presentation for actions(methods/functions) in controller, application/views
Controller - PHP files, each file, each class that control application flow, application/controllers

2. when they say, build a model for your database, think that you are going to create PHP files, each for each table.. etc…  with a class with some function to access database (using SQL queries or ORM/object relation mapper or plane SQL) & return these data to controller as array or objects like you used to return 0;  in C/C++ main functions.

function get_last_ten_entries()
    {
       //codeigniters default ORM activerecord’s way to retrive data
       //produces sql like -- select * from bookmarks limit 10
        $query = $this->db->get('bookmarks', 10);
        return $query->result();//return data to calling function from controller, returns objects array
    }

3. When they say access data from the model – you’ll be calling from controller or view a function inside a codeigniter models php file to retrieve data from the database. like this.

//load model like you use to include dbconfig.php or whatever, wherever in controller you need
$this->load->model('Bookmarks_model');
//use the function inside it through the loaded model instance
$bookmarks=$this->Bookmarks_model->get_last_ten_entries();   //an object array  

data returned from model is stored invariable $bookmarks

4. when they say, pass data to the view, you’ll be using a simple codeigniter function to pass data to a function which is used to load view (php files inside the views folder).

why you accessed data in controller? obviously to display or act upon it: so let’s pass it to view that handles our display system, no data manipulation for now.

//create $data array with the values returned from the model function
$data['bookmarks']=$bookmarks;                  

//load the view named hello_view.php passing $data to it.
$this->load->view("hello_view",$data);

5. When they say, design/markup a view? you are going to add some PHP files in the Views folder, name it as you like but keep the name in order so that it’ll be easier to reference later which controller is calling which view??

//you passed the variable bookmarks from step 3(controller), to step 5 (view) in summary just above. now access it & display it.
<?php
foreach($bookmarks as $b) :?>
echo $b->description;
echo ‘<br>’;
echo $b->url;<hr>
endforeach;
?>

Hope this helps you to start out with CodeIgniter, you are ready to explore on your own now. 
Regards.

Sunday, May 2, 2010

Social Network Database Design Sample - MySQL

what?
------
sample database for a social network project – a mysql database schema
Database Engine: InnoDB (edit the mwb file if you need to change it to MyISAM or any other.)
the aspects of a social network i tried to cover in this database:
- user profile
- friends
- friends list
- status updates
- thumbs up/down status (these can be easily ported to other entities)
- bookmark saving
- rss/atom feeds saving
- notifications
- chat
- blog, site level not user level

user

- privacy
profile
why?
------
you can use these files for beginning a social n/w type projects in PHP/MySQL development environment.
when i was doing social network project, i searched here & there for database design of a social network, but what i found in the internet were not useful. they provided a introductory sketch about social network database structure but but as i had a limited  time frame for my project, those materials were not useful. i have analyzed most of the basic requirements for a  social network database structure, and sharing this with you so that it would save some of your time to start out your project. 
statusthe database is not completely normalized yet but you can edit it as per your needs. don't waste to much time on what  fields should i use for profile or for a status representation, these entity sets in the design will suffice in most of the cases. You can add entities for pictures, video, music sharing or anything you like. Just use the workbench design file.






Here are few books i'd recommend if you are willing to dive deep into MySQL and database designs

1. Beginning MySQL Database Design and Optimization: From Novice to Professional
or
2. High Performance MySQL: Optimization, Backups, and Replication

files included
-----------------
following files are included
sns.7.0-.mwb - MySql WorkBench Design
sns.7.0.png - exported PNG from MySql workbench
sns7.0.sql - exported SQL from MySql Workbench
sns.yml - Doctrine Generated schema in YAML
you can use the MySQL WorkBench Designer available Open Source at http://wb.mysql.com & begin with the mwb file,
change it for your need, export to sql & use it for your project.
Download MySQL Social Network Database Design – Sample

Update 11/14/2011:
Many readers have requested how the project ended up in look.
So, here goes the slide we presented to Tribhuvan University (with formal details cut out).
Thanks for reading this post.

TimiHami a Nepali Social Network