Matt McCormick

Safely Change Database Columns in Yii Framework

Posted on September 20, 2012 ·1

Note: This post refers to Yii Framework version 1.1.11

Let’s say you have an existing web application that uses Yii framework. For some reason, you would like to go about changing some column names in your database tables. Recently I went through this process because some tables in our application were using title and others were using name. I wanted to standardize them all to name.

Changing column names can be a pain because, if you are making use of CActiveRecord, you probably have many in places in the code that refer to the attribute directly such as:

$model->title;

Finding all the references and updating them could be quite time consuming depending on the size of your application.

Luckily, because of the way Yii accesses attributes, it is quite painless to change column names in a way that ensures any existing references do not break.

Let’s take a look at how you could go about changing the column title to name by first taking a look at what is happening when you call $model->title.

Yii makes use of the PHP magic methods to access attributes directly.

In the CActiveRecord class we have the __get() method:

	public function __get($name)
	{
		if(isset($this->_attributes[$name]))
			return $this->_attributes[$name];
		else if(isset($this->getMetaData()->columns[$name]))
			return null;
		else if(isset($this->_related[$name]))
			return $this->_related[$name];
		else if(isset($this->getMetaData()->relations[$name]))
			return $this->getRelated($name);
		else
			return parent::__get($name);
	}

When you try to access a property of the object, Yii will first check to see if it is an attribute. If is not an attribute, and not a relation, the call will be passed up the chain to CComponent.

	public function __get($name)
	{
		$getter='get'.$name;
		if(method_exists($this,$getter))
			return $this->$getter();
		else if(strncasecmp($name,'on',2)===0 && method_exists($this,$name))
		{
			// duplicating getEventHandlers() here for performance
			$name=strtolower($name);
			if(!isset($this->_e[$name]))
				$this->_e[$name]=new CList;
			return $this->_e[$name];
		}
		else if(isset($this->_m[$name]))
			return $this->_m[$name];
		else if(is_array($this->_m))
		{
			foreach($this->_m as $object)
			{
				if($object->getEnabled() && (property_exists($object,$name) || $object->canGetProperty($name)))
					return $object->$name;
			}
		}
		throw new CException(Yii::t('yii','Property "{class}.{property}" is not defined.',
			array('{class}'=>get_class($this), '{property}'=>$name)));
	}

We only need to concern ourselves with the first few lines of this method. It says if a method exists that starts with ‘get’, in our case this would be getTitle() then it will return the return value from that method. Set works similarly as Yii implements __set() as well. I won’t post the code for it but you can have a look if you are interested.

Knowing this, it is easy to rename our columns without having to touch any existing code.

In your model class we just need to add a couple of very simple methods:

	public function getTitle()
	{
		return $this->name;
	}

	public function setTitle($name)
	{
		$this->name = $name;
	}

That’s it! Our existing code will continue to function as normal. Any call to $model->title will be handled by the getTitle() method which now will return the name attribute.

It would be good idea to write a few unit tests to make sure it is working properly in your application.

Alternatively, if you have columns in many tables that are being renamed in the same manner, you can refactor the above code into a Behaviour to avoid code duplication.

I should point out that this only works for code where you are directly referencing the attribute as a property. If you refer to the column name elsewhere, such as in the rules() or relations() methods or directly in SQL you will need to change those manually. So it is still a good idea to do a search through your code but implementing the above methods should help substantially to decrease the time it takes to rename columns.

Categories: programming · Tags:

Unit Testing URL Routes in Yii Framework

Posted on September 14, 2012 ·1

(This post refers to Yii Framework v.1.1.11)

Let’s say you have a bunch of custom URL routes setup in your configuration file for Yii. Since custom URL routes can quickly become complicated due to regular expression matching, it’s a good idea to have some tests in place to make sure that your URLs are getting sent to the correct controller and action.

Unfortunately, Yii is a little too tightly coupled for my taste. This makes it difficult to test something like this. Routes are one of the main parts of any web application out there and should be standard to write unit tests for them. This is one of the downfalls of the Yii framework and could be improved.

