the blog of ndungi kyalo

i write web apps, and i also write about writing web apps. if writing web apps is wrong, i dont wanna be write :-)

“Do not be afraid, It is I”

“But when he (Peter) saw that the wind was boisterous, he was afraid; and beginning to sink..” ~ Matthew 14:30


The passage above is from the Gospel account of Jesus walking on water, and Peter too soon after him. But Peter looked the raging winds and became afraid and began to sink. Fortunately, Jesus caught him before he could drown and saved him and asked him “Why did you doubt?”.

“But when he (Peter) saw that the wind was boisterous ..”  Winds are also mentioned by Paul in Eph/4/14 like this “Then we will no longer be infants, tossed back and forth by the waves, and blown here and there by every wind of teaching and by the cunning and craftiness of people in their deceitful scheming.”

Therefore winds in Peter’s story may represent “winds of doctrine” which will trouble infant believers in their faith. When Peter looked at the winds he became afraid and began to lose faith then began to sink. As long as he looked at Jesus who had just said to them “do not be afraid” he would not sink.

The true Word of Jesus as opposed to winds of doctrine, inspires confidence in believers, not fear. It speaks comfort and courage to them to stand confidently before God and his promises. It reinforces the consciuosness that we are righteous and upright before God not by ourselves but by our faith in Christ. And therefore we are deserving of every blessing he has for us; no need to fear a reprisal from him.

Anyone purporting to be teaching you God’s word or some doctrine of it and yet the end-result of what he teaches is fear or that it diminishes the believer’s confidence before God is not teaching the true words of Jesus himself.

“Winds of doctrine” are also “boisterous”. They draw attention to themselves or make you look inwardly at yourself and your unworthiness instead of making you look up to Christ’s perfection in whom is your righteousness and acceptance before God. James 3.17 says “the wisdom from above is first of all peacable..“.

Jesus pointed the disciples to himself “Fear not, It is I ..” When our thoughts are fixed on Jesus comforting and validating us inspite of our weakness and inabilities, somehow we become transformed to become like him – walking on water just as he does.  But when we look at our weaknesses or the threatening storm around us which still points us to our inabilities, we sink and wallow in our mess.

If you are in a storm make it your aim to fix the eyes of your heart and thoughts on Jesus face saying to you this comfort “Be not afraid; It is I”.

Write your own PHP5 MVC framework: Handling databases [part 2] – The ORM

We had earlier introduced the concept of working with models (db objects) rather that writing db queries in your php scripts. We had seen how it offers a simpler object oriented interface to the db, and what a joy it is to work with. Here we expound on the M in ‘MVC’. In brief though, models allow you to treat db data in a mysql or postgres or oracle (or any other rdbms) database as php objects. These objects might represent a single row in a db table, or span across multiple relations in the case of a row having related data in other tables ; they can also be a collection of db objects (which then makes them iterable). Whatever they are, they offer a high degree of encapsulation and enforce the DRY principle ( ie Dont Repeat Yourself). You will not repeatedly write the same queries fetching data, instead , you will concentrate on the task at hand in your application.

Consider :

$rs = mysql_query("select username form users where id = 2");
while($row = mysql_fetch_array($rs)) {
echo $row['username'];
}

With an orm we are able to summarise the above repetitive cycle into :

$user = new User(2);
echo $user->username;

There is yet much more to it, just read on..

You will need the following files (dao.php, db.php, db_connect.php) in 0rm.zip  :

0rm.zip

This ORM has 3 classes in 3 files:

  • db_conn in db_conn.php
  • db in db.php
  • dao in dao.php

db_conn

db_conn as you may have guessed, provides a db connection to the database through whatever db driver you have chosen : pgsql, mysql and perhaps mssql, odbc etc if you have compiled pdo support for those into your apache php module.

db_conn also maps out relations between different tables in your database.

This is done automatically for you, provided you followed 4 simple naming conventions when designing your db tables :

  1. All primary key fields are called “id”
  2. Foreign keys are named <tablename_singular_form>_id eg users table has a one-to-many foreign key link with the persons table through a foreign key “person_id”; “persons” becomes “person” and then we append “_id” to it.
  3. Table names and all field names are rendered in lower case e.g. users, username rather than Users, UserName etc.
  4. Table names are in their plural forms, though this may not always be possible.

With these in place, db_conn will create an array of all the tables in the database, their fields, their relations with other tables and the field types.

The code below:

print_r(db_conn::instance());

