Category: PHP

How not to do a CI controller? – Tips to develop CodeIgniter Controllers

Posted by – December 11, 2011

I cam across a post that was actually a small tutorial on CodeIgniter. The tutorial had what ever it requires to write a basic controller. I am picking up the same post and adding my comments to the post.

The original post – http://phpmaster.com/untangling-mvc-with-codeigniter/

The controller

<?php
public function index() {
    $this->load->helper("form");
    $this->load->library("form_validation");

    $this->form_validation->set_rules("first", "First Name",
        "required");
    $this->form_validation->set_rules("last", "Last Name",
        "required");
    $this->form_validation->set_rules("email", "Email Address",
        "required|valid_email");

    if ($this->form_validation->run() == false) {
        $this->load->view("phpmasterform_view");
    }
    else {
        $first = $_POST["first"];
        $last = $_POST["last"];
        $email = $_POST["email"];
        $data = array("first_name" => $first,
                      "last_name" => $last,
                      "email" => $email);

        $this->load->model("phpmasterform_model");
        $this->phpmasterform_model->insert_address($data);
        $this->load->view("formsuccess");
    }
}

What is wrong with this Controller?
The controller doesn’t utilises the full powers of a framework. Any decent framework or a develop methodology will suggest you to move configurations to a separate place. CI has configuration settings for almost everything. The configuration folder is easily identifiable and path isĀ /application/config. In this folder is file autoload.php. This file is commented and is self explanatory. I will move the form helper and form_validation library loading tasks to autoload.php. Read more about it here, Auto-loading Resources. Then in same config folder I will create another file named form_validation.php which will hold all my validation rules. This will be a centralised place to hold all the validation rules. I can easily modify just one file and change validation rules on my whim and fancy. Read more about this here, “Saving Sets of Validation Rules to a Config File“. All these were just small tips and one can read the manual and find more about them. But the biggest mistake I found in this controller was blindly consuming the user input. The commandment of web development says

Thy shalt never trust user input.

CI provides a Input Class library. This library is so important that CI loads it by default. So if you are using CI, use this library.
This was not the only possible security hole. If run through other files in CI, they all start with following line

if ( ! defined('BASEPATH')) exit('No direct script access allowed');

.
This restricts some one from directly accessing the file if path to that file is known.
After all this the controller is changed to following

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');
public function index() {
    if (false === $this->form_validation->run(feedback)) {
        $this->load->view("phpmasterform_view");
    }
    else {
/*
    if you have set following "$config['global_xss_filtering'] = TRUE;"in your 
    application/config/config.php then you don't need to pass 2nd param as 
    true in following three lines.
*/
        $first = $this->input->post("first", true);
        $last = $this->input->post("last", true);
        $email = $this->input->post("email", true);

        $data = array("first_name" => $first,
                      "last_name" => $last,
                      "email" => $email);

        $this->load->model("phpmasterform_model");
        $this->phpmasterform_model->insert_address($data);
        $this->load->view("formsuccess");
    }
}

Following is form_validation.php, this will go in application/config/ folder.

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

$config = array(
    'feedback' => array(
        array(
            'field' => 'first',
            'label' => 'First name',
            'rules' => 'required'
        ),
        array(
            'field' => 'last',
            'label' => 'Last name',
            'rules' => 'required'
        ),
        array(
            'field' => 'email',
            'label' => 'Email',
            'rules' => 'required'
        )
    ),
);

Last thing to do is to modify autload.php and load form helper and form validation library. This should give an idea how to develop a maintainable code in CI.
Happy coding!

M4 – My top secret learning project :-)

Posted by – June 5, 2011

Yahoo! is now going through a very tough time and is being ignored for mostly. There is hardly any attention being paid to Yahoo! products. I recently tried to play with Yahoo! Application Platform and YQL. One can develop web based and standalone applications using YAP SDK and YQL. These apps are more or less similar to Facebook Apps in architecture. I used YQL and quickly created a small site that fetches Sensex data and displays it. Please visit http://www.indianbizdirectory.com/.