It takes a bit of digging through the Yii Framework code to figure out how to test URL routes. Let’s walk through and see how you can setup your own URL route tests.

In your configuration file, under the key ['components']['urlManager']['rules'] we’ll assume you have the following RESTful routes setup:

array('<controller>/view', 'pattern' => '<controller:\w+>/<id:\d+>', 'verb' => 'GET'),
array('<controller>/create', 'pattern' => '<controller:\w+>', 'verb' => 'POST'),
array('<controller>/update', 'pattern' => '<controller:\w+>/<id:\d+>', 'verb' => 'PUT'),
array('<controller>/delete', 'pattern' => '<controller:\w+>/<id:\d+>', 'verb' => 'DELETE')

This says that any GET request matching /word/ID, where “word” is the name of the controller and ID is a number, will be redirected to that controller’s view action. A PUT request to the same URL would be handled by the update action and a DELETE request would be handled by the delete action. A POST request to /word will be handled by the create action. There is no need for the ID because we are creating a new object.

Now that we have our routes setup, let’s move on to testing them. I’ll assume you have something like a UserController that contains these four actions.

Under the /protected/tests/unit/ directory, add a file named UserControllerTest.php which contains the following:

class UserControllerTest extends CDbTestCase
{
	public function testViewRouteResolves()
	{
	
	}
}

Note: This tutorial assumes you already have PHPUnit setup for testing your Yii application. Setting up your testing framework is outside the scope of this article. See the Yii tutorial if you need guidance.

The first problems you should be thinking about solving are:

1) How do I tell Yii what URL I want to test?
2) How do I get the controller and action from Yii that it will redirect to?

Let’s walk through the Yii initialization code. This will help you get familiar with what is going on behind the scenes.

You should have a type of bootstrap file which contains something along the following lines:

Yii::createWebApplication($config)->run();

This is the main call to run the application. $config refers to an array of configuration items that was mentioned earlier.

If you follow the code and open up the CApplication::run() method, you will see the following:

if($this->hasEventHandler('onBeginRequest'))
	$this->onBeginRequest(new CEvent($this));
$this->processRequest();
if($this->hasEventHandler('onEndRequest'))
	$this->onEndRequest(new CEvent($this));

We’re only concerned with the highlighted line. processRequest() is an abstract method which means it will be handled in the inherited class.

In CWebApplication::processRequest(), we see the following code:

public function processRequest()
{
	if(is_array($this->catchAllRequest) && isset($this->catchAllRequest[0]))
	{
		$route=$this->catchAllRequest[0];
		foreach(array_splice($this->catchAllRequest,1) as $name=>$value)
			$_GET[$name]=$value;
	}
	else
		$route=$this->getUrlManager()->parseUrl($this->getRequest());
	$this->runController($route);
}

We’re only concerned with the part after the else statement as we are not using a catch-all request. Line 10 says that, in order to get the route, Yii will use the UrlManager::parseUrl() method and pass in the Request object. So let’s take a look at that next:

public function parseUrl($request)
{
	if($this->getUrlFormat()===self::PATH_FORMAT)
	{
		$rawPathInfo=$request->getPathInfo();
		$pathInfo=$this->removeUrlSuffix($rawPathInfo,$this->urlSuffix);
		foreach($this->_rules as $i=>$rule)
		{
			if(is_array($rule))
				$this->_rules[$i]=$rule=Yii::createComponent($rule);
			if(($r=$rule->parseUrl($this,$request,$pathInfo,$rawPathInfo))!==false)
				return isset($_GET[$this->routeVar]) ? $_GET[$this->routeVar] : $r;
		}
		if($this->useStrictParsing)
			throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
				array('{route}'=>$pathInfo)));
		else
			return $pathInfo;
	}
	else if(isset($_GET[$this->routeVar]))
		return $_GET[$this->routeVar];
	else if(isset($_POST[$this->routeVar]))
		return $_POST[$this->routeVar];
	else
		return '';
}

The highlighted lines are where the route is calculated. First, the path is figured out which comes from the Request object. For our purposes, it is important to take a look at it in order to figure out how we can tell Yii which URL we want to test.