anywhere in the controllers you will give you an idea of how db_conn maps out and stores the information on table relations.

db

The db class provides a database abstraction layer. this means, it allows to run queries without having to care whether your queries are compatible with whatever RDBMS runs beneath your application.

You can do:-

  1. SELECTs
  2. INSERTs
  3. UPDATEs
  4. DELETEs

Now lets assume we have a db with the 3 tables:

users

  1. id
  2. username
  3. email
  4. password
  5. person_id

persons

  1. id
  2. firstname
  3. lastname
  4. phone
  5. organisation_id

organisations

  1. id
  2. name
  3. location
  4. phone

1. SELECTs

Example 1: a simple select


SELECT username from users where id = 1


 $user = db::factory()
		 ->SELECT("username")
		 ->from("users")
		 ->where(array('id' => 1))
		 ->run(); 

you must run() or execute() every query for it to be actually run against the db
the query will return a 2 dimensional array result
echo $user[0]['username'];

Example 2 : SELECT * from users where id = 1


 $user = db::factory()
		 ->SELECT("*")
		 ->from("users")
		 ->where(array('id' => 1))
		 ->run();
the query will return a 2 dimensional array result
echo $user[0]['username'];

Example 3 : get(‘fieldname’)


 $username = db::factory()
		 ->SELECT("*")
		 ->from("users")
		 ->where(array('id' => 1))
		 ->get('username')
		 ->run();
with get() , the query will simply return the SELECTed column
echo $username;

Example 4 : a join between users and persons table


SELECT concat(firstname, ' ' , lastname) as names from users, persons where users.person_id = persons.id and id = 1;$username = db::factory()
		 ->SELECT("concat(firstname, ' ' , lastname) as names ")
		 ->from("users", "persons")
		 ->join(array('users.person_id'))
		 ->where(array('id' => 1))
		 ->get('names')
		 ->run();
echo $username;

Example 5 : prepared queries


SELECT concat(firstname, ' ' , lastname) as names from users, persons where users.person_id = persons.id and id = 1;$username = db::factory()
		 ->SELECT("concat(firstname, ' ' , lastname) as names ")
		 ->from("users", "persons")
		 ->join(array('users.person_id'))
		 ->where(array('id' => '?'))
		 ->get('names')
		 ->run(1);
echo $username;

Example 6 : insert()


INSERT INTO users (username, password, email) VALUES ('johndoe', md5('secret'), 'john@doe.com');
$last_insert_id = db::factory()
	          ->insert("users",
		  array(
			'username' => '?',
			'password' => '?',
			'email' => '?'
		  )
	          )
	          ->run('johndoe', 'secret', 'john@doe.com');

Example 7 : update()


UPDATE users SET email = 'johndoe@google.com' WHERE id = 1;
db::factory()->update(“users”, array( 'email' ⇒ '?' ) )->run('johndoe@google.com');

Example 8 : _and()


SELECT users.username as username FROM users, persons WHERE persons.id = users.person_id AND persons.firstname = 'john' AND ersons.lastname = 'kamau';$username = db::factory()
		 ->SELECT("users.username as username")
		 ->from("users", "persons")
		 ->join(array('users.person_id'))
		 ->_and(array('persons.firstname' => '?', 'persons.lastname' => '?'))
		 ->get('username')
		 ->run('john', 'kamau');
echo $username;

Example 9 : _or()


SELECT users.username as username FROM users, persons WHERE persons.id = users.person_id AND persons.firstname = 'john' OR persons.firstname = 'kamau';$users = db::factory()
		 ->SELECT("users.username as username")
		 ->from("users", "persons")
		 ->join(array('users.person_id'))
		 ->_or('persons.firstname' => '?')
		 ->_or('persons.firstname' => '?')
		 ->run('john', 'kamau');
foreach ($users as $user) {
echo $user['username'] . "<br/>";
}

the result might be a multiple result set of guys named john or kamau

Example 10 : _in()


 SELECT users.username as username FROM users, persons WHERE
 persons.id = users.person_id AND
 persons.firstname IN ('john', 'kamau');
$users = db::factory()
		 ->SELECT("users.username as username")
		 ->from("users", "persons")
		 ->join(array('users.person_id'))
		 ->_or('persons.firstname' => '?')
		 ->_or('persons.firstname' => '?')
		 ->run('john', 'kamau');

the result might be a multiple result set of guys named john or kamau

foreach ($users as $user) {
echo $user['username'] . "<br/>";
}