The domain IndianBizDirectory.com was lying idle for more than 4-5 years. I ran a small example fetch weather data for Beverly using YQL console. The example is so simple and self explaining. I was encouraged and decided to use YQL in some real life stuff. I used CodeIgniter to set up a project. Codeigniter is my framework of choice for rapidly developing prototypes. I searched for some feeds and web pages for data and as usual Yahoo! and Google were there to help me. Apart from this I hooked up BSEIndia.com, NDTV.com, Bing.com and MoneyControl.com for data. Initially I decided to run real time calls to these data sources. I setup a very basic logger with CI that mailed me every time a call to any data source or feed failed. I asked my friends to start hitting my site. They hammered it for two weeks. It was slow. And occasionally the feed from BSEIndia.com was failing. I studied logs an realised that the speed was slow due to multiple calls, there were at least 4 to 5 calls to different data sources, were making the page slow. I decided to cache the data. This increased the speed. So

  • on every page load, CI checks if cache is available and loads it, if not then it updates cache for that particular data source/feed.
  • there is a background process that caches data for Sensex during trading hours. The cache is refreshed every 15 minutes.
  • there are chances that a feed may fail during the background process, in that case the process leaves the cache in its original state. The cache is updated by CI.

I found there that BSE feed failure log entries were reduced though the data was not real time. After fetching data I used Xpath to transform data into HTML. Result, I could develop a standalone self sustaining website that displays useful Sensex, Forex and Commodity data. One can see Sensex top looser and gainers, clicking on a scrip name shows further detail about that scrip. On top of it, I added Bing search to fetch and display news related to that particular scrip. All in all, it was a great experiment and learning.

To monetize this effort, I added Google Ads on all pages. I wanted to add more ads but don’t have experience with other platforms.

After this, I am planning to dirty my hands with Python, PyGTK specifically to solve a problem I usually face. :-)

Method chaining

Posted by – October 2, 2010

I love the way CodeIgniter explains method chaining by saying.

Method chaining allows you to simplify your syntax by connecting multiple functions.

As explained above it simply lets you do things like

FileObject->OpenFile('FileName')->AppendLine('Hello World!')->CloseFile()

Its neat. But in PHP, you have to have PHP5.x. This wonderful thing is also available in JavaScript. From jQuery home page

$("p.neat").addClass("ohmy").show("slow");

How to do method chaining?
To have an object chain methods every method in that object must return a reference to itself. Easy. Example?

<?php
class MethodChainingExample{
	public function methodOne(){
		echo __METHOD__." \n";
		return $this;
	}
	public function anotherMethod(){
		echo __METHOD__." \n";
		return $this;
	}
	public function oneMoreMethod(){
		echo __METHOD__." \n";
		return $this;
	}
}
$example =  new MethodChainingExample;
$example->methodOne()->anotherMethod()->oneMoreMethod();

Hello World in CakePHP – 3 steps

Posted by – April 13, 2010

  1. Download and set up CakePHP in your webroot. Stop reading further if you cant do it or you are not sure how to do it.
  2. Create a file named “helloworld_controller.php” in folder “cakephp/app/controllers/helloworld_controller.php” and paste following code in the file
    <?php
    class HelloWorldController extends Controller {
    public $name = 'HelloWorld'; //Controller name, we need it.
    public $uses=null; //The example doesn't "use" any model.
    public $autoRender=false; //Do not render "automagically"
    public function index() {//The default action for a CakePHP controller
    echo __METHOD__;//This will print HelloWorld suffixed with some more info ;-)
    }
    }
  3. Point your browser to CakePHP installation on your server for example “http://localhost/cakephp/helloworld/”

Piece of cake… :-)

Error Reporting

Posted by – March 25, 2009

PHP has come a long way. I used to program with Global vars then $HTTP_POST_VARS and then $_POST and even did a foreach to convert all Posted/Get-ed vars to their respective variable names. But I never faced any issue till the time I started using error_reporting(E_ALL).
My life changed. Initially I started pulling my hairs and then I realised that I will be bald very soon and then started concentrating on writing better code. Avoiding on the fly variables. Yesterday at work, I again realised the value of error_reporting(E_ALL).I created a small piece of code and tested it in a temp php file. It looked superb. I ported the code to production environment and it started breaking. I thought for a while. May be I have introduced some parse errors. I ran a php -l test and didnt see any syntax error. I read the whole code line by line. Even did a diff. Still the temporary php code was running fine and the code in production environment was not working fine. :-/

I decided to look at the code bit later. After a break of 15 minutes I decided to write a unit test and capture everything. And then I found a notice message telling me I was accessing an index that didn’t exist. I looked at my data set. It was a long range of number, 6184 to be precise and an index value 280 was not set. I looked at my temp file and found my code was not going thru error reporting and production environment was set up to halt at all notices and warnings. Damn it!