CHttpRequest::getPathInfo()

	public function getPathInfo()
	{
		if($this->_pathInfo===null)
		{
			$pathInfo=$this->getRequestUri();

			if(($pos=strpos($pathInfo,'?'))!==false)
			   $pathInfo=substr($pathInfo,0,$pos);

			$pathInfo=$this->decodePathInfo($pathInfo);

			$scriptUrl=$this->getScriptUrl();
			$baseUrl=$this->getBaseUrl();
			if(strpos($pathInfo,$scriptUrl)===0)
				$pathInfo=substr($pathInfo,strlen($scriptUrl));
			else if($baseUrl==='' || strpos($pathInfo,$baseUrl)===0)
				$pathInfo=substr($pathInfo,strlen($baseUrl));
			else if(strpos($_SERVER['PHP_SELF'],$scriptUrl)===0)
				$pathInfo=substr($_SERVER['PHP_SELF'],strlen($scriptUrl));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the path info of the request.'));

			$this->_pathInfo=trim($pathInfo,'/');
		}
		return $this->_pathInfo;
	}

We’re getting closer now! Line 5 indicates where Yii gets the request URI from. So let’s take a look at CHttpRequest::getRequestUri():

	public function getRequestUri()
	{
		if($this->_requestUri===null)
		{
			if(isset($_SERVER['HTTP_X_REWRITE_URL'])) // IIS
				$this->_requestUri=$_SERVER['HTTP_X_REWRITE_URL'];
			else if(isset($_SERVER['REQUEST_URI']))
			{
				$this->_requestUri=$_SERVER['REQUEST_URI'];
				if(!empty($_SERVER['HTTP_HOST']))
				{
					if(strpos($this->_requestUri,$_SERVER['HTTP_HOST'])!==false)
						$this->_requestUri=preg_replace('/^\w+:\/\/[^\/]+/','',$this->_requestUri);
				}
				else
					$this->_requestUri=preg_replace('/^(http|https):\/\/[^\/]+/i','',$this->_requestUri);
			}
			else if(isset($_SERVER['ORIG_PATH_INFO']))  // IIS 5.0 CGI
			{
				$this->_requestUri=$_SERVER['ORIG_PATH_INFO'];
				if(!empty($_SERVER['QUERY_STRING']))
					$this->_requestUri.='?'.$_SERVER['QUERY_STRING'];
			}
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the request URI.'));
		}

		return $this->_requestUri;
	}

Finally we can see that if the $_SERVER['REQUEST_URI'] value is set, Yii will use that value as the URL route. ($_SERVER['HTTP_X_REWRITE_URL'] would also work as well.)