Example 11 : _in() with a subselect


SELECT username FROM users WHERE person_id IN (SELECT id from persons WHERE firstname = 'john' OR firstname = 'kamau');$users = db::factory()
		 ->SELECT("username")
		 ->from("users")
		 ->_in( "id",
				db::factory()
				->select('id')
				->from('persons')
				->_or('persons.firstname' => '?')
				->_or('persons.firstname' => '?')
				->params('john', 'kamau')
				/* dont run() the subquery just yet*/
		 )
		 ->run();

the result might be a multiple result set of guys named john or kamau

foreach ($users as $user) {
echo $user['username'] . "<br/>";
}

Example 12 : between()


SELECT username FROM users WHERE id between 1 and 8;
$users = db::factory()
 ->SELECT("username")
 ->from("users")
 ->where('id' => 'BETWEEN ? and ?')
->run('1', '8');

the result might be a multiple result set of guys named john or kamau

foreach ($users as $user) {
echo $user['username'] . "<br/>";
}

====

There are other methods you can use to generate db agnostic queries. Look at them in db.php, chances are they will cover almost every querying scenario that will arise in day to day use. If all these fail, you can always fall back to good old PDO::query($query).

$allusers = db_conn::instance() →query(“SELECT * FROM users”) ;

while ($allusers→fetch() as $user) {
echo $user['username'] . "<br/>";
}

dao.php – the orm


to SELECT the username of a user with an id = 1;

 

Example 1 : SELECT username from users where id = 1


$id = 1; $user = new DAO('users', $id);echo $user→username;

Example 2 : SELECT * from users


$user = new DAO('users', “*”);
foreach ($users as $user) {
echo $user->username;
}

Example 3 : UPDATE users SET email = ‘john.doe@google.com’ WHERE id = 1;


$user = new DAO('users', 1);
$user→save();

 

Example 4 : INSERT INTO users (username, password, email) VALUES ('johndoe', md5('secret'), 'john@doe.com');

