Mapper Classes / Code Generator

By orqi

You can create your own mappers if you like, but there are code generators to help you at http://www.orqi.co.uk/mapper-class-generator.html

All domain classes should extend the Mapper superclass so that you can take advantage of the auto functions !

If have a table like this …

CREATE TABLE `blogcomments` (
  `id` int(11) NOT NULL auto_increment,
  `posts_id` int(11) NOT NULL,
  `name` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `timestamp` int(11) NOT NULL,
  `approved` int(11) NOT NULL,
  PRIMARY KEY  (`id`)
) ENGINE=MyISAM AUTO_INCREMENT=1 ;

You should fill in the mapper form like this (explanation to follow) …

The “posts_id” field in the database table is a link to the “posts” table. This means that the BlogComment object being passed into our mapper will most likely have an object as one of it’s members. So this means we need to give it the object’s name as well. Hence “posts_id, post”.

The “name” and “email” values you will notice are surrounded by quotemarks. This is because these fields are text and need surrounding by quote marks in the insert/update sql statements. Putting the quotemarks simply tells Orqi to do this as well.

Hit “Generate” and you will get a fille looking something like this.

// ================================================================================= //		

class BlogComments extends Mapper
{
	// ============================================================================= //

	function BlogComments()
	{
		$this->config = new Config();
		$this->dao = new DAO();
	}

	// ============================================================================= //

	function GetSelectBoxData()
	{
		$data = array();

		$sql_string = "select id as value, name as text from blogcomments order by name asc";
		$recordset = $this->dao->ExecuteQuery($sql_string);
		if ($recordset) while ($record = mysql_fetch_assoc($recordset)) $data[] = $record;

		return $data;
	}

	// ============================================================================= //

	function GetTotalRows()
	{
		$recordset = $this->dao->ExecuteQuery("select count(*) as total_rows from blogcomments");
		$record = mysql_fetch_assoc($recordset);
		return $record['total_rows'];
	}

	// ============================================================================= //

	function FindAll($page='')
	{
		$data = array();
		$sql_string = "select * from blogcomments order by name";

		if (!empty($page))
		{
			$cursor = ($page-1) * $this->config->page['items'];
			$sql_string .= "
				limit		" . $cursor . ", " . $this->config->page['items'] . "
			";
		}

		$recordset = $this->dao->ExecuteQuery($sql_string);
		if ($recordset) while ($record = mysql_fetch_assoc($recordset)) $data[] = Caster::Cast($record, new BlogComment());
		return $data;
	}

	// ============================================================================= //

	function Save(&$object)
	{
		$action_text = (!$object->GetId()) ? "insert into " : "update ";
		if ($object->GetId()) $condition = "where id=" . $object->GetId();

		$obj_post = $object->GetPost();

		$sql_string = "
			$action_text	blogcomments
			set				posts_id=" . $obj_post->GetId() . ",
							name='" . $object->GetName() . "',
							email='" . $object->GetEmail() . "',
							timestamp=" . $object->GetTimestamp() . ",
							approved=" . $object->GetApproved() . "
			$condition
		";

		if ($this->dao->ExecuteQuery($sql_string))
		{
			$this->success = true;
			if (!$object->GetId()) $object->SetId(mysql_insert_id($this->dao->conn));
		}
		else $this->success = false;
		return $this->success;
	}

	// ============================================================================= //
}

// ================================================================================= //

Explanation of the functions

Here is a quick explanation of the functions in this class …

Constructor

The constructor just instantiates a couple of class variables that we will need pretty much every funtion. The DAO object is obvious since most mappers have to talk to a database at some point their lives. The Config object is there so we can access stuff like the paging variables.

function BlogComments()
{
	$this->config = new Config();
	$this->dao = new DAO();
}

GetSelectBoxData

This function provides a full list of the table in a value/text pair form.

function GetSelectBoxData()
{
	$data = array();

	$sql_string = "select id as value, name as text from blogcomments order by name asc";
	$recordset = $this->dao->ExecuteQuery($sql_string);
	if ($recordset) while ($record = mysql_fetch_assoc($recordset)) $data[] = $record;

	return $data;
}

GetTotalRows

Returns the total number of rows in the table.

function GetTotalRows()
{
	$recordset = $this->dao->ExecuteQuery("select count(*) as total_rows from blogcomments");
	$record = mysql_fetch_assoc($recordset);
	return $record['total_rows'];
}

FindAll

This will return either a page of items or if no page parameter is passed, all the items in the table.

function FindAll($page='')
{
	$data = array();
	$sql_string = "select * from blogcomments order by name";

	if (!empty($page))
	{
		$cursor = ($page-1) * $this->config->page['items'];
		$sql_string .= "
			limit		" . $cursor . ", " . $this->config->page['items'] . "
		";
	}

	$recordset = $this->dao->ExecuteQuery($sql_string);
	if ($recordset) while ($record = mysql_fetch_assoc($recordset)) $data[] = Caster::Cast($record, new BlogComment());
	return $data;
}

Note: That the Caster is being used to return an object as opposed to just associative mysql array.

Save

This will save the object passed to it. Note that the parameter is passed by reference. This is to try and mimic java a little bit so that back in the calling function we can use the id after an insert easily.

function Save(&$object)
{
	$action_text = (!$object->GetId()) ? "insert into " : "update ";
	if ($object->GetId()) $condition = "where id=" . $object->GetId();

	$obj_post = $object->GetPost();

	$sql_string = "
		$action_text	blogcomments
		set				posts_id=" . $obj_post->GetId() . ",
						name='" . $object->GetName() . "',
						email='" . $object->GetEmail() . "',
						timestamp=" . $object->GetTimestamp() . ",
						approved=" . $object->GetApproved() . "
		$condition
	";

	if ($this->dao->ExecuteQuery($sql_string))
	{
		$this->success = true;
		if (!$object->GetId()) $object->SetId(mysql_insert_id($this->dao->conn));
	}
	else $this->success = false;
	return $this->success;
}

Note: Even though there is a validator framework to check for errors, this function may soon have a type check at the start to trap invalid objects being passed …

// something like this (in the example)
if (!is_a($object, 'BlogComment')) return false;

Common Usages

$control = new SelectBox($this->config, "Usergroups", "usergroups_id", "", "", $this->form->GetUsergroupId(), 'level <=' . $this->session->user_usergroup->GetLevel());

List Page

class AdvertController extends Controller
{
	function All()
	{
		$this->object = new Adverts();
		$this->data = $this->object->FindAll($this->page['current']);
		$this->LoadTemplate("ListAdverts");
	}
}

Saving Stuff

$blogcomments_mapper = new BlogComments();
$blogcomment = new BlogComment();
$blogcomment->SetPost(new Post(1));
$blogcomment->SetName('N E Commenter');
$blogcomment->SetEmail('n.e.commenter@gmail.com');
$blogcomment->SetTimestamp(mktime());
$blogcomment->SetApproved(1);
$blogcomments_mapper->Save($blogcomment);

In Model Classes

class Post extends Object
{
	var $comments = array();

	function GetComments()
	{
		if (empty($this->comments))
		{
			$blogcomments_mapper = new BlogComments();
			$this->comments = $blogcomments_mapper->FindByPost($this);
		}
		return $this->comments;
	}
}

Tags: , , ,

Leave a Reply