Going back to CHttpRequest::getPathInfo(), also see that I’ve highlighted the call to CHttpRequest::getScriptUrl(). This is important because we are running PHPUnit from the command line and not through an ordinary URL request. Looking at the code we see:

	public function getScriptUrl()
	{
		if($this->_scriptUrl===null)
		{
			$scriptName=basename($_SERVER['SCRIPT_FILENAME']);
			if(basename($_SERVER['SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['SCRIPT_NAME'];
			else if(basename($_SERVER['PHP_SELF'])===$scriptName)
				$this->_scriptUrl=$_SERVER['PHP_SELF'];
			else if(isset($_SERVER['ORIG_SCRIPT_NAME']) && basename($_SERVER['ORIG_SCRIPT_NAME'])===$scriptName)
				$this->_scriptUrl=$_SERVER['ORIG_SCRIPT_NAME'];
			else if(($pos=strpos($_SERVER['PHP_SELF'],'/'.$scriptName))!==false)
				$this->_scriptUrl=substr($_SERVER['SCRIPT_NAME'],0,$pos).'/'.$scriptName;
			else if(isset($_SERVER['DOCUMENT_ROOT']) && strpos($_SERVER['SCRIPT_FILENAME'],$_SERVER['DOCUMENT_ROOT'])===0)
				$this->_scriptUrl=str_replace('\\','/',str_replace($_SERVER['DOCUMENT_ROOT'],'',$_SERVER['SCRIPT_FILENAME']));
			else
				throw new CException(Yii::t('yii','CHttpRequest is unable to determine the entry script URL.'));
		}
		return $this->_scriptUrl;
	}

It is important that we make a note of these variables because if we don’t set them like it was an actual URL request, Yii wouldnot be able to parse the route correctly. If you want to delve in deeper, you can try to figure out why we need to override these variables but I’ve already gone deep enough in this tutorial and this should be good enough to move on.

Jumping back to the CWebApplication::processRequest() method, we see that after the route has been determined, Yii runs the controller. Let’s take a look at our final Yii method, CWebApplication::runController()

	public function runController($route)
	{
		if(($ca=$this->createController($route))!==null)
		{
			list($controller,$actionID)=$ca;
			$oldController=$this->_controller;
			$this->_controller=$controller;
			$controller->init();
			$controller->run($actionID);
			$this->_controller=$oldController;
		}
		else
			throw new CHttpException(404,Yii::t('yii','Unable to resolve the request "{route}".',
				array('{route}'=>$route===''?$this->defaultController:$route)));
	}

We see that Yii calls createController() which returns an array where the controller is the first value, and the action is second. For our purpose, we don’t need to know how it does it but we’ll use this method to our advantage.

Now we have enough information about Yii that we can put our test together. Jumping back to our UserControllerTest class, we can add the following lines:

$_SERVER['SCRIPT_FILENAME'] = 'index.php';
$_SERVER['SCRIPT_NAME'] =  '/index.php';
$_SERVER['REQUEST_URI'] = 'user/1';

The first two lines fool Yii into thinking this is a normal request coming through the index.php file. With mod_rewrite turned on, every request is first funnelled through the index.php file to setup the Yii application.

Next, we set the $_SERVER['REQUEST_URI'] variable to the route we want to test because we know Yii will use this later on.

$route = Yii::app()->getUrlManager()->parseUrl(new CHttpRequest());

list($controller, $action) = Yii::app()->createController($route);

Next we use the CUrlManager::parseUrl() method to get the route. I’ve passed in a new CHttpRequest object because it doesn’t really matter in this case. You could also use Yii::app()->getRequest() as well. We also use the CWebApplication::createController() method just like Yii does to get an instance of the controller and the action. It’s important to note here that $controller will contain an object while $action contains a string of the action to be called.

Finally, we can add our assert calls.

$this->assertInstanceOf('UserController', $controller);
$this->assertEquals('view', $action);

All in all, this will assert that the route ‘user/1′ is handled by the view action from the UserController.

There you have it. You are now able to test your routes in Yii. In my codebase, I have refactored most of the code into an abstract class that acts as a parent to UserControllerTest.

One other point. In order to test the other request methods – POST, PUT and DELETE – you will need to set it explicitely. This is done by:

$_SERVER['REQUEST_METHOD'] = 'POST';

In the end, our full test looks like:

public function testViewRouteResolves()
{
	$_SERVER['SCRIPT_FILENAME'] = 'index.php';
	$_SERVER['SCRIPT_NAME'] =  '/index.php';
	$_SERVER['REQUEST_URI'] = 'user/1';

	$_SERVER['REQUEST_METHOD'] = 'GET';

	$route = Yii::app()->getUrlManager()->parseUrl(new CHttpRequest());

	list($controller, $action) = Yii::app()->createController($route);

	$this->assertInstanceOf('UserController', $controller);
	$this->assertEquals('view', $action);
}

It should be easy to use this code as a starting point to test your other actions.

Categories: programming · Tags: ,

How to use Zend Framework’s ResultSet class with Yii Framework

Posted on September 7, 2012 ·2

Note: This post refers to Yii Framework version 1.1.11 and Zend Framework version 2.0.0

I’ve been working with the Yii Framework for about six months now. While it’s decently designed there are a few points that bother me about it. My favourite PHP framework that I’ve worked with is Zend Framework so this post is a little biased towards it. I find Zend Framework extremely well-designed and thought out. It’s not for beginners and there is a bit of a steep learning curve. I wouldn’t consider it a rapid development framework but it helps keep code very clean when dealing with larger systems.

One of things I find missing the most from Zend when working in Yii is the ResultSet object (previously the Rowset class in Zend v1.x). Yii has the ActiveRecord class for holding individual records that are returned from the database but if a query returns multiple rows, the objects are just stored in an array. This makes things difficult if I want to be able to manipulate the results or convert them to a specific JSON object.

To remove this annoyance, I did the best thing I could think of – I altered the ActiveRecord class to use ResultSet’s for multiple records that are returned.

To do this, you first need to add the Zend Framework library code to the application. Yii recommends placing 3rd-party library code under the /protected/vendors directory so add the Zend/ directory there.

You will need to make sure this is added to the application’s path. Your setup may vary, but for the app I’m working on, we have a configuration file and I added Zend to the aliases key like the following:

...
'aliases' => array(
	// ...
	'Zend' => realpath(__DIR__.'/../vendors/Zend/'),
	// ...
),

This example assumes your configuration file is in the /protected/config/ directory.

After this, Zend Framework is ready to use within Yii.

To get Yii to convert arrays of records into a ResultSet, you will need to override some methods in the CActiveRecord class. In our application, we have a ActiveRecord class that inherits from the CActiveRecord to provide custom functionality needed for our app.

Unfortunately, Yii does not provide a single method that handles returning a rowset. There are three methods that need to be overwritten:

- CActiveRecord::getRelated()
- CActiveRecord::findAllBySql()
- CActiveRecord::query()
- CActiveRecord::__get()

The getRelated() handles the logic for getting related records. Any data resulting from relationships such as one-to-many, many-to-many, etc. are processed through this method before being returned.

The query() method is called as the final step by most of the findX() methods – find(), findAll(), findByPk() and findByAttributes().

The findAllBySql() method needs to be overwritten separately because it (along with findBySql()) does not use the query() method.

__get() is a magic method that needs to be overwritten for instances where the Result Set data is saved as an array in the object to avoid hitting the database on subsequent calls in the same request.

Even though we are overwriting the query() method which also handles single ActiveRecord objects, we will add logic to prevent altering them.

Since the code we want to use will be the same for all methods, we can extract it into a private method to avoid code duplication. Therefore, all the methods that we are overwriting simply need to call the parent method and then call our private method which I have named getResult().

public function getRelated($name,$refresh=false,$params=array())
{
	$related = parent::getRelated($name, $refresh, $params);
	return $this->getResult($related);
}

public function findAllBySql($sql,$params=array())
{
	$resultSet = parent::findAllBySql($sql, $params);
	return $this->getResult($resultSet);
}

protected function query($criteria,$all=false)
{
	$query = parent::query($criteria, $all);
	return $this->getResult($query);
}

public function __get($name)
{
	$hasRelated = $this->hasRelated($name);
	$result = parent::__get($name);
	if ($hasRelated) {
		return $this->getResult($result);
	}
	return $result;
}

Notice that the method signatures have all stayed exactly the same as the parent signatures. If you are overriding a method, it’s important to keep the signatures the same, especially a framework method, as you will most likely get errors when they are called incorrectly.

Finally, we can write our getResult() method.

/**
 * Converts the result into a ResultSet if it contains multiple records
 * Leaves an ActiveRecord untouched
 * @param array|ActiveRecord $dataSource
 * @return \Zend\Db\ResultSet\ResultSet|ActiveRecord
 */
private function getResult($dataSource)
{
	if (is_array($dataSource)) {	// assuming a ResultSet
		$resultSet = new \Zend\Db\ResultSet\ResultSet();
		$resultSet->initialize($dataSource);

		return $resultSet;
	}

	return $dataSource;
}

As you can see, this method will only return a ResultSet if $dataSource is an array. If it is something else, for example a User ActiveRecord object, it will be returned as is.

In my actual code, I have extended the \Zend\Db\ResultSet\ResultSet class with my own app-specific class to provide further logic that is specific to my application. But this can be an exercise for the reader.

In summary, although Yii does not offer it’s own class for handling result sets, it’s easy to either write your own or use a 3rd-party library to do so as we did in this case.

Categories: code · Tags: ,

Your Controllers need to lose weight

Posted on September 4, 2012 ·0

Most software developers have probably heard of the design principle “Fat Models, Skinny Controllers” but I constantly come across code that doesn’t follow this principle. How skinny is skinny? Properly designed controllers should not have more than a few lines of code. For most actions, if you have more than four lines in the method, that should be an indication that there is a better way to do something.

Let’s take a look at some code working with a delete() action.

Many URLs follow a RESTful setup. In this example, I’m assuming a URL structure like /model/$id/action.

For example, using Yii Framework, this would be my delete action for a VideoController:

public function actionDelete($id)
{
	$success = $this->model->delete();
	$this->sendAjaxResult($success, 'Deleted video', 'The video could not be deleted');
}

This is just two lines of code. Most standard actions need to follow the format of:
- load the appropriate object
- perform the action on the object
- send data back to the view with the result

In this case, the “view” is an AJAX response.

In this example, there is no code indicating that the object is being loaded. So how is that being accomplished?

Many PHP frameworks have an init() method available for controllers where you can specify code that should be run before the action. From the name, init you can tell that this should mainly be used for initializing variables.

In my Controller class I have the following:

class Controller extends CController 
{
	/**
	 * @var ActiveRecord
	 */
	protected $model;

	public function init()
	{
		$this->model = $this->loadModel();
		parent::init();
	}

There is a variable $model which stores the current object to be acted upon. This is loaded through the loadModel() method which takes the $id, figures out the name of the model with a little bit of magic (ie. for ‘VideoController’ the model would be assumed to be ‘Video’) and stores it in the $model attribute. Since $model is protected, it can be accessed by child classes.

What if there is no ID? For example, the index page of /video may just contain a list of videos. Ah you got me. It’s good to see you’re thinking ahead.

My actual init() method looks like this:

public function init()
{
	if (Yii::app()->getRequest()->getParam('id')) {
		$this->model = $this->loadModel();
	}

	parent::init();
}

So loadModel() will only be called if the ID parameter is available in the URL. In the index action scenario, $model would be null and could not be acted upon.

Going back to the controller action, the delete() method on the object performs all the work. I won’t include the code here but you should push back all code into the object’s class (ActiveRecord in Yii, Zend_Db_Table_row in Zend Framework, etc.) so that you just need to call one method from the controller action.

The second line, $this->sendAjaxResult() performs some processing which sends back the response via AJAX. For standard rendering, many PHP frameworks provide a render() method for the controller to render a view and set data. This is a common scenario that the last line would be calling render() if it is not done automatically after the action.

What about authorization?

Good question. You’re still following along. Authorization needs to be performed before you even get to the action. If a user does not have access to the action, the processing should never even reach the action code. If you are putting authorization logic in the action code, that is another indicator that things need to be cleaned up.

In Yii Framework, for example, you can override the filters() and accessRules() methods in your controller. In my VideoController class, I have the following:

public function filters()
{
	return array(
		'ajaxOnly + delete',
		'deleteOnly + delete',
		'accessControl',
	);
}

public function accessRules()
{
	return array(
		array('allow', 'actions' => array('delete'), 'expression' => array($this->model, 'isModerator')),
		array('deny')
	);
}

NOTE: This is just an example for Yii Framework. Other frameworks would handle authorization differently.

In this example, the filters() method is run first. Each value of the array will be checked to make sure that this action matches the filters. So the delete action must be called via AJAX and must be a DELETE request, as opposed to a GET or POST request. If those filters pass, then accessControl is called which makes use of the accessRules() method.

This method also returns an array which is pretty easy to follow along. Each value of the array is checked for the first match that returns true. In this case, the first value indicates that the user is allow ed to perform the delete action if the expression $this->model->isModerator() returns true. I won’t provide the code for that method, but as you can guess it checks to make sure that the current user is a moderator for the video and thereby has the ability to delete it.

If that access rule is false, then Yii will check the next one which is simply deny. For authorization, it is a good idea to deny access to anything you haven’t explicitly given access to. This is a good rule of thumb for security – deny everything and then slowly open up access one by one.

The other benefit of keeping authorization out of the action code, other than keeping skinny controllers, is that authorization and actions require two different trains of thought. When dealing with authorization, you should be thinking “Who needs access to this action and what special criteria do they need?” When writing the action code you should only be thinking about what action to perform and not be worrying about security. Separating authorization from the action is a good way to keep your mind focusing while programming and it should help reduce bugs.

So, in a nutshell, this is one example of how you can go about creating skinny controllers.

Let’s review the rules of thumb:

- actions should contain no more than a few lines of code
- push back logic into the model/ActiveRecord class
- initialize variables and attributes in an init() method before the action
- authorization logic should be performed before the action

Follow these principles and you can help your controllers lose weight!

Categories: programming · Tags: , ,

Forget Sunscreen….Focus

Posted on October 21, 2011 ·2

Focus. If I could offer you only one tip for the future, focus would be it.

In the next 20 years, we are going to face an extreme shortage of people who are able to focus single-mindedly on what they are doing. Children growing up these days face an onslaught of distractions thanks to news feeds and smartphones and it is only going to get worse.

Why is this a problem?

People cannot multi-task well. I know there will be many people who say they can, but they can’t – at least not on a task that requires concentration and focus. If you think multi-tasking is fine, answer me this: if you were going into surgery and saw your surgeon preparing while checking his mobile phone messages and watching TV, would you feel comfortable?

The ability to focus is a habit that can be trained or drained. Growing up in a distraction-oriented world, this will be a problem because the best work gets done when someone is focused on what they are doing.

When programming, my best days are when I don’t even check email until the end of the day. I have my tasks laid out and just start on them. When I need a break, I take a break but focus solely on the break during that time. Then when I am refreshed, I get back to work and focus just on the work. Days like these are bliss. I finish work feeling energized and enthusiastic.

The worst days are days I usually check email first thing in the morning. Immediately the distractions start. And even though I may check email only for a few minutes, it can throw me off for the rest of the day. On these days, I finish work feeling drained of energy and wondering what I got done.

My first full-time job after university was at a large, bureaucratic organization. As part of their IT policies, they blocked access to “time-wasting” sites like Gmail and Facebook. At the time, I thought this was a horrible, Orwellian thing to do. By restricting access, they were treating employees like children instead of trusting people to get their work done.

Now, I realise there is some benefit to this course of action (although it is better for people to figure it out for themselves – you can’t block every non-work essential website).

How to focus

What is focus? Focus is setting limits on yourself. In today’s world where most North Americans are in debt, setting limits is something that very few people do. The average person might even be annoyed at just the idea of setting a limit on themselves. Most people don’t even limit their spending to the income that they earn. After all, it benefits others when you don’t set limits on yourself. I hear advertisements all the time saying things like “Buy this. You deserve it.” I never hear an ad saying “Buy this if you have the money saved and can afford it.”

Luckily, the ability to focus can be improved just like any skill.

There are two parts to it – mental fitness and physical fitness

Mental Fitness

I meditate for 15 minutes a day in the morning. There are different kinds of meditation but for improving your focus, the best one I know of is just trying to focus on your breath and only your breath. Whenever another thought or sensation enters your mind, just picture a bubble or cloud forming around it and floating away while you come back to focusing on your breath.

It can be a very challenging activity. Currently, I can only last up to a few minutes before getting distracted without even realising it. However, improvement comes with practice.

After a couple weeks, you should start noticing that you are able to focus more while working. You will build up higher resistance to those thoughts that enter your mind throughout the day which tug at you saying “Let’s just check Facebook for a few minutes…” This will help you get more done in less time.

Physical fitness

It should go without saying but being physically fit helps you in so many areas of your life, focus being one of them. Your body can only expend so much energy at one time and if you are unhealthy, your body needs to spend more energy to keep your heart beating or your lungs breathing. The more energy your body uses keeping you alive, the less energy you have to expend on the task at hand.

As we get further along in the technological revolution, the focus divide between people is going to become more noticeable. If you want to set yourself apart from your peers, train and improve your ability to focus. While other people are distracting the day away, you will be able to accomplish more in much less time.

Focus.

Categories: Productivity, programming ·