$user = new DAO('users'); //we instantiate DAO without an $id
$user→username = 'johndoe';
$user→password = md5('secret)';
$user→email = 'john@doe.com';
$user→save();

Example 5 : an array of arguments as the $id param


we can instantiate DAO with an array $id. the array is converted into 'and' arguments in a 'select .. where' clause

$user = new DAO('users', array('username' ⇒ 'johndoe'));
$user = new DAO('users', array('id' ⇒ 1));

echo $user→email ;

 

it is also possible to travel “up” the relational hierarchy and retrieve related information stored in other tables ..

echo $user→person→firstname . ' ' $user→person→lastname ;

and even

$user→person→organisation→name

Notice that an instance of a record stored in the ‘users’ table became “user” (singular), ‘persons’ became “person” and ‘organisations’ became ‘organisation’

Example 6 : one to many relations


From our db design above, an ‘organisation’ can have many ‘persons’. Thus :

$org = new DAO('organisations', $id);
//list all the persons in the organisations :

foreach ($org→persons as $person) {
echo $person->firstname;
}

on the other hand it is is possible to go back up this way :

$person→organisation→name

This perfectly mirrors the one-to-many relation existent between ‘organisations’

and ‘persons’ ie an $organisation has many $persons, whereas a $person belongs to an $organisation. This is an active record pattern.

Example 7 : a db object as an argument


we can instantiate DAO with a db object as an argument.below, we are selecting all ‘persons’ who do not have corresponding accounts/entries in the users table :

$persons_sql = db::factory()
  1. >select('*')
  2. >from('persons')
  3. >and_not_in('id',
db::factory()
  1. >select('person_id')
  2. >from('users')
)
			;
$persons = new DAO('persons', $persons_sql);
foreach ($persons as $person) {
echo "{$person->firstname $person->lastname} <br/>";
}

Example 8 : limit() the result set


the limit() method (also available in the db object) comes in handy when paginating.below, we are selecting all 'persons' who do not have corresponding accounts/entries in the users table :
$persons_sql = db::factory()
  1. >select('*')
  2. >from('persons')
  3. >and_not_in('id',
db::factory()
  1. >select('person_id')
  2. >from('users')
)
			;
$persons = new DAO('persons', $persons_sql);
$limit = 10; $offset = 2;
$persons→limit($limit, $offset);
foreach ($persons as $person) {
echo "{$person->firstname $person->lastname} <br/>";
}

Creating models which extend DAO


At the very least :class User extends DAO
{
	public function __construct($id = null)
	{
		parent::__construct("users", $id);
	}
}

With this, you can then do

$user = new User($id); /*$id can be “*”, an interger or an array*/

You can do the much buzzwordied “model validation” :

class User extends DAO
{
	public function __construct($id = null)
	{
		parent::__construct("users", $id);
	}    

	public function validate($input)
	{
		$this->input = $input;

		$this->validator = new Validate($this->input);

		$this->validator
		->pre_filter('username, password', array('valid::trim'))
		->post_filter('password', array('valid::hash_password'))
		->add_rule('username',
				 array('valid::required' => "Please fill in your username.",
					   'valid::length 6-128' => "Username should be between 6-128 characters long.",
					   'valid::unique users username' => "The username <b>{$this->input['username']}</b> is already taken."
					   ))
		->add_rule('password',
				array('valid::required' => "Please fill in a password.",
					  'valid::length 6-128' => "Password should be between 6-128 characters long.",
					  "valid::matches {$this->input['confirm_pass']}" => "Your passwords do not match.",
					  ))
		->add_rule('person_id',
				array('valid::required' => "Please select a person for this account.",
					  'valid::unique users person_id' => "That person already has an account"
					  ))
		;

		if ($this->validator->validate()) {

			$this->input = $this->validator->input ;

			// populate the obvious fields
			foreach ($this->fields as $field){
				if(isset($this->input[$field])) {
					$this->$field  = $this->input[$field];
				}
			}
			return true;

		} else {

			$this->errors = $this->validator->errors;
			return false;
		}
	}
}

The above user model can validate posted data in a $_POST array and returns a boolean depending on the result of the validation. For example :

Somewhere in your controllers, handling posted data ..

public function save_user()
{
	$user = new User();
	if ($user->validate($_POST)) {
		$user->save();

		Msg::instance()->info[] = "The user has been succesfully added";
	} else {
		Msg::instance()->info[] = "The user could not be added";

	}

}

The Validate class


The validate class (library) is used to validate submitted data in models using user defined static methods which reside in the Valid class.We instantiate while passing in the posted data into the constructor:

$validator = new Validate($_POST);

We trim fields :

$validator →pre_filter('username, password', array('valid::trim'))

We add a rule to validate the username and password field:

$validator →add_rule('username, password',
	 array('valid::required' => "This field is required."))

add_rule takes the arguments : 1. a string of the $_POST field or several fields to be validated by this rule 2. an array where

a. the key is the rule, with space separated arguments in order, from

the first of the valid::function() arguments to the second last. the last
  argument is reserved for the value of the submitted $_POST field.

  b. the value of the array is the error message to be shown if the
  field validation fails

We add more rules for the username field :

→add_rule('username, password',
	 array(
		   'valid::length 6-128' => "Username should be between 6-128 characters long.",
		   'valid::unique users username' => "The username <b>{$this->input['username']}</b> is already taken."
		   ))
We can then run the $validator→validate() method. It will return a boolean on success or failure. If there are errors, they will be found on the array property $validator→errors.
If there are no errors, $validator→[field] will have the posted data ready for saving.

In a model, we typically colleft all these fields back into instanctiated model as properties and call the save() method of the model. ie

$this→input = $validator→input ;
foreach ($this->fields as $field){
	if(isset($this->input[$field])) {
		$this->$field  = $this->input[$field];
	}
}
save() , will then be called from a controller.

Have a look at the methods in the valid class [valid.php] and try to write your 0wn validation rules.

That is basically it. The 3 classes are pretty hackable, and you can modify or extend them to suit your 0wn programming needs.

Happy hacking :-)

Write your own PHP5 MVC framework

Let there be Lite

Although there are as many frameworks out there as there are programmers, very few frameworks allow the programmer room to code his/her own way. Most are bloated with libraries and features you will never use. And most impose arcane rules to application development, creating a whole new programming language the programmer now has to learn. Whereas our unnamed framework is not the answer to all your problems, it gives the web developer more leverage in deciding how to use the framework, changing the conventions, or even trashing it etc It is dead simple. And it would be useless without a simple do-it-yoursel tutorial of how it is built and how it works, because this is the whole point of wrestling control from popular mainstream frameworks and giving it back to the programmer.

Enough with the sales pitch.

(From Wikipedia)

Model–View–Controller (MVC) is an architectural pattern used in software engineering. Successful use of the pattern isolates business logic from user interface considerations, resulting in an application where it is easier to modify either the visual appearance of the application or the underlying business rules without affecting the other.

In simpler words-

1. Models handle database logic. As a matter of fact the model acts as an abstraction layer enabling us to access data (mostly from a database) as PHP objects or attributes of PHP objects.
2. Controller sit between the Models and the Views, passing requests from the views to the model and data from the model onto the view which the user interacts with.
3. Views are what the user sees when interacting with the application.

So with such a nice introduction we get down to it! We will create a PHP5 application to access a database of all our contacts. We will also provide forms to save contacts into the database.

In the beginning

We want our application to be at http://localhost/contacts/. The application will have pretty urls of the form

http://localhost/contacts/index/list_all -> to list all contacts in the db

http://localhost/contacts/index/delete/12 – to delete contact with the id 12

and so on and so forth ..

So we start off by creating the project directory `contacts`. Inside this directory we create a .htaccess file and put in the following rules :

Options -Indexes
RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !(index.php|favicon.ico)$
RewriteRule (.*) index.php/$1 [PT,L]

Basically, the above rules allow you to implement pretty urls in the application. This is done by redirecting all requests in the background to index.php which in turn will pass the url parameters separated by front-slashes to bootstrap.php.

Note that your apache installation needs to have the directive AllowOverride set to All. Well not really All, but basically it must allow override of rules by .htaccess files.

index.php

Next we create the index file, index.php.

<?php
define(‘ROOT’, dirname(__FILE__));
require_once (ROOT . ‘/core/bootstrap.php’);

Notice that there are no closing tags in the above php file .. this is good standard practice for security purposes for files which do not contain any HTML content. Remember, index.php receives a string of parameters separated by the forward slash ‘/’ and will thus pass this onto bootstrap.php.

bootstrap.php

We create /contacts/core/bootstrap.php with the following..

<?php

$conf = parse_ini_file(‘./config/application.ini’, TRUE);

//[site]
define(‘BASE_DIR’, $conf['site']['BASE_DIR']);

//date.timezone setting
date_default_timezone_set($conf['time']['default_timezone']);

//path info
define (‘HTTP_PATH’, ‘http://’ . $_SERVER['SERVER_NAME'] . ‘/’ . BASE_DIR);
define (‘FS_PATH’, $_SERVER['DOCUMENT_ROOT'] . ‘/’ . BASE_DIR);
define (‘REQUEST_URI’, preg_replace(‘/\?’ . $_SERVER['QUERY_STRING'] . ‘/i’, ”, $_SERVER['REQUEST_URI']));

require_once (ROOT . ‘/core/init.php’);

The bootstrap basically initialises the application. The line :

$conf = parse_ini_file(‘./config/application.ini’, TRUE);

parses an .ini file for configurations which we have saved in the location /contacts/config/application.ini. These could be database credentials, the default time zone and any other configuration you will need. The lines which follow use the php function define() to define certain variables which will be used throughout the application. These defines are necessary because the $conf variable (or any $-variable for that matter) is limited in scope and will not be availabe within our class definitions in the very near future.

The last line :

require_once (ROOT . ‘/core/init.php’);

finishes off the initialisation process.

We save bootstrap in /contacts/core/bootstrap.php

init.php

We now begin prepare the way for some more interesting stuff here. We create /contacts/core/bootstrap.php with the following..

function callHook() {

$url = REQUEST_URI;

// strip out our query string
$url = preg_replace(‘/\?.+$/i’, ”, $url);
//explode() the string into an array of parameters
$urlArray = array();
$urlArray = explode(“/”, $url);
// for an empty string we assume the user wants to access index/index
if (!count($urlArray)) {
$urlArray[0] = “index”;
$urlArray[1] = “index”;
} else if (count($urlArray) < 2) {
$urlArray[1] = “index”;
}

$controller = $urlArray[0];
array_shift($urlArray);
$action = $urlArray[0];
array_shift($urlArray);
$params = array_map(‘urldecode’, $urlArray);

$controllerName = $controller;
$controller = ucwords($controller);
$controller .= ‘Controller’;

//we instantiate and call the controller methods
try {

if (class_exists($controller)) {
$dispatch = new $controller;
} else {
throw new Exception(“Invalid call to non-existent class {$controller}.”);

}

if (method_exists($dispatch, $action)) {

call_user_func_array(array($dispatch, $action), $params);
} else {

throw new Exception(“Invalid call to non-existent {$controller}::{$action}.”);

}
} catch (Exception $e) {

echo “<pre>” . $e->getMessage() . “</pre>”;

}

}

/** Autoload any classes that are required **/

function __autoload($className) {

if (file_exists(ROOT . ‘/db/’ . strtolower($className) . ‘.php’)) {
require_once(ROOT . ‘/db/’ . strtolower($className) . ‘.php’);
}

if (file_exists(ROOT . ‘/core/’ . strtolower($className) . ‘.php’)) {
require_once(ROOT . ‘/core/’ . strtolower($className) . ‘.php’);
}

if (file_exists(ROOT . ‘/lib/’ . strtolower($className) . ‘.php’)) {
require_once(ROOT . ‘/lib/’ . strtolower($className) . ‘.php’);
}

if (file_exists(ROOT . ‘/application/controllers/’ . strtolower(preg_replace(“/controller/i”, “”, $className)) . ‘.php’)) {
require_once(ROOT . ‘/application/controllers/’ . strtolower(preg_replace(“/controller/i”, “”, $className)) . ‘.php’);
}

if (file_exists(ROOT . ‘/application/models/’ . strtolower($className) . ‘.php’)) {
require_once(ROOT . ‘/application/models/’ . strtolower($className) . ‘.php’);

}

}

try {
callHook();

} catch (Exception $e) {

echo $e->getMessage();
}

Quite a mouthful, huh? Well, not really.

We receive the REQUEST_URI (minus the base url of our application ‘contacts’); for example

http://localhost/contacts/list_all/index is list_all/index.

The string ‘list_all/index’ exploded by the php explode() function into Array(’0′] => ‘list_all’, ['1'] => ‘index’)

http://localhost/contacts/list_all also becomes Array(’0′] => ‘list_all’, ['1'] => ‘index’) thanks to this block of code

if (!count($urlArray)) {
$urlArray[0] = “index”;
$urlArray[1] = “index”;
} else if (count($urlArray) < 2) {
$urlArray[1] = “index”;
}

The above block also generates Array(‘index’, ‘index’) from the url http://localhost/contacts.

Next is the block :

$controller = $urlArray[0];
array_shift($urlArray);
$action = $urlArray[0];
array_shift($urlArray);
$params = array_map(‘urldecode’, $urlArray);

$controllerName = $controller;
$controller = ucwords($controller);
$controller .= ‘Controller’;

Here, we assign $controllerName and $action which are, effectively, the Controller class to be instantiated and the method to invoke with the necessary parameters ($params) if the method requires parameters. The try/catch block that follows does all the above, additionally throwing an error if one occurs. Typical error scenarios include calling non-existent controller or its method; or calling a method without parameters where there needed to have been.

The __autoload function defined saves you the trouble of so many include’s or require_once’s on the hundred or so project files you might create on a bigger project.

Finally we callHook(), which basically executes our url as an object method.

So does this work? We will test it out shortly ..

Let there be light..

We create a directory application/ and inside it another directory controllers/. It is inside controllers/ that we will save all our controller classes; starting with our index file right here .. We create a file index.php and inside it the class IndexController

<?php

class IndexController {

public function index() {

echo “Finally, some light!”;

}

}

Now go the url http://localhost/contacts/index/index : ‘Finally, some light!’

Views

Being able to echo or print() content from the controller is all fine. But this doesnt scale up very well. It would be a nightmare not worth a framework if you had to echo all your HTML content.

Luckily, a View helper will help us out. The idea is to have different parts of a HTML page saved in a different directory as just .html or .php pages and then embedded into the correct template as necessary. Also we need to be able to embed templates within other templates with a great deal of flexibility. Afterall, this is the whole point of separation of content from logic.

We will be able to create a view , for example, named light.php and save it in a directory views/ inside application/. We should then be able to do the following to get ‘Finally, some light!’, only done in a smarter way!

<?php

class IndexController {

public function index() {

$view = new View(‘light.php’);

$view->message = “Finally, some light!”;

$view->render();

}

}

And just for fun, a nested view should be possible too :

$view = new View(‘light.php’);

$view->message = new View(‘light.php’);

$view->message->message = “Finally, some light!”;

$view->render();

The above feat is made possible by a few lines of code in the file view.php, which will reside in contacts/core/views.php

<?php

class View {

public $arr = array();
public $file;

public function __construct($file) {
$this->file = $file;
}

protected function get_sub_views($obj) {

foreach ($obj as $varname => $var) {
if ($var instanceof View) {
$obj->arr[$varname] = $var->get_sub_views($var);
} else {
$obj->arr[$varname] = $var;
}
}
extract($obj->arr);
ob_start();
if (file_exists(ROOT . “/application/views/” . $obj->file)) {
include ROOT . “/application/views/” . $obj->file;
} else {
throw new Exception(“The view file ” . ROOT . “/application/views/” . $obj->file . ” is not available”);
}
$html = ob_get_clean();

return $html;
}

public function render() {
echo self::get_sub_views($this);
}

}

Quite briefly, get_sub_views() recurses through the nested views and renders all the variables from the bottom of the recursion tree going up until at last it renders the base view. Magic? You tell me.

Models

We have taken care of the V and the C in MVC but what about the M ? For now it will suffice to say that we need the following 3 files saved in our contacts/db/. In one of the following blog posts I will go into what exactly happens inside db.php and dao.php, I will then break forth into poetry of how these two files with the help of PDO are the key to world peace and finding lasting love. But this (and more) will happen on another day.

contacts/db/

—->db_conn.php : will set up a database connection via PDO.

—->db : supports CREATE (insert), READ (select), UPDATE (update), DELETE (delete) methods to our mysql db. But why not just use PDO::query() to directly execute mysql queries ? Because we are trying to achieve database agnosticism. So that later when our contacts app changes its db from mysql to postgre, all we (the smarter) will need to is to change this wrapper to postgres, mssql or whatever other relational db they will hjave come up with then. The not-too-smart programmers will be re-writing the whole application from scratch!

—->dao

: This is an Object Relation Modeller (ORM) for our application. I called DAO (Data Access Object) instead because .. well, I didnt want to sound like everyone else ;-) . The DAO (plus adherence to some 3 or so database scheming conventions) will make db access and updating a breeze. as easy as

$contact= new Contact;

$contact->name = “blowfish”;

$contact->number = “254722115273″;

$contact->save();

Quite easy!

The database username and passwords reside in contacts/config/application.ini. For purposes of clarity, application.ini looks something like this :

[db]
host = localhost
username = db-username
password = db-password
name = contacts

[site]
BASE_DIR = biblia/

[time]
default_timezone = “Africa/Nairobi”

We now have a core system with which we can build an application.

Let the framework bring forth applications that the interwebs may teem with life ..

I suppose with that brief introduction to the application’s core we can begin bringing to life our Contacts app.

The contacts database

We create a mysql database named Contacts. And in it we create the table `contacts`.

create table contacts (id int auto_increment primary key, name char(30), number char(16), email char(50));

To leverage the goodies (and lasting love brought by) DAO we follow these 3 simple rules in our table schema

1. all table names are plural eg contacts, users, boxes etc

2. all tables must have an id field (with the exception of pivot tables)

3. foreign keys are named in the singular form of the parent table. This involves knocking off the last `s` from the parent table name and appending `_id` to it. Therefore, if we were to later have a `users` table with the contacts.id foreign key it would be contact_id`. A less interesting scenario is where the table name’s plural contains an `es` at the end. `Knives`, for example, will have its foreign key named `knive_id`. Dont blame the framework, blame the English language !

The Model

After creating the db table, we will create a model for it in contacts/application/models/contact.php.

<?php

class Contact extends DAO{

public function __construct($table = “contacts”, $id= null) {

parent::__construct($table, $id);

}

}

It is now possible to do

$contact = new Contact();

OR to select an existing contact by id

$contact = new Contact(2);

echo “{$contact->name} –> {$contact->number}”;

Adding data – The form view

we create application/views/add.contact.php with the followind code :

<form action=’<?=HTTP_PATH?>index/save’ method=’post’>

<p>

<label for=’name’>Name : </label>

<input type=’text’ name=’name’ />

</p>

<p>

<label for=’number’>Number : </label>

<input type=’text’ name=’number’ />

</p>

<p>

<label for=’email’>Email : </label>

<input type=’text’ name=’email’ />

</p>

<p>

<input type=’submit’ name=’save’ value=’Save’ />

</p>

</form>

Adding data – The controller `add` method

Inside contacts/application/controllers/index.php ..

<?php

class IndexController {

public function index() {

$view = new View(‘light.php’);

$view->message = “Finally, some light!”;

$view->render();

}

public function add() {

$view = new View(‘add.contact.php’);

$view->render();

}

}

And now the `save` method in IndexController

public function save() {

$contact = new Contact(); // no constructor arguments since we are creating a new Contact object

$contact->name = $_POST['name']; // in the real world, all $_POST and $_GETS _must_ me sanitized

$contact->number = $_POST['number'];

$contact->email = $_POST['email'];

if ($contact->save()) {

$view = new View(‘light.php’);

$view->message = “The new contact {$_POST['name']} has been saved!”;

$view->render();

} else {

$view = new View(‘light.php’);

$view->message = “There was a problem saving the contact {$_POST['name']} “;

$view->render();

}

}

`list_all` contacts in the db

We start off with the view : contacts/application/views/list.contacts.php

With this view we loop over a collection of contact objects and echo the rows in a nice table. We also add ‘delete’ link at the end of every column to enable delete non-forthcoming contacts (the guys who blocks your calls).

<table>

<?php foreach ($contacts as $contact) {?>

<tr>

<td><?=$contact->name?></td>

<td><?=$contact->number?></td>

<td><?=$contact->email?></td>

<td> <a href=’<?=HTTP_PATH?>index/delete/<?=$contact->id?>’>delete </a></td>

</tr>

<?php }?>

</table>

We create another method/action in IndexController to list our contacts. We will call tis `list_all` ..

public function list_all(){

// we select all the contacts in the db

$contacts = new Contact(‘*’); // ‘*’ is equivalent to `select * contact objects` in DAO-speak

//assign a view

$view = new View(‘list.contacts.php’);

$view->contacts = $contacts;

}

We create the delete method/action :

public function delete($id){

// this $id is the integer immediately following http://../index/delete/<integer>

$contacts = new Contact($id); // now here we select a contact with the id equal to the value of $id

if ($contact->del()) {

$view = new View(‘light.php’);

$view->message = “the contact has been deleted”;

} else {

$view = new View(‘light.php’);

$view->message = “there was a problem deleting the contact”;

}

}

And that is it!

Now we look on all our (brief but smart) works in awe, thank the Good Lord above .. and rest

See you later when I explain how the DAO class works, and most importantly how you too can build your own.

Malcom X

Malcolm X stressed the global perspective he had gained from his international travels. He emphasized the “direct connection” between the domestic struggle of African Americans for equal rights with the liberation struggles of Third World nations.[183] He said that African Americans were wrong when they thought of themselves as a minority; in a global context, black people were a majority, not a minority.[184]

Although he no longer called for the separation of black people from white people, Malcolm X continued to advocate black nationalism, which he defined as self-determination for the African American community.[185] In the last months of his life, however, Malcolm X began to reconsider his support of black nationalism after meeting northern African revolutionaries who, to all appearances, were white.[186]

After his Hajj, Malcolm X articulated a view of white people and racism that represented a deep change from the philosophy he articulated as a minister of the Nation of Islam. In a famous letter from Mecca, he wrote that the white people he had met during his pilgrimage had forced him to “rearrange” his thinking about race and “toss aside some of [his] previous conclusions”.[187]

In a 1965 conversation with Gordon Parks, two days before his assassination, Malcolm said:

[L]istening to leaders like Nasser, Ben Bella, and Nkrumah awakened me to the dangers of racism. I realized racism isn’t just a black and white problem. It’s brought bloodbaths to about every nation on earth at one time or another.

Brother, remember the time that white college girl came into the restaurant — the one who wanted to help the [Black] Muslims and the whites get together — and I told her there wasn’t a ghost of a chance and she went away crying? Well, I’ve lived to regret that incident. In many parts of the African continent I saw white students helping black people. Something like this kills a lot of argument. I did many things as a [Black] Muslim that I’m sorry for now. I was a zombie then — like all [Black] Muslims — I was hypnotized, pointed in a certain direction and told to march. Well, I guess a man’s entitled to make a fool of himself if he’s ready to pay the cost. It cost me 12 years.

That was a bad scene, brother. The sickness and madness of those days — I’m glad to be free of them.[188]

Replicating a mysql table structure

Just found out that as of mysql4.1 you can actually replicate a whole table structure (with no data, so cool!) with the command :

create <new-table> like <old-table>;

Just that!

An older method is to attach a select statement to the create command like so :

create <new-table> select * from <old-table>;

This will actually create a copy of the old table as the new table. If you dont want to move data, then :

create <new-table> select * from <old-table> where 1=0;

For all these methods however, table indexes are not copied.