<?xml version="1.0" encoding="UTF-8"?>
<?xml-stylesheet type="text/xsl" media="screen" href="/~d/styles/rss2full.xsl"?><?xml-stylesheet type="text/css" media="screen" href="http://feeds.feedburner.com/~d/styles/itemcontent.css"?><rss xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:sy="http://purl.org/rss/1.0/modules/syndication/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:feedburner="http://rssnamespace.org/feedburner/ext/1.0" version="2.0">

<channel>
	<title>PHP and Stuff</title>
	
	<link>http://www.phpandstuff.com</link>
	<description>PHP, JS, CSS, jQuery, CodeIgniter, Doctrine</description>
	<lastBuildDate>Thu, 11 Feb 2010 17:35:39 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.0.4</generator>
		<atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="self" type="application/rss+xml" href="http://feeds.feedburner.com/PhpAndStuff" /><feedburner:info uri="phpandstuff" /><atom10:link xmlns:atom10="http://www.w3.org/2005/Atom" rel="hub" href="http://pubsubhubbub.appspot.com/" /><item>
		<title>CodeIgniter and Doctrine from scratch. Day 11 – Record Hooks</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/pU6gTvyl7gA/codeigniter-doctrine-scratch-day-11-record-hooks</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks#comments</comments>
		<pubDate>Mon, 08 Feb 2010 21:24:33 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=824</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this tutorial we will be looking into <strong>Doctrine Record Hooks</strong>. This will allow us to trigger certain actions in our Models. 

We are going to use this feature to simplify a few things in the existing code, and even gain some performance benefits.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-11-record-hooks"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this tutorial we will be looking into <strong>Doctrine Record Hooks</strong>. This will allow us to trigger certain actions in our Models. </p>
<p>We are going to use this feature to simplify a few things in the existing code, and even gain some performance benefits.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_doctrine_day11.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Record Hooks</h3>
<p>In the <a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8 article</a> we talked about CodeIgniter Hooks. This time we are going to look at <strong>Record Hooks</strong> with Doctrine.</p>
<p>Hooks are used to execute certain code when a certain event is triggered. Record Hooks are used when something happens with a Doctrine Record. For example we can use the <strong>postInsert</strong> hook to do some task every time a new record is inserted.</p>
<p>Here is a list of all available Record Hooks:</p>
<ul>
<li>preSave</li>
<li>postSave</li>
<li>preUpdate</li>
<li>postUpdate</li>
<li>preInsert</li>
<li>postInsert</li>
<li>preDelete</li>
<li>postDelete</li>
<li>preValidate</li>
<li>postValidate</li>
</ul>
<p>To use a one of these hooks, simply add a method with that name into the Doctrine_Record model:</p>
<pre class="brush: php; highlight: [11,12,13,14];">
class Post extends Doctrine_Record {

	public function setTableDefinition() {
		// ...
	}

	public function setUp() {
		// ...
	}

	public function postInsert() {
		// a new record was inserted
		// you can put some code here
	}

}
</pre>
<p>Let&#8217;s look at what we are going to be doing today to utilize this feature.</p>
<h3>Forum Display Page Improvements</h3>
<p>In the <a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9 article</a> we built a page for displaying all Threads under a Forum.</p>
<p><img height="291" width="590" class="aligncenter size-full wp-image-744" title="ci_doctrine_day9_5" alt="ci_doctrine_day9_5" src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_5.png"/></p>
<p>Let&#8217;s look at the code we used for getting the list of threads:</p>
<pre class="brush: php;">
// from the Forum model

// ...
	public function getThreadsArray($offset, $limit) {

		$threads = Doctrine_Query::create()
			-&gt;select('t.title')
			-&gt;addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
			-&gt;addSelect('MIN(p.id) as first_post_id')
			-&gt;addSelect('MAX(p.created_at) as last_post_date')
			-&gt;from('Thread t, t.Posts p')
			-&gt;where('t.forum_id = ?', $this-&gt;id)
			-&gt;groupBy('t.id')
			-&gt;orderBy('last_post_date DESC')
			-&gt;limit($limit)
			-&gt;offset($offset)
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;execute();

		foreach ($threads as &amp;$thread) {

			$post = Doctrine_Query::create()
				-&gt;select('p.created_at, u.username')
				-&gt;from('Post p, p.User u')
				-&gt;where('p.id = ?', $thread['Posts'][0]['first_post_id'])
				-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
				-&gt;fetchOne();

			$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
			$thread['created_at'] = $post['created_at'];
			$thread['username'] = $post['User']['username'];
			$thread['user_id'] = $post['User']['id'];
			unset($thread['Posts']);

		}

		return $threads;

	}
// ...
</pre>
<p>There are two main DQL queries. The first one for fetching the Threads, and the second one, inside of a loop, for fetching further details about each Thread, such as number of replies, the username etc&#8230; </p>
<p>There is quite a bit going on in there. With the changes we will make today, we will be able to reduce that into a single DQL call.</p>
<h3>Adding a &#8220;First_Post&#8221; Relationship</h3>
<p>We first had to get the id of the first post, and then get information on that post in another DQL query. If we had a direct relationship with a &#8220;First_Post&#8221; record, it would simplify things.</p>
<ul>
<li>Edit: <strong>system/application/models/thread.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Thread extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
		$this-&gt;hasColumn('forum_id', 'integer', 4);
		$this-&gt;hasColumn('first_post_id', 'integer', 4);
	}

	public function setUp() {
		$this-&gt;hasOne('Forum', array(
			'local' =&gt; 'forum_id',
			'foreign' =&gt; 'id'
		));
		$this-&gt;hasMany('Post as Posts', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'thread_id'
		));

		$this-&gt;hasOne('Post as First_Post', array(
			'local' =&gt; 'first_post_id',
			'foreign' =&gt; 'id'
		));
	}

}
</pre>
<p>The highlighted lines have been added. Now each Thread will have a relationship with a Post record, which will be the first Post in that Thread.</p>
<h4>Setting up the Hook</h4>
<p>When a new Post is added, if it is the first Post in that Thread, it needs to be assigned to the First_Post relationship. This will be done with the following &#8220;postInsert&#8221; <strong>Record Hook</strong>.</p>
<ul>
<li>Edit: <strong>system/application/models/post.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Post extends Doctrine_Record {

// ...
	public function postInsert() {

		// is this the first post?
		if (!$this['Thread']['First_Post']-&gt;exists()) {
			$this['Thread']['First_Post'] = $this;
			$this['Thread']-&gt;save();
		}

	}

}
</pre>
<p>Note that &#8220;postInsert&#8221; means, &#8220;after&#8221; insert. It has nothing to do with the class name &#8220;Post&#8221;.</p>
<p>This function gets invoked right after a new Post record was created. </p>
<p>First we check if a First_Post relationship exists, with the <strong>exist()</strong> function. If not, we assign &#8220;$this&#8221;, which is the current Post record, to this relationship with the corresponding Thread record.</p>
<h3>Rebuild the Database</h3>
<ul>
<li>Drop all tables.</li>
</ul>
<p>You may use this query:</p>
<pre>
SET FOREIGN_KEY_CHECKS = 0;
DROP TABLE category, forum, post, thread, user;
</pre>
<p>Now we need to rebuild it all.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/create_tables" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/create_tables</a> and click the button.</li>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/load_fixtures" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/load_fixtures</a> and click the button.</li>
</ul>
<p>Now all the tables are rebuilt and the fixture data is reloaded.</p>
<p>Take a look at your thread table:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_doctrine_day11_1.png" alt="ci_doctrine_day11_1" title="ci_doctrine_day11_1" width="581" height="850" class="aligncenter size-full wp-image-852" /></p>
<p>You can see the new column. And thanks to the Record Hook, the values have been assigned already.</p>
<h3>Simplify Things</h3>
<p>Now we can go ahead and simplify the &#8220;getThreadsArray&#8221; method under the Forum Model.</p>
<ul>
<li>Edit: <strong>system/application/models/forum.php</strong></li>
</ul>
<pre class="brush: php; highlight: [12,13,25,26,27];">
&lt;?php
class Forum extends Doctrine_Record {

// ...

	public function getThreadsArray($offset, $limit) {

		$threads = Doctrine_Query::create()
			-&gt;select('t.title')
			-&gt;addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
			-&gt;addSelect('MAX(p.created_at) as last_post_date')
			-&gt;addSelect('fp.created_at, u.username')
			-&gt;from('Thread t, t.Posts p, t.First_Post fp, fp.User u')
			-&gt;where('t.forum_id = ?', $this-&gt;id)
			-&gt;groupBy('t.id')
			-&gt;orderBy('last_post_date DESC')
			-&gt;limit($limit)
			-&gt;offset($offset)
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;execute();

		foreach ($threads as &amp;$thread) {

			$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
			$thread['created_at'] = $thread['First_Post']['created_at'];
			$thread['username'] = $thread['First_Post']['User']['username'];
			$thread['user_id'] = $thread['First_Post']['User']['id'];

			unset($thread['Posts']);

		}

		return $threads;

	}

}
</pre>
<p><strong>Line 13:</strong> Now we have 2 more relationships in the from() call. First_Post and the User for the First_Post.<br />
<strong>Line 12:</strong> We select the created_at and username fields from these new relationships.<br />
<strong>Line 25,26,27:</strong> These lines have been changed to use the new fields.<br />
Also the <strong>DQL query</strong> inside the loop is now gone. This should have a positive impact on performance.</p>
<p>Note that the loop now is only being used to simplify the <strong>$threads</strong> array structure, so it&#8217;s actually optional.</p>
<h4>Testing the Results</h4>
<p>We haven&#8217;t really changed anything on the actual pages. So everything should look the same as before.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_doctrine_day11_2.png" alt="ci_doctrine_day11_2" title="ci_doctrine_day11_2" width="600" height="321" class="aligncenter size-full wp-image-855" /></p>
<h3>Stay Tuned</h3>
<p>There are many things you can do with Hooks and Listeners in Doctrine. Make sure to <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/event-listeners#record-hooks" rel="nofollow">read the documentation</a>.</p>
<p>I hope you enjoyed this tutorial. See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/pU6gTvyl7gA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks/feed</wfw:commentRss>
		<slash:comments>102</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch. Day 10 – Pagination</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/Xd3VQs71vHE/codeigniter-doctrine-scratch-day-10-pagination</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination#comments</comments>
		<pubDate>Wed, 20 Jan 2010 07:42:19 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=793</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> Today we will be working on <strong>Pagination</strong>.

<div class="clear"></div>

<img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_15.png" alt="ci_doctrine_day10_15" title="ci_doctrine_day10_15" width="600" height="313" class="aligncenter size-full wp-image-818" />]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-10-pagination"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> Today we will be working on <strong>Pagination</strong>.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Upgrading Doctrine</h3>
<p>Before we get started, let&#8217;s upgrade Doctrine.</p>
<p>When I wrote the first article in this series, Doctrine 1.1 was the current stable version at the time. Since then, 1.2 has come out. Luckily it is backwards compatible with 1.1.</p>
<p>So, if you are like me and have been using Doctrine 1.1, just follow these steps to upgrade to 1.2.</p>
<ul>
<li>Delete folder: <strong>system/application/plugins/doctrine/lib</strong></li>
<li>Download <a href="http://www.doctrine-project.org/download" rel="nofollow">Doctrine 1.2</a> and extract.</li>
<li>Copy the lib folder to <strong>system/application/plugins/doctrine</strong></li>
</ul>
<h4>One Small Fix</h4>
<p>At some point I did find an issue that wasn&#8217;t backwards compatible. I modified the previous articles to fix that issue but some of you may not have done this if you read those articles before I changed them. </p>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php; highlight: [8];">
&lt;?php
class Home extends Controller {

	public function index() {

		$vars['categories'] = Doctrine_Query::create()
			-&gt;select('c.title, f.title, f.description')
			-&gt;addSelect('t.id, COUNT(t.id) as num_threads')
			-&gt;from('Category c, c.Forums f')
			-&gt;leftJoin('f.Threads t')
			-&gt;groupBy('f.id')
			-&gt;execute();

		$vars['title'] = 'Home';
		$vars['content_view'] = 'forum_list';
		$vars['container_css'] = 'forums';

		$this-&gt;load-&gt;view('template', $vars);
	}

}
</pre>
<p>It&#8217;s just the highlighted line. The &#8216;t.id&#8217; needed to be added to the addselect() or COUNT(t.id) did not work properly.</p>
<p>That is all. If your website is loading without errors, everything should be fine.</p>
<h3>What is Pagination?</h3>
<p>Displaying data in multiple pages is <strong>Pagination</strong>. </p>
<p>There are two main parts to this. First we need to generate links to the pages.</p>
<h4>Pagination Links</h4>
<p>Here is an example from CodeIgniter Forums:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_11.png" alt="ci_doctrine_day10_1" title="ci_doctrine_day10_1" width="324" height="58" class="aligncenter size-full wp-image-799" /></p>
<p>That looks simple, but we also need to consider what happens when we start going to other pages:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_21.png" alt="ci_doctrine_day10_2" title="ci_doctrine_day10_2" width="318" height="58" class="aligncenter size-full wp-image-798" /></p>
<p>Now there is a &#8220;Prev&#8221; link which we didn&#8217;t have before. And we see links to 5 page numbers instead of 3.</p>
<p>Things change even more if we go deeper:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_3.png" alt="ci_doctrine_day10_3" title="ci_doctrine_day10_3" width="361" height="69" class="aligncenter size-full wp-image-800" /></p>
<p>Now there is also a &#8220;<< First" link, because the link for Page 1 is no longer visible.</p>
<p>One more:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_4.png" alt="ci_doctrine_day10_4" title="ci_doctrine_day10_4" width="328" height="53" class="aligncenter size-full wp-image-801" /></p>
<p>The &#8220;Last >>&#8221; link disappeared because we already have a link to Page 89, which is the last page.</p>
<p>Another example from Digg.com:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_5.png" alt="ci_doctrine_day10_5" title="ci_doctrine_day10_5" width="449" height="40" class="aligncenter size-full wp-image-802" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_6.png" alt="ci_doctrine_day10_6" title="ci_doctrine_day10_6" width="568" height="49" class="aligncenter size-full wp-image-803" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_7.png" alt="ci_doctrine_day10_7" title="ci_doctrine_day10_7" width="604" height="35" class="aligncenter size-full wp-image-804" /></p>
<p>As you can see they are doing it quite differently. It&#8217;s all a matter of preference.</p>
<p>Let&#8217;s look at the way they do the links.</p>
<p>CodeIgniter Forums:</p>
<pre>

http://codeigniter.com/forums/viewforum/59/

http://codeigniter.com/forums/viewforum/59/P25/

http://codeigniter.com/forums/viewforum/59/P50/
</pre>
<p>Those were the links for the first, second and third page. The first page gets no parameter as it works with default values. But the second and third pages have these &#8220;P25&#8243; and &#8220;P50&#8243; parameters at the end. Strangely enough these are not page numbers. They actually represent the <strong>offset</strong> value for the records instead, as they display 25 records per page.</p>
<p>Digg.com:</p>
<pre>

http://digg.com/all/upcoming

http://digg.com/all/upcoming/page2

http://digg.com/all/upcoming/page3
</pre>
<p>Again, we see a difference between the two websites. Digg.com prefers to use actual page numbers instead of offset numbers.</p>
<h4>Paginating Data</h4>
<p>This is the second part to this Pagination subject. Our code needs to be responsible for displaying the correct set of data on each page.</p>
<p>In terms of raw SQL, here is how you can get a set of records for a given page:</p>
<pre>
SELECT * FROM table LIMIT 50, 25
</pre>
<p>The LIMIT clause does the job. In this particular query, we fetch 25 records, starting after the first 50 records. So, 50 is the <strong>offset</strong> and 25 is the <strong>limit</strong>, i.e. the number of records.</p>
<p>With Doctrine we will be using DQL rather than raw SQL queries.</p>
<p>Let&#8217;s say we have a URL like they do on CodeIgniter forums:</p>
<pre>

http://codeigniter.com/forums/viewforum/59/P125/
</pre>
<p>That would translate into having the <strong>offset</strong> 125. And the <strong>limit</strong> would always be 25, because internally we decide to display 25 threads per page.</p>
<p>If we have a Digg style pagination URL:</p>
<pre>

http://digg.com/all/upcoming/page7
</pre>
<p>We need to multiply 7 with the &#8220;per page&#8221; count. So it could be 175 (7*25) offset and 25 limit, if the per page limit is set to 25. But we are not going to be using this method.</p>
<h3>CodeIgniter Pagination Library</h3>
<p>CodeIgniter comes with a nice simple <strong>Pagination Library</strong>, which we will be using. First, I will explain it briefly.</p>
<p>Let&#8217;s put some code in a test Controller.</p>
<ul>
<li>Edit: <strong>system/application/controllers/test.php</strong></li>
</ul>
<pre class="brush: php;">
class Test extends Controller {

	function paginate() {

		$this-&gt;load-&gt;library('pagination');

		$config['base_url'] = base_url() . &quot;test/paginate&quot;;
		$config['total_rows'] = '200';
		$config['per_page'] = '10';

		$this-&gt;pagination-&gt;initialize($config);

		echo $this-&gt;pagination-&gt;create_links();

	}

}
</pre>
<p>The code is very simple. We just provide the base url, number of total records, and the number of records per page.</p>
<p>The results look like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_8.png" alt="ci_doctrine_day10_8" title="ci_doctrine_day10_8" width="137" height="42" class="aligncenter size-full wp-image-806" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_9.png" alt="ci_doctrine_day10_9" title="ci_doctrine_day10_9" width="171" height="39" class="aligncenter size-full wp-image-807" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_10.png" alt="ci_doctrine_day10_10" title="ci_doctrine_day10_10" width="193" height="45" class="aligncenter size-full wp-image-808" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_111.png" alt="ci_doctrine_day10_11" title="ci_doctrine_day10_11" width="181" height="43" class="aligncenter size-full wp-image-809" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_12.png" alt="ci_doctrine_day10_12" title="ci_doctrine_day10_12" width="165" height="49" class="aligncenter size-full wp-image-810" /></p>
<p>And the links look like this:</p>
<pre>

http://localhost/ci_doctrine/test/paginate/

http://localhost/ci_doctrine/test/paginate/10

http://localhost/ci_doctrine/test/paginate/20

http://localhost/ci_doctrine/test/paginate/30

http://localhost/ci_doctrine/test/paginate/40
</pre>
<p>So this library puts the <strong>offset</strong> number, rather than the page number at the end of the URL&#8217;s.</p>
<p>Also, with this library you can customize the HTML structure of the links. You can see more information about that in the <a href="http://codeigniter.com/user_guide/libraries/pagination.html" ref="nofollow">documentation</a>.</p>
<h3>Adding More Data</h3>
<p>First we are going to add some more data to our database so we have something to paginate.</p>
<p>All we have to do is add more stuff to the fixture file we have been using before:</p>
<ul>
<li>Edit: <strong>system/fixtures/data.yml</strong></li>
</ul>
<pre class="brush: yaml;">
User:
  Admin:
    username: Administrator
    password: testing
    email: programming@gmail.com
  Test:
    username: TestUser
    password: mypass
    email: test@test.com
  Foo:
    username: Foobar
    password: mypass
    email: test2@test2.com

Forum:
  Forum_1:
    title: Introduce Yourself!
    description: &gt;
      Use this forum to introduce yourself to the CodeIgniter community,
      or to announce your new CI powered site.
  Forum_2:
    title: The Lounge
    description: &gt;
      CodeIgniter's social forum where you can discuss anything not related
      to development. No topics off limits... but be civil.
  Forum_3:
    title: CodeIgniter Discussion
    description: This forum is for general topics related to CodeIgniter.
  Forum_4:
    title: Code and Application Development
    description: &gt;
      Use the forum to discuss anything related to
      programming and code development.
  Forum_5:
    title: Ignited Code
    description: &gt;
      Use this forum to post plugins, libraries, or other code contributions,
      or to ask questions about any of them.

Category:
  Lounge:
    title: The CodeIgniter Lounge
    Forums: [Forum_1, Forum_2]
  Dev:
    title: CodeIgniter Development Forums
    Forums: [Forum_3, Forum_4, Forum_5]

Thread:
  Thread_1:
    title: Hi there!
    Forum: Forum_1
  Thread_2:
    title: Greetings to all
    Forum: Forum_1
  Thread_3:
    title: Sed vitae ligula erat
    Forum: Forum_3
  Thread_4:
    title: Vivamus laoreet quam vitae mauris tempus
    Forum: Forum_3
  Thread_5:
    title: Maecenas vel dolor odio
    Forum: Forum_3
  Thread_6:
    title: In nec justo at orci fermentum
    Forum: Forum_3
  Thread_7:
    title: Nullam volutpat laoreet orci
    Forum: Forum_3
  Thread_8:
    title: Sed sodales augue vel elit
    Forum: Forum_3
  Thread_9:
    title: Integer posuere luctus metus
    Forum: Forum_3
  Thread_10:
    title: Maecenas ut mauris eget odio pharetra
    Forum: Forum_3
  Thread_11:
    title: Pellentesque lacinia nibh vel lacus
    Forum: Forum_3
  Thread_12:
    title: Nunc facilisis nibh a nulla laoreet in ultricies
    Forum: Forum_3
  Thread_13:
    title: Maecenas pretium nisi eget nunc rutrum quis
    Forum: Forum_3
  Thread_14:
    title: Etiam at ligula leo
    Forum: Forum_3
  Thread_15:
    title: Vivamus tempus semper libero
    Forum: Forum_3
  Thread_16:
    title: Phasellus venenatis consectetur quam
    Forum: Forum_3
  Thread_17:
    title: Nam sagittis elementum turpis
    Forum: Forum_3
  Thread_18:
    title: Sed at odio id ante rutrum sodales
    Forum: Forum_3
  Thread_19:
    title: Praesent eget lorem nec odio
    Forum: Forum_3
  Thread_20:
    title: Donec at enim sit amet quam
    Forum: Forum_3
  Thread_21:
    title: Ut sit amet ante nec leo volutpat
    Forum: Forum_3
  Thread_22:
    title: Pellentesque accumsan orci nec
    Forum: Forum_3
  Thread_23:
    title: Curabitur convallis sapien in dolor feugiat
    Forum: Forum_3
  Thread_24:
    title: Aenean sodales massa in dui ultrices
    Forum: Forum_3

Post:
  Post_1:
    Thread: Thread_1
    User: Test
    created_at: '2009-11-20 01:20:30'
    updated_at: '2009-11-20 01:20:30'
    content: &gt;
      Hello everyone! My name is Test, and I go to school at
      Test Institute of Technology in the US.
      I just found CodeIgniter some time last week and have been
      reading through the documentation trying to get myself acquainted.

      Hopefully the forums will be a great help! I already have some questions.
      Thanks!
  Post_2:
    Thread: Thread_1
    User: Admin
    created_at: '2009-11-20 02:15:33'
    updated_at: '2009-11-20 02:15:33'
    content: Welcome Test! Nice to meet you.
  Post_3:
    Thread: Thread_2
    User: Foo
    created_at: '2009-11-19 12:14:50'
    updated_at: '2009-11-19 12:14:50'
    content: I am new here. Just wanted to say hi.
  Post_4:
    Thread: Thread_3
    User: Foo
    created_at: '2009-12-01 12:14:50'
    updated_at: '2009-12-01 12:14:50'
    content: Vivamus ultricies hendrerit justo, sit amet semper nulla scelerisque pulvinar.
  Post_5:
    Thread: Thread_4
    User: Foo
    created_at: '2009-12-02 12:14:50'
    updated_at: '2009-12-02 12:14:50'
    content: Sed luctus enim ut magna pellentesque mollis.
  Post_6:
    Thread: Thread_5
    User: Foo
    created_at: '2009-12-03 12:14:50'
    updated_at: '2009-12-03 12:14:50'
    content: Nam id nisi dolor, vel interdum turpis.
  Post_7:
    Thread: Thread_6
    User: Foo
    created_at: '2009-12-04 12:14:50'
    updated_at: '2009-12-04 12:14:50'
    content: Donec volutpat accumsan lorem, at euismod metus lobortis viverra.
  Post_8:
    Thread: Thread_7
    User: Foo
    created_at: '2009-12-05 12:14:50'
    updated_at: '2009-12-05 12:14:50'
    content: Nulla vestibulum erat ac nisi convallis rutrum.
  Post_9:
    Thread: Thread_8
    User: Foo
    created_at: '2009-12-06 12:14:50'
    updated_at: '2009-12-06 12:14:50'
    content: Nulla pharetra tortor id ante sollicitudin sodales.
  Post_10:
    Thread: Thread_9
    User: Foo
    created_at: '2009-12-07 12:14:50'
    updated_at: '2009-12-07 12:14:50'
    content: Cras id metus a elit mattis blandit et aliquet diam.
  Post_11:
    Thread: Thread_10
    User: Foo
    created_at: '2009-12-08 12:14:50'
    updated_at: '2009-12-08 12:14:50'
    content: Nunc non felis vitae dolor posuere aliquam non et augue.
  Post_12:
    Thread: Thread_11
    User: Foo
    created_at: '2009-12-09 12:14:50'
    updated_at: '2009-12-09 12:14:50'
    content: Nam et velit ac tellus interdum adipiscing.
  Post_13:
    Thread: Thread_12
    User: Foo
    created_at: '2009-12-10 12:14:50'
    updated_at: '2009-12-10 12:14:50'
    content: Donec viverra leo mauris, ac convallis turpis.
  Post_14:
    Thread: Thread_13
    User: Foo
    created_at: '2009-12-11 12:14:50'
    updated_at: '2009-12-11 12:14:50'
    content: Integer sagittis nisl ut nisi euismod in dignissim massa sagittis.
  Post_15:
    Thread: Thread_14
    User: Foo
    created_at: '2009-12-12 12:14:50'
    updated_at: '2009-12-12 12:14:50'
    content: Integer vel lectus mollis quam sollicitudin porta.
  Post_16:
    Thread: Thread_15
    User: Foo
    created_at: '2009-12-13 12:14:50'
    updated_at: '2009-12-13 12:14:50'
    content: Etiam tempor luctus sem, at consequat enim posuere in.
  Post_17:
    Thread: Thread_16
    User: Foo
    created_at: '2009-12-14 12:14:50'
    updated_at: '2009-12-14 12:14:50'
    content: Proin placerat lectus dolor, quis viverra ante.
  Post_18:
    Thread: Thread_17
    User: Foo
    created_at: '2009-12-15 12:14:50'
    updated_at: '2009-12-15 12:14:50'
    content: Maecenas ullamcorper commodo leo, lobortis molestie turpis cursus sit amet.
  Post_19:
    Thread: Thread_18
    User: Foo
    created_at: '2009-12-16 12:14:50'
    updated_at: '2009-12-16 12:14:50'
    content: Integer tincidunt facilisis dolor, vitae pellentesque turpis rutrum sed.
  Post_20:
    Thread: Thread_19
    User: Foo
    created_at: '2009-12-17 12:14:50'
    updated_at: '2009-12-17 12:14:50'
    content: Donec eget lacus a nibh volutpat venenatis quis a felis.
  Post_21:
    Thread: Thread_20
    User: Foo
    created_at: '2009-12-18 12:14:50'
    updated_at: '2009-12-18 12:14:50'
    content: Nam fringilla tellus quis augue elementum eleifend.
  Post_22:
    Thread: Thread_21
    User: Foo
    created_at: '2009-12-19 12:14:50'
    updated_at: '2009-12-19 12:14:50'
    content: Nullam sollicitudin nulla at orci accumsan eget ultrices felis vehicula.
  Post_23:
    Thread: Thread_22
    User: Foo
    created_at: '2009-12-20 12:14:50'
    updated_at: '2009-12-20 12:14:50'
    content: Nullam sit amet purus nec mauris convallis tincidunt sodales eget nunc.
  Post_24:
    Thread: Thread_23
    User: Foo
    created_at: '2009-12-21 12:14:50'
    updated_at: '2009-12-21 12:14:50'
    content: Praesent in eros non elit ultricies tincidunt a nec tellus.
  Post_25:
    Thread: Thread_24
    User: Foo
    created_at: '2009-12-22 12:14:50'
    updated_at: '2009-12-22 12:14:50'
    content: Aenean ac nisl a sapien pulvinar gravida et quis metus.
</pre>
<p>Now load this fixture:</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/load_fixtures" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/load_fixtures</a></li>
<li>Hit the button.</li>
<li>Go home: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p>You should see this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_13.png" alt="ci_doctrine_day10_13" title="ci_doctrine_day10_13" width="600" height="434" class="aligncenter size-full wp-image-812" /></p>
<ul>
<li>Click the &#8220;CodeIgniter Discussion&#8221; link</li>
</ul>
<p>You should see:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_14.png" alt="ci_doctrine_day10_14" title="ci_doctrine_day10_14" width="600" height="869" class="aligncenter size-full wp-image-813" /></p>
<h3>Sorting By Last Post Date</h3>
<p>As it is, the Threads are not being sorted by a specific column, because we did not add that to the DQL query last time. They need to be sorted by the &#8220;created_at&#8221; date of the last Post in that Thread, in descending order. Let&#8217;s fix that now.</p>
<ul>
<li>Edit: <strong>system/application/models/forum.php</strong></li>
</ul>
<pre class="brush: php; highlight: [11,15];">
class Forum extends Doctrine_Record {

// ...

	public function getThreadsArray() {

		$threads = Doctrine_Query::create()
			-&gt;select('t.title')
			-&gt;addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
			-&gt;addSelect('MIN(p.id) as first_post_id')
			-&gt;addSelect('MAX(p.created_at) as last_post_date')
			-&gt;from('Thread t, t.Posts p')
			-&gt;where('t.forum_id = ?', $this-&gt;id)
			-&gt;groupBy('t.id')
			-&gt;orderBy('last_post_date DESC')
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;execute();

		foreach ($threads as &amp;$thread) {

			$post = Doctrine_Query::create()
				-&gt;select('p.created_at, u.username')
				-&gt;from('Post p, p.User u')
				-&gt;where('p.id = ?', $thread['Posts'][0]['first_post_id'])
				-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
				-&gt;fetchOne();

			$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
			$thread['created_at'] = $post['created_at'];
			$thread['username'] = $post['User']['username'];
			$thread['user_id'] = $post['User']['id'];
			unset($thread['Posts']);

		}

		return $threads;

	}

}
</pre>
<p>The highlighted lines have been added. They should be self-explanatory.</p>
<p>We should also update the View so it shows that date.</p>
<ul>
<li>Edit: <strong>system/application/views/forum.php</strong></li>
</ul>
<pre class="brush: php; highlight: [14]; html-script: true;">
&lt;h2&gt;&lt;?php echo $title ?&gt;&lt;/h2&gt;

&lt;?php foreach($threads as $thread): ?&gt;
&lt;div class=&quot;thread&quot;&gt;

	&lt;h3&gt;
		&lt;?php echo anchor('threads/display/'.$thread['id'], $thread['title']) ?&gt;
		(&lt;?php echo $thread['num_replies']; ?&gt; replies)
	&lt;/h3&gt;

	&lt;div&gt;
		Author: &lt;em&gt;&lt;?php echo anchor('profile/display/'.$thread['user_id'],
								$thread['username']); ?&gt;&lt;/em&gt;,
		Last Post: &lt;em&gt;&lt;?php echo $thread['last_post_date']; ?&gt;&lt;/em&gt;
	&lt;/div&gt;

&lt;/div&gt;
&lt;?php endforeach; ?&gt;
</pre>
<h3>Pagination Links</h3>
<p>Now, to do pagination, we need 3 pieces of information:</p>
<ul>
<li><strong>Total number of records.</strong> In our case, number of Threads.</li>
<li><strong>Number of records per page.</strong> We can pick any number. I will set it to 4 for now so we can have several pages.</li>
<li><strong>Current page number or record offset.</strong> Since CodeIgniter Pagination library works with the offset number, rather than page number, that&#8217;s what we will use.</li>
</ul>
<p>We need to edit the View, the Model and the Controller.</p>
<h4>The View</h4>
<p>Let&#8217;s set the output of the pagination links in the View.</p>
<ul>
<li>Edit: <strong>system/application/views/forum.php</strong></li>
</ul>
<pre class="brush: php; highlight: [20,21,22,23,24]; html-script: true;">
&lt;h2&gt;&lt;?php echo $title ?&gt;&lt;/h2&gt;

&lt;?php foreach($threads as $thread): ?&gt;
&lt;div class=&quot;thread&quot;&gt;

	&lt;h3&gt;
		&lt;?php echo anchor('threads/display/'.$thread['id'], $thread['title']) ?&gt;
		(&lt;?php echo $thread['num_replies']; ?&gt; replies)
	&lt;/h3&gt;

	&lt;div&gt;
		Author: &lt;em&gt;&lt;?php echo anchor('profile/display/'.$thread['user_id'],
								$thread['username']); ?&gt;&lt;/em&gt;,
		Last Post: &lt;em&gt;&lt;?php echo $thread['last_post_date']; ?&gt;&lt;/em&gt;
	&lt;/div&gt;

&lt;/div&gt;
&lt;?php endforeach; ?&gt;

&lt;?php if (isset($pagination)): ?&gt;
	&lt;div class=&quot;pagination&quot;&gt;
		Pages: &lt;?php echo $pagination; ?&gt;
	&lt;/div&gt;
&lt;?php endif; ?&gt;
</pre>
<p>At line 20, we check to see if the $pagination variable is set, which will contain the pagination links, because sometimes there won&#8217;t be enough records to paginate.</p>
<h4>The Model</h4>
<p>Now let&#8217;s modify the Forum Model.</p>
<ul>
<li>Edit: <strong>system/application/models/forum.php</strong></li>
</ul>
<pre class="brush: php; highlight: [21,30,34,45,46];">
&lt;?php
class Forum extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
		$this-&gt;hasColumn('description', 'string', 255);
		$this-&gt;hasColumn('category_id', 'integer', 4);
	}

	public function setUp() {
		$this-&gt;hasOne('Category', array(
			'local' =&gt; 'category_id',
			'foreign' =&gt; 'id'
		));
		$this-&gt;hasMany('Thread as Threads', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'forum_id'
		));
	}

	public function numThreads() {

		$result = Doctrine_Query::create()
			-&gt;select('COUNT(*) as num_threads')
			-&gt;from('Thread')
			-&gt;where('forum_id = ?', $this-&gt;id)
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;fetchOne();

		return $result['num_threads'];

	}

	public function getThreadsArray($offset, $limit) {

		$threads = Doctrine_Query::create()
			-&gt;select('t.title')
			-&gt;addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
			-&gt;addSelect('MIN(p.id) as first_post_id')
			-&gt;addSelect('MAX(p.created_at) as last_post_date')
			-&gt;from('Thread t, t.Posts p')
			-&gt;where('t.forum_id = ?', $this-&gt;id)
			-&gt;groupBy('t.id')
			-&gt;orderBy('last_post_date DESC')
			-&gt;limit($limit)
			-&gt;offset($offset)
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;execute();

		foreach ($threads as &amp;$thread) {

			$post = Doctrine_Query::create()
				-&gt;select('p.created_at, u.username')
				-&gt;from('Post p, p.User u')
				-&gt;where('p.id = ?', $thread['Posts'][0]['first_post_id'])
				-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
				-&gt;fetchOne();

			$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
			$thread['created_at'] = $post['created_at'];
			$thread['username'] = $post['User']['username'];
			$thread['user_id'] = $post['User']['id'];
			unset($thread['Posts']);

		}

		return $threads;

	}

}
</pre>
<p><strong>Line 21:</strong> Added new method named &#8220;numThreads&#8221;, since we are going to need the total number of Threads. </p>
<p>Note: I know that it would have been simpler to just use this code: &#8220;$this->Threads->count()&#8221;. However, unfortunately Doctrine creates a very inefficient query when we do that, that&#8217;s why I used a DQL query instead.</p>
<p><strong>Line 34:</strong> Just added 2 parameters to the existing function, since we are only interested in the Thread records for a given page.</p>
<p><strong>Lines 45-46:</strong> Here we use the given $offset and $limit parameters to limit the DQL query results.</p>
<h4>The Controller</h4>
<p>Finally we update the Forums Controller.</p>
<ul>
<li>Edit: <strong>system/application/controllers/forums.php</strong></li>
</ul>
<pre class="brush: php; highlight: [4,6,12,13,18,21,22,23,24,25,26,27,28,29,30,31];">
&lt;?php
class Forums extends Controller {

	public function display($id, $offset = 0) {

		$per_page = 4;

		$forum = Doctrine::getTable('Forum')-&gt;find($id);

		$vars['title'] = $forum['title'];
		$vars['threads'] = $forum-&gt;getThreadsArray(
			$offset,
			$per_page
		);
		$vars['content_view'] = 'forum';
		$vars['container_css'] = 'forum';

		$num_threads = $forum-&gt;numThreads();

		// do we have enough to paginate
		if ($num_threads &gt; $per_page) {
			// PAGINATION
			$this-&gt;load-&gt;library('pagination');
			$config['base_url'] = base_url() . &quot;forums/display/$id&quot;;
			$config['total_rows'] = $num_threads;
			$config['per_page'] = $per_page;
			$config['uri_segment'] = 4;
			$this-&gt;pagination-&gt;initialize($config);

			$vars['pagination'] = $this-&gt;pagination-&gt;create_links();
		}

		$this-&gt;load-&gt;view('template', $vars);

	}

}
</pre>
<p>Updated lines are highlighted.</p>
<p><strong>Line 4:</strong> Now there is a second parameter named $offset, because the paginated URL&#8217;s will contain the offset after the Forum id.</p>
<p><strong>Line 6:</strong> Here we pick a number of Threads per page. Normally it could be 10, 20 or 25, but for this test we are picking a smaller number.</p>
<p><strong>Lines 12-13:</strong> We send the 2 parameters that the getThreadsArray method is expecting.</p>
<p><strong>Line 21:</strong> We only do pagination if there are more records than the $per_page number.</p>
<p><strong>Line 27:</strong> We have to set the &#8216;uri_segment&#8217; setting for the Pagination library. This is the uri segment that will carry the offset number. If not set, it defaults to uri segment 3. For example the URL will look like this:</p>
<pre>

http://localhost/ci_doctrine/forums/display/53/8
</pre>
<p>&#8220;forums&#8221; is uri segment 1, &#8220;display&#8221; is uri segment 2, &#8220;53&#8243; is uri segment 3 and the Forum id, &#8220;8&#8243; is the URI segment 4 and the $offset variable.</p>
<h4>The Result</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
<li>Click the forum name: &#8220;CodeIgniter Discussion&#8221;</li>
</ul>
<p>You should see:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_15.png" alt="ci_doctrine_day10_15" title="ci_doctrine_day10_15" width="600" height="313" class="aligncenter size-full wp-image-818" /></p>
<p>Continue clicking on the pagination links:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_16.png" alt="ci_doctrine_day10_16" title="ci_doctrine_day10_16" width="185" height="35" class="aligncenter size-full wp-image-819" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_17.png" alt="ci_doctrine_day10_17" title="ci_doctrine_day10_17" width="183" height="34" class="aligncenter size-full wp-image-820" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/ci_doctrine_day10_18.png" alt="ci_doctrine_day10_18" title="ci_doctrine_day10_18" width="148" height="30" class="aligncenter size-full wp-image-821" /></p>
<p>Seems to be working <img src='http://www.phpandstuff.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<h3>Stay Tuned</h3>
<p>Thank you for reading, and sorry about the delay. We still have more work to do. See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/Xd3VQs71vHE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination/feed</wfw:commentRss>
		<slash:comments>45</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch. Day 9 – Templates &amp; Data Hydrators</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/q0rfn_TrIWE/codeigniter-doctrine-scratch-day-9-templates-data-hydrators</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators#comments</comments>
		<pubDate>Mon, 14 Dec 2009 00:04:45 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=704</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this article we are going to create <strong>Templates</strong> (with CodeIgniter) to keep our Views organized, and avoid repeating the same HTML code. Also we are going to learn about <strong>Doctrine Data Hydrators</strong> to see alternative ways to structure the data returned from the database.

<div class="clear"></div><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_2.png" alt="ci_doctrine_day9_2" title="ci_doctrine_day9_2" width="580" height="369" class="aligncenter size-full wp-image-720" />]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-9-templates-data-hydrators"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this article we are going to create <strong>Templates</strong> (with CodeIgniter) to keep our Views organized, and avoid repeating the same HTML code. Also we are going to learn about <strong>Doctrine Data Hydrators</strong> to see alternative ways to structure the data returned from the database.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Templates</h3>
<h4>What and Why?</h4>
<p>The term <strong>Template</strong> might be a little ambiguous right now. Maybe you are already thinking of <strong>Views</strong> as Templates. Which is mostly true. However, there is a problem with using separate Views for every single page in our application. There will be headers, footers and other content that will be repeated everywhere. That&#8217;s why there is a need for actual Templates for our Views.</p>
<p>For example, we will be creating a new View for the Forum pages. It will look mostly the same as the home page, using the same css stylesheet, same header, same user control panel, etc&#8230; There will be other Views later that will be the same way. If we ever make a change to any of these common parts, we don&#8217;t want to go through every single View. There should be Views that have the common html output that we can quickly edit. Using Templates will enable us to do just that, and maybe more.</p>
<h4>Creating a Template</h4>
<p>Let&#8217;s create our first Template, which is actually going to be a View itself. The idea is to keep all the common elements in one file, and take out the variable stuff.</p>
<p>For example, take a look at this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_2.png" alt="ci_doctrine_day9_2" title="ci_doctrine_day9_2" width="580" height="369" class="aligncenter size-full wp-image-720" /></p>
<p>The content section is definitely going to change from page to page. Also, I would like to take out the user controls section, so it can have its own View. We&#8217;re going to replace these with some code instead.</p>
<ul>
<li>Create: <strong>system/application/views/template.php</strong></li>
</ul>
<pre class="brush: php; highlight: [5,11,14,19]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;&lt;?php echo $title; ?&gt; | CI+Doctrine Message Board&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;&lt;?php echo $container_css; ?&gt; container&quot;&gt;

	&lt;div class=&quot;user_controls&quot;&gt;
		&lt;?php $this-&gt;load-&gt;view('user_controls'); ?&gt;
	&lt;/div&gt;

	&lt;h1&gt;CI+Doctrine Message Board&lt;/h1&gt;

	&lt;?php $this-&gt;load-&gt;view($content_view); ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I have copied the contents of the Home View we created before, and replaced a few things.</p>
<p><strong>Line 14:</strong> The code for the user_controls div will now be found in a View named user_controls.php.<br />
<strong>Line 19:</strong> $content_view is the name of the View that will be loaded to fill up the content area. For example, we will use a View named forum_list for the home page. The controller will have to pass this variable.<br />
<strong>Line 5:</strong> Now the page title can be passed as a $title variable.<br />
<strong>Line 11:</strong> We can apply a different css class for the container div on every page.</p>
<p>As you can see, a View can load other Views. That&#8217;s a big help in creating Templates. Now, all Controllers can just load this Template View, and they can pass the name for a content View that will be loaded in the middle of the page.</p>
<p>Now let&#8217;s create the <strong>user_controls</strong> View.</p>
<ul>
<li>Create: <strong>system/application/views/user_controls.php</strong></li>
</ul>
<pre class="brush: php; html-script: true;">
&lt;?php if ($user = Current_User::user()): ?&gt;
	Hello, &lt;em&gt;&lt;?php echo $user-&gt;username; ?&gt;&lt;/em&gt; &lt;br/&gt;
	&lt;?php echo anchor('logout', 'Logout'); ?&gt;
&lt;?php else: ?&gt;
	&lt;?php echo anchor('login','Login'); ?&gt; |
	&lt;?php echo anchor('signup', 'Register'); ?&gt;
&lt;?php endif; ?&gt;
</pre>
<p>Basically it&#8217;s the same code as before, but now it is in its own View file.</p>
<p>Now let&#8217;s create the forum_list View.</p>
<ul>
<li>Create: <strong>system/application/views/forum_list.php</strong></li>
</ul>
<pre class="brush: php; html-script: true;">
&lt;?php foreach($categories as $category): ?&gt;
&lt;div class=&quot;category&quot;&gt;

	&lt;h2&gt;&lt;?php echo $category-&gt;title; ?&gt;&lt;/h2&gt;

	&lt;?php foreach($category-&gt;Forums as $forum): ?&gt;
	&lt;div class=&quot;forum&quot;&gt;

		&lt;h3&gt;
			&lt;?php echo anchor('forums/display/'.$forum-&gt;id, $forum-&gt;title) ?&gt;
			(&lt;?php echo $forum-&gt;Threads[0]-&gt;num_threads; ?&gt; threads)
		&lt;/h3&gt;

		&lt;div class=&quot;description&quot;&gt;
			&lt;?php echo $forum-&gt;description; ?&gt;
		&lt;/div&gt;

	&lt;/div&gt;
	&lt;?php endforeach; ?&gt;

&lt;/div&gt;
&lt;?php endforeach; ?&gt;
</pre>
<p>This code is also taken from the middle section of the old Home View. (I only made a small change to the link at line 10.)</p>
<p>Now we can get rid of the Home View file.</p>
<ul>
<li>Delete: <strong>system/application/views/home.php</strong></li>
</ul>
<h4>Updating the Home Controller</h4>
<p>This new Template needs to know what content to load, what the title of the page is, etc&#8230; So we need to update the Home Controller.</p>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php; highlight: [14,15,16,18];">
&lt;?php
class Home extends Controller {

	public function index() {

		$vars['categories'] = Doctrine_Query::create()
			-&gt;select('c.title, f.title, f.description')
			-&gt;addSelect('t.id, COUNT(t.id) as num_threads')
			-&gt;from('Category c, c.Forums f')
			-&gt;leftJoin('f.Threads t')
			-&gt;groupBy('f.id')
			-&gt;execute();

		$vars['title'] = 'Home';
		$vars['content_view'] = 'forum_list';
		$vars['container_css'] = 'forums';

		$this-&gt;load-&gt;view('template', $vars);
	}	

}
</pre>
<p>The changes are only the highlighted lines. We are now passing the page title, name of the content View, and a CSS class name for styling purposes. Then we load the View named &#8216;template&#8217; instead of &#8216;home&#8217; (since we deleted that one).</p>
<h4>See the Results</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p>The page should look exactly the same as before:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_1.png" alt="ci_doctrine_day9_1" title="ci_doctrine_day9_1" width="590" height="416" class="aligncenter size-full wp-image-707" /></p>
<p>Later in this article we are going to use this Template to build the Forum page, that lists Threads in a Forum.</p>
<h3>Data Hydrators (Doctrine)</h3>
<p>Our Doctrine Models extend the <strong>Doctrine_Record</strong> class. We have been using instances of this class for representing and persisting the database records. Also, we have been using instances of the <strong>Doctrine_Collection</strong> class when dealing with multiple records (e.g. fetching multiple rows with DQL).</p>
<p>With <strong>Data Hydrators</strong>, we can work with the data in other structure formats. For example, with DQL we can have it return the results of a SELECT query as an <strong>Array</strong> instead of Doctrine_Collection.</p>
<h4>HYDRATE_SCALAR</h4>
<p>This returns an array similar to what you would get from doing raw SQL queries.</p>
<pre class="brush: php; highlight: [5];">
$category = Doctrine_Query::create()
	-&gt;select('c.*, f.*')
	-&gt;from('Category c, c.Forums f')
	-&gt;where('c.id = ?', 1)
	-&gt;setHydrationMode(Doctrine::HYDRATE_SCALAR)
	-&gt;execute();

print_r($category);
/* output:
Array
(
    [0] =&gt; Array
        (
            [c_id] =&gt; 1
            [c_title] =&gt; The CodeIgniter Lounge
            [f_id] =&gt; 1
            [f_title] =&gt; Introduce Yourself!
            [f_description] =&gt; Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.

            [f_category_id] =&gt; 1
        )

    [1] =&gt; Array
        (
            [c_id] =&gt; 1
            [c_title] =&gt; The CodeIgniter Lounge
            [f_id] =&gt; 2
            [f_title] =&gt; The Lounge
            [f_description] =&gt; CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.

            [f_category_id] =&gt; 1
        )

)
*/
</pre>
<p>We fetched the Category with id 1, and it&#8217;s associated Forums. There were 2 Forums under that Category, so the result contains 2 rows of data.</p>
<p>If I run the same raw query from phpMyAdmin, it looks like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_4.png" alt="ci_doctrine_day9_4" title="ci_doctrine_day9_4" width="590" height="414" class="aligncenter size-full wp-image-739" /></p>
<p>Note that the Category title is repeated in both rows, because of the nature of JOIN queries. That is also the case in the Array that was returned by DQL.</p>
<h4>HYDRATE_ARRAY</h4>
<p>This also returns an Array. But this time, it will have a nice multi-tier structure based on the Model relationships.</p>
<pre class="brush: php; highlight: [5];">
$category = Doctrine_Query::create()
	-&gt;select('c.*, f.*')
	-&gt;from('Category c, c.Forums f')
	-&gt;where('c.id = ?', 1)
	-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
	-&gt;execute();

print_r($category);
/* output:
Array
(
    [0] =&gt; Array
        (
            [id] =&gt; 1
            [title] =&gt; The CodeIgniter Lounge
            [Forums] =&gt; Array
                (
                    [0] =&gt; Array
                        (
                            [id] =&gt; 1
                            [title] =&gt; Introduce Yourself!
                            [description] =&gt; Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.

                            [category_id] =&gt; 1
                        )

                    [1] =&gt; Array
                        (
                            [id] =&gt; 2
                            [title] =&gt; The Lounge
                            [description] =&gt; CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.

                            [category_id] =&gt; 1
                        )

                )

        )

)
*/
</pre>
<p>Now we have a multidimensional Array. As you can see, this time the Category info is not repeated. And Forums is a sub-array under the Category. Also the keys of the array retain their original names, like &#8216;title&#8217;, instead of &#8216;c_title&#8217;.</p>
<h4>Other Hydrators</h4>
<p>By default Doctrine is using HYDRATE_RECORD, that causes objects to be returned. And there are a few other Hydrators you can read about here: <a href="http://www.doctrine-project.org/documentation/manual/1_2/en/data-hydrators" rel="nofollow">http://www.doctrine-project.org/documentation/manual/1_2/en/data-hydrators</a></p>
<h4>Why?</h4>
<p>Hydrators can have certain performance benefits. Creating an array is faster than creating an object that has lots of overhead. And arrays take less memory too.</p>
<p>Also there are things you can do with arrays that you cannot do with a Doctrine object. If you prefer to handle the data as an array, Hydration is the way to go.</p>
<p>We are going to be using HYDRATE_ARRAY to fetch a list of Threads in the following sections, to demonstrate the usage.</p>
<h3>CSS Changes</h3>
<p>Before we move on, I want to make some CSS changes, so the new pages we build will be styled.</p>
<ul>
<li>Edit: <strong>css/style.css</strong></li>
</ul>
<pre class="brush: css;">
body {
	font-family: &quot;Trebuchet MS&quot;,Arial;
	font-size: 14px;
	background-color: #212426;
	color: #B9AA81;
}
a			{color: #FFF;}
a:hover		{color: #B9AA81;}
input, textarea, select {
	font-family:inherit; font-size:inherit;	font-weight:inherit;
}
.container	{width: 720px; margin: auto;}
/* FORUMS -----------------------------------------*/
.forums.container h2 {
	font-size: 16px;
	color: #000;
	padding: 5px 10px 5px 10px;
	margin: 0px;
	background-color: #BBB;
	-moz-border-radius-topleft: 6px;
	-moz-border-radius-topright: 6px;
	-webkit-border-top-left-radius: 6px;
	-webkit-border-top-right-radius: 6px;
}
.forums.container h3			{font-size: 15px; margin: 0px;}
.forums.container .category 	{margin-bottom: 40px;}
.forums.container .forum 		{border-bottom: 1px solid #666;	padding: 10px;}
.forums.container .forum .description	{font-size: 14px;}
/* FORUM -----------------------------------------*/
.forum.container h2 {
	font-size: 16px;
	color: #000;
	padding: 5px 10px 5px 10px;
	margin: 0px;
	background-color: #BBB;
	-moz-border-radius-topleft: 6px;
	-moz-border-radius-topright: 6px;
	-webkit-border-top-left-radius: 6px;
	-webkit-border-top-right-radius: 6px;
}
.forum.container h3			{font-size: 15px; margin: 0px 0px 5px 0px;}
.forum.container .thread	{border-bottom: 1px solid #666;	padding: 10px;}
/* SIGNUP FORM ------------------------------------*/
#signup_form	{margin: auto; width: 360px; font-size: 16px;}
#signup_form .heading {
	text-align: center;	font-size: 22px; font-weight: bold;	color: #B9AA81;
}
#signup_form form {
	background-color: #B9AA81;
	padding: 10px;
	-moz-border-radius: 8px;
	-webkit-border-radius: 8px;
}
#signup_form form label {font-weight: bold;	color: #11151E;}
#signup_form form input[type=text],input[type=password] {
	width: 316px;
	font-weight: bold;
	padding: 8px;
	border: 1px solid #FFF;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}
#signup_form form input[type=submit] {
	display: block;
	margin: auto;
	width: 200px;
	font-size: 18px;
	background-color: #FFF;
	border: 1px solid #BBB;
}
#signup_form form input[type=submit]:hover {border-color: #000;}
#signup_form .error {font-size: 13px; color: #690C07; font-style: italic; }
/* USER CONTROL BOX -------------------------------*/
.user_controls {float: right; text-align: right;}
</pre>
<h3>Forum Pages</h3>
<p>Now, let&#8217;s use what we have, to build the Forum Pages. These pages will list all the Threads, in a given Forum.</p>
<p>Currently, on the Home page we have links like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_3.png" alt="ci_doctrine_day9_3" title="ci_doctrine_day9_3" width="585" height="235" class="aligncenter size-full wp-image-727" /></p>
<p>We created these links, because we expect to have a Controller named &#8216;Forums&#8217; that has a function named &#8216;Display&#8217;. </p>
<p>There is also an ID number at the end of the URL. That is passed to the Controller function as a parameter.</p>
<p>This Controller is supposed to load a page that lists all the Threads in that particular Forum.</p>
<h4>Forums Controller</h4>
<p>The skeleton structure first:</p>
<ul>
<li>Create: <strong>system/application/controllers/forums.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Forums extends Controller {

	public function display($id) {

	}

}
</pre>
<p>It looks like any other Controller. But this time we are expecting a parameter being passed to the <strong>display()</strong> method. The string that comes after <strong>/forums/display/</strong> in the URL automatically gets passed as the first parameter to that method.</p>
<p>For example: </p>
<pre>

http://localhost/ci_doctrine/forums/display/1
</pre>
<p>Will call <strong>display(1)</strong> in the Forums Class. We are going to use that parameter as the Forum ID. Then we need to display the Forum page.</p>
<p>The Controller needs to obtain the following pieces of data, and pass them on to the View:</p>
<ul>
<li>The <strong>title</strong> of the Forum.</li>
<li>Each <strong>Thread</strong> under the Forum.</li>
<li>For each Thread, we need Thread <strong>title</strong>, <strong>create date</strong>, <strong>author name</strong> and <strong>number of replies</strong>.</li>
</ul>
<p>Please note that the create date of the Thread is not part of the Thread Model (or table), because of the way we designed the Models. The first Post inside of the Thread carries a create date already, so we did not want to duplicate that data again. Same thing goes for the author (or user_id) of the Thread.</p>
<p>Now let&#8217;s add some code to make this happen:</p>
<pre class="brush: php; highlight: [9];">
&lt;?php
class Forums extends Controller {

	public function display($id) {

		$forum = Doctrine::getTable('Forum')-&gt;find($id);

		$vars['title'] = $forum['title'];
		$vars['threads'] = $forum-&gt;getThreadsArray();
		$vars['content_view'] = 'forum';
		$vars['container_css'] = 'forum';

		$this-&gt;load-&gt;view('template', $vars);

	}

}
</pre>
<p>First we get an instance of the Forum object with the id $id. Then we create the array of variables that will be passed to the template View.</p>
<p>At line 9 you can see that I am attempting to call a method named <strong>getThreadsArray()</strong>. This does not exist yet, so let&#8217;s build it.</p>
<p>The idea is to create a method that can return all associated Threads in an array structure. But we also want each Thread to have information such as: number of replies, date (of first post), author of (first post).</p>
<ul>
<li>Edit: <strong>system/application/models/forum.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Forum extends Doctrine_Record {

// ...

	public function getThreadsArray() {

		$threads = Doctrine_Query::create()
			-&gt;select('t.title')
			-&gt;addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
			-&gt;addSelect('MIN(p.id) as first_post_id')
			-&gt;from('Thread t, t.Posts p')
			-&gt;where('t.forum_id = ?', $this-&gt;id)
			-&gt;groupBy('t.id')
			-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
			-&gt;execute();

		foreach ($threads as &amp;$thread) {

			$post = Doctrine_Query::create()
				-&gt;select('p.created_at, u.username')
				-&gt;from('Post p, p.User u')
				-&gt;where('p.id = ?', $thread['Posts'][0]['first_post_id'])
				-&gt;setHydrationMode(Doctrine::HYDRATE_ARRAY)
				-&gt;fetchOne();

			$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
			$thread['created_at'] = $post['created_at'];
			$thread['username'] = $post['User']['username'];
			$thread['user_id'] = $post['User']['id'];
			unset($thread['Posts']);

		}

		return $threads;

	}
</pre>
<p>In the first DQL query:</p>
<p>Look at the <strong>from()</strong> call first. We are joining 2 Models (Thread, Post) because we need information from both. </p>
<p>Now look at the <strong>select()</strong> and <strong>addSelect()</strong> calls to see what we are getting:<br />
- We select the title for every Thread.<br />
- Then we select the number of Posts under each Thread by using <strong>COUNT(p.id)</strong>, and subtract 1 to get number of replies.<br />
- Finally we are also getting the ID for the first Post in that Thread using <strong>MIN(p.id)</strong>. That will be used later in the second DQL query.</p>
<p><strong>where(&#8216;t.forum_id = ?&#8217;, $this->id)</strong> indicates which Forum id we are looking up.</p>
<p><strong>groupBy(&#8216;t.id&#8217;)</strong> groups the results by the Thread id, so the Post count works properly.</p>
<p>Then, we loop through the Threads to get some more data into each Thread:</p>
<p>In the first query we fetched the ID of the first post on each Thread and stored it as <strong>first_post_id</strong>. So this DQL query now gets data for that Post and also the <strong>username</strong> of its author by joining to the related User Model.</p>
<p>The rest of the code, I just arranged all the values in $thread so it has a nice structure when returned.</p>
<p>Just to give you a better picture, if you were to print_r <strong>$threads</strong> , it would look this this:</p>
<pre>
Array
(
    [0] => Array
        (
            [id] => 1
            [title] => Hi there!
            [num_replies] => 1
            [first_post_id] => 1
            [created_at] => 2009-12-13 13:00:09
            [username] => TestUser
            [user_id] => 2
        )

    [1] => Array
        (
            [id] => 2
            [title] => Greetings to all
            [num_replies] => 0
            [first_post_id] => 3
            [created_at] => 2009-12-13 13:00:09
            [username] => Foobar
            [user_id] => 3
        )

)
</pre>
<p>I did <strong>unset($thread['Posts'])</strong> in the code just to keep the resulting array cleaner.</p>
<p>Note that we used HYDRATE_ARRAY, like we talked about earlier. This allowed us to do 2 things that we couldn&#8217;t have done with Doctrine_Collection objects:<br />
- When we <strong>foreach()</strong> the Threads, we are able to get each element by reference (<strong>&#038;$thread</strong>), and modify them.<br />
- We are able to create new array elements and assign values to them, like this:<br />
<strong> $thread['username'] = $post['User']['username'];</strong>.</p>
<p>Now, we need to create the View that will be for the content section of this page. </p>
<h4>Forum View</h4>
<p>In the Controller we passed this: <strong>$vars['content_view'] = &#8216;forum&#8217;;</strong><br />
So the Template will look for a View named &#8216;forum&#8217;.</p>
<ul>
<li>Create: <strong>system/application/views/forum.php</strong></li>
</ul>
<pre class="brush: php; html-script: true;">
&lt;h2&gt;&lt;?php echo $title ?&gt;&lt;/h2&gt;

&lt;?php foreach($threads as $thread): ?&gt;
&lt;div class=&quot;thread&quot;&gt;

	&lt;h3&gt;
		&lt;?php echo anchor('threads/display/'.$thread['id'], $thread['title']) ?&gt;
		(&lt;?php echo $thread['num_replies']; ?&gt; replies)
	&lt;/h3&gt;

	&lt;div&gt;
		Author: &lt;em&gt;&lt;?php echo anchor('profile/display/'.$thread['user_id'],
								$thread['username']); ?&gt;&lt;/em&gt;,
		Posted: &lt;em&gt;&lt;?php echo $thread['created_at']; ?&gt;&lt;/em&gt;
	&lt;/div&gt;

&lt;/div&gt;
&lt;?php endforeach; ?&gt;
</pre>
<p>There is nothing new here. Just putting the data into HTML.</p>
<h4>The Result</h4>
<ul>
<li>Go to the Home Page and click on the first Forum.</li>
</ul>
<p>You should see this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day9_5.png" alt="ci_doctrine_day9_5" title="ci_doctrine_day9_5" width="590" height="291" class="aligncenter size-full wp-image-744" /></p>
<p>Seems to be working!</p>
<h3>Stay Tuned</h3>
<p>We built another page in our project and explored two more important subjects along the way. Stay tuned for the next article, there is still plenty of work to do <img src='http://www.phpandstuff.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>Thank you for reading. </p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/q0rfn_TrIWE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators/feed</wfw:commentRss>
		<slash:comments>81</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch. Day 8 – Hooks, Profiling &amp; DQL</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/kM1ulA7TBG8/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql#comments</comments>
		<pubDate>Fri, 04 Dec 2009 04:52:10 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=649</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this article we are going to look at 3 main subjects: Hooks (with CodeIgniter), Doctrine Profiling and DQL. And we are going to see how we can use these to optimize some of our database interactions.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-8-hooks-profiling-dql"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this article we are going to look at 3 main subjects: <strong>Hooks</strong> (with CodeIgniter), Doctrine <strong>Profiling</strong> and <strong>DQL</strong>. And we are going to see how we can use these to optimize some of our database interactions.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<p>Before we start going into Hooks, Profiling and DQL, let&#8217;s make a small addition to our Message Board home page.</p>
<h3>User Controls</h3>
<p>In Message Boards, there is usually a section in the top right, with user specific info and links. I am not sure if there is a better name for it, but I&#8217;m going to call it &#8220;User Controls&#8221;.</p>
<p>On the <a href="http://codeigniter.com/forums/" rel="nofollow">CodeIgniter Forums</a> it looks like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8_1.png" alt="ci_doctrine_day8_1" title="ci_doctrine_day8_1" width="454" height="179" class="aligncenter size-full wp-image-650" /></p>
<p>And if you are not logged in, it looks like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8_2.png" alt="ci_doctrine_day8_2" title="ci_doctrine_day8_2" width="466" height="183" class="aligncenter size-full wp-image-651" /></p>
<p>Now we are going add something similar, but simpler, to our Message Board.</p>
<h4>Home View</h4>
<ul>
<li>Edit: <strong>system/application/views/home.php</strong></li>
</ul>
<pre class="brush: php; highlight: [13,14,15,16,17,18,19,20,21];">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Home&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;forums&quot;&gt;

	&lt;div class=&quot;user_controls&quot;&gt;
		&lt;?php if ($user = Current_User::user()): ?&gt;
			Hello, &lt;em&gt;&lt;?php echo $user-&gt;username; ?&gt;&lt;/em&gt; &lt;br/&gt;
			&lt;?php echo anchor('logout', 'Logout'); ?&gt;
		&lt;?php else: ?&gt;
			&lt;?php echo anchor('login','Login'); ?&gt; |
			&lt;?php echo anchor('signup', 'Register'); ?&gt;
		&lt;?php endif; ?&gt;
	&lt;/div&gt;

	&lt;h1&gt;CI+Doctrine Message Board&lt;/h1&gt;

	&lt;?php foreach($categories as $category): ?&gt;

		&lt;div class=&quot;category&quot;&gt;

			&lt;h2&gt;&lt;?php echo $category-&gt;title; ?&gt;&lt;/h2&gt;

			&lt;?php foreach($category-&gt;Forums as $forum): ?&gt;

				&lt;div class=&quot;forum&quot;&gt;

					&lt;h3&gt;
						&lt;?php echo anchor('forums/'.$forum-&gt;id, $forum-&gt;title) ?&gt;
						(&lt;?php echo $forum-&gt;Threads-&gt;count(); ?&gt; threads)
					&lt;/h3&gt;

					&lt;div class=&quot;description&quot;&gt;
						&lt;?php echo $forum-&gt;description; ?&gt;
					&lt;/div&gt;

				&lt;/div&gt;

			&lt;?php endforeach; ?&gt;

		&lt;/div&gt;

	&lt;?php endforeach; ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>We just added the highlighted lines. </p>
<p><strong>Line 13:</strong> We are using the <strong>Current_User</strong> class, to see if the user is logged in. If they are logged in, we will get an instance of the <strong>User Model</strong>. If not, it will return false.</p>
<p><strong>Lines 15-16:</strong> We display the username, and link to the <strong>Logout Controller</strong>.</p>
<p><strong>Lines 18-19:</strong> This section is for people who are not logged in. We link to the <strong>Login Controller</strong> and <strong>Signup Controller</strong>.</p>
<p>So we pretty much have just utilized Models and Controllers we have built before.</p>
<p>We need to make a small addition to the css.</p>
<ul>
<li>Edit: <strong>css/style.css</strong></li>
<li>Add this to the end of the file.</li>
</ul>
<pre class="brush: css;">
/* USER CONTROL BOX -------------------------------*/
.user_controls {
	float: right;
	text-align: right;
}
</pre>
<h4>Testing</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8_3.png" alt="ci_doctrine_day8_3" title="ci_doctrine_day8_3" width="580" height="411" class="aligncenter size-full wp-image-661" /></p>
<p>The links are showing up at the top right corner.</p>
<ul>
<li>Click Login.</li>
<li>Login as Testuser:mypass .</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8_4.png" alt="ci_doctrine_day8_4" title="ci_doctrine_day8_4" width="411" height="343" class="aligncenter size-full wp-image-662" /></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/ci_doctrine_day8_5.png" alt="ci_doctrine_day8_5" title="ci_doctrine_day8_5" width="590" height="418" class="aligncenter size-full wp-image-663" /></p>
<p>Now we can see the username and the Logout link.</p>
<p>We will add more features to this later in other tutorials.</p>
<h3>Profiling with Doctrine</h3>
<p>Using Doctrine, our code is cleaner, smaller and easier to read and maintain. But it is sometimes a good idea to look at a few things that are going on behind the scenes. </p>
<p>For example, Doctrine executes several SQL queries for us, while we use our Models. It would be nice to know what these queries are, so we can see if there is more room for optimization. This can be accomplished by <strong>Profiling</strong>.</p>
<p>For this, we are going to be using a Doctrine component called <strong>Doctrine_Connection_Profiler</strong>.</p>
<h4>Profiling the Home Page</h4>
<p>Let&#8217;s look at what queries are executed on the home page. We are going to make a quick and dirty test for now. Later in the article we&#8217;ll make a more re-usable version.</p>
<p>There is going to be lots of new code here, but I will explain them line by line:</p>
<ul>
<li>Edit: <strong>system/application/controllers/test.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Test extends Controller {

//...

	function home_profiler() {

		// set up the profiler
		$profiler = new Doctrine_Connection_Profiler();
		foreach (Doctrine_Manager::getInstance()-&gt;getConnections() as $conn) {
			$conn-&gt;setListener($profiler);
		}

		// copied from home controller
		$vars['categories'] = Doctrine::getTable('Category')-&gt;findAll();

		$this-&gt;load-&gt;view('home', $vars);

		// analyze the profiler data
		$time = 0;
		$events = array();
		foreach ($profiler as $event) {
		    $time += $event-&gt;getElapsedSecs();
			if ($event-&gt;getName() == 'query' || $event-&gt;getName() == 'execute') {
				$event_details = array(
					&quot;type&quot; =&gt; $event-&gt;getName(),
					&quot;query&quot; =&gt; $event-&gt;getQuery(),
					&quot;time&quot; =&gt; sprintf(&quot;%f&quot;, $event-&gt;getElapsedSecs())
				);
				if (count($event-&gt;getParams())) {
					$event_details[&quot;params&quot;] = $event-&gt;getParams();
				}
				$events []= $event_details;
			}
		}
		print_r($events);
		echo &quot;\nTotal Doctrine time: &quot; . $time  . &quot;\n&quot;;
		echo &quot;Peak Memory: &quot; . memory_get_peak_usage() . &quot;\n&quot;;
	}

}
</pre>
<p><strong>Lines 15-17</strong> are just copied from the home Controller. Before that, we set up the Profiler, and after that we look at the data gathered by the Profiler.</p>
<p><strong>Lines 9-12</strong>: First we create a Profiler object. Then we attach it to every Doctrine connection. In our case, it will be just one connection. Now it&#8217;s ready to listen and record all Doctrine events.</p>
<p><strong>Line 22</strong>: The Profiler object let&#8217;s us loop through it and get each Event object. Events can be executed queries and also other things like fetching row data etc.. But we are only going to look at query events.</p>
<p><strong>Lines 20,23 and 37</strong>: Each Event has information on how much time it took. So we will add them up in $time variable and display it at the end.</p>
<p><strong>Line 24</strong>: We are only interested in SQL queries. These can be types &#8216;query&#8217; or &#8216;execute&#8217;. If a query has assigned parameters (for example &#8216;WHERE id = ?&#8217;), then it is of type &#8216;execute&#8217;, otherwise it is &#8216;query&#8217;.</p>
<p><strong>Lines 25-32</strong>: We create an array ($event_details) with information about the query. The type, the query SQL, and the time it took to run. Also if there were any parameters, we add that too.</p>
<p><strong>Lines 33 and 36</strong>: We add it all into the $events array, and just dump it at the end with print_r().</p>
<p><strong>Line 38</strong>: We use the memory_get_peak_usage() PHP function to find out what the maximum memory usage was during the script execution.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/test/home_profiler" rel="nofollow">http://localhost/ci_doctrine/test/home_profiler</a></li>
<li>View Source:</li>
</ul>
<pre>
Array
(
    [0] => Array
        (
            [type] => query
            [query] => SELECT c.id AS c__id, c.title AS c__title FROM category c
            [time] => 0.000220
        )

    [1] => Array
        (
            [type] => execute
            [query] => SELECT u.id AS u__id, u.username AS u__username, u.password AS u__password, u.email AS u__email, u.created_at AS u__created_at, u.updated_at AS u__updated_at FROM user u WHERE u.id = ? LIMIT 1
            [time] => 0.000310
            [params] => Array
                (
                    [0] => 2
                )

        )

    [2] => Array
        (
            [type] => execute
            [query] => SELECT f.id AS f__id, f.title AS f__title, f.description AS f__description, f.category_id AS f__category_id FROM forum f WHERE f.category_id IN (?)
            [time] => 0.000322
            [params] => Array
                (
                    [0] => 1
                )

        )

    [3] => Array
        (
            [type] => execute
            [query] => SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] => 0.000208
            [params] => Array
                (
                    [0] => 1
                )

        )

    [4] => Array
        (
            [type] => execute
            [query] => SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] => 0.000169
            [params] => Array
                (
                    [0] => 2
                )

        )

    [5] => Array
        (
            [type] => execute
            [query] => SELECT f.id AS f__id, f.title AS f__title, f.description AS f__description, f.category_id AS f__category_id FROM forum f WHERE f.category_id IN (?)
            [time] => 0.000322
            [params] => Array
                (
                    [0] => 2
                )

        )

    [6] => Array
        (
            [type] => execute
            [query] => SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] => 0.000238
            [params] => Array
                (
                    [0] => 3
                )

        )

    [7] => Array
        (
            [type] => execute
            [query] => SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] => 0.000171
            [params] => Array
                (
                    [0] => 4
                )

        )

    [8] => Array
        (
            [type] => execute
            [query] => SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] => 0.000160
            [params] => Array
                (
                    [0] => 5
                )

        )

)

Total Doctrine time: 0.013517618179321
Peak Memory: 5849232
</pre>
<p>As you can see, there were 9 queries executed by Doctrine. That seems too many. This happens because of the way Doctrine does &#8216;lazy loading&#8217;. It fetches data from the database as we access the objects and their parameters.</p>
<p>Later in the article, we are going to see how we can optimize this with DQL.</p>
<p>Let&#8217;s see how we can use the Profiler for the entire application, in a re-usable way. For that, we&#8217;re going to look at CodeIgniter Hooks.</p>
<h3>CodeIgniter Hooks</h3>
<p>With <strong>Hooks</strong>, we can tell CodeIgniter to perform an operation, at a given point in the application flow.</p>
<p>For example, we are going to initialize the Profiler, before any Controller function is called.</p>
<h4>Enabling Hooks</h4>
<p>Hooks are disabled by default, so we must first enable them.</p>
<ul>
<li>Edit: <strong>system/application/config/config.php</strong></li>
</ul>
<pre class="brush: php;">
// ...

/*
|--------------------------------------------------------------------------
| Enable/Disable System Hooks
|--------------------------------------------------------------------------
|
| If you would like to use the &quot;hooks&quot; feature you must enable it by
| setting this variable to TRUE (boolean).  See the user guide for details.
|
*/
$config['enable_hooks'] = TRUE;

// ...
</pre>
<p>Just changed it from FALSE to TRUE. Now we can use Hooks.</p>
<h4>Creating a Profiler Hook</h4>
<p>Let&#8217;s create the functions that will be called for this hook.</p>
<ul>
<li>Create: <strong>system/application/hooks/doctrine_profiler_hooks.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Doctrine_Profiler_Hooks {

	public static $profiler;

	public function profiler_start() {

		self::$profiler = new Doctrine_Connection_Profiler();
		foreach (Doctrine_Manager::getInstance()-&gt;getConnections() as $conn) {
			$conn-&gt;setListener(self::$profiler);
		}

	}

	public function profiler_end() {

		// analyze the profiler data
		$time = 0;
		$events = array();
		foreach (self::$profiler as $event) {
		    $time += $event-&gt;getElapsedSecs();
			if ($event-&gt;getName() == 'query' || $event-&gt;getName() == 'execute') {
				$event_details = array(
					&quot;type&quot; =&gt; $event-&gt;getName(),
					&quot;query&quot; =&gt; $event-&gt;getQuery(),
					&quot;time&quot; =&gt; sprintf(&quot;%f&quot;, $event-&gt;getElapsedSecs())
				);
				if (count($event-&gt;getParams())) {
					$event_details[&quot;params&quot;] = $event-&gt;getParams();
				}
				$events []= $event_details;
			}
		}

		$output = &quot;&lt;&quot;.&quot;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?&quot;.&quot;&gt;\n\n&quot;;
		$output .= print_r($events,1);
		$output .= &quot;\nTotal Doctrine time: &quot; . $time  . &quot;\n&quot;;
		$output .= &quot;Peak Memory: &quot; . memory_get_peak_usage() . &quot;&quot;;

		file_put_contents(BASEPATH.&quot;/logs/doctrine_profiler.php&quot;, $output);
	}
}
</pre>
<p>The code is mostly the same as before. This time we are storing the $profiler as a static variable in this class. Also, we are writing the output to a log file instead of dumping it into the browser.</p>
<h4>Adding the Hooks</h4>
<p>Now we need to add the hooks to the config so they get executed.</p>
<ul>
<li>Edit: <strong>system/application/config/hooks.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed');
/*
| -------------------------------------------------------------------------
| Hooks
| -------------------------------------------------------------------------
| This file lets you define &quot;hooks&quot; to extend CI without hacking the core
| files.  Please see the user guide for info:
|
|	http://codeigniter.com/user_guide/general/hooks.html
|
*/

$hook['post_controller_constructor'][] = array(
	'class'    =&gt; 'Doctrine_Profiler_Hooks',
	'function' =&gt; 'profiler_start',
	'filename' =&gt; 'doctrine_profiler_hooks.php',
	'filepath' =&gt; 'hooks',
	);

$hook['post_controller'][] = array(
	'class'    =&gt; 'Doctrine_Profiler_Hooks',
	'function' =&gt; 'profiler_end',
	'filename' =&gt; 'doctrine_profiler_hooks.php',
	'filepath' =&gt; 'hooks',
	);

/* End of file hooks.php */
/* Location: ./system/application/config/hooks.php */
</pre>
<p>So we store the hooks inside the $hook array. The index of the array is name of the hook. In this case we used the &#8216;post_controller_constructor&#8217; and &#8216;post_controller&#8217; Hooks.</p>
<p>The array structure should be easy to understand. We point to the class name, function, file path, file name, so that CodeIgniter can find our code for execution.</p>
<p>(Note: I would have preferred to use the &#8220;pre_controller&#8221; Hook, because it happens before even the Controller constructor is called. However, the plug-ins are not initialized at that point, including Doctrine, so we need to use &#8220;post_controller_constructor&#8221; instead.)</p>
<h4>Testing</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p>You should just see the homepage with no errors. If you are getting file access errors, make sure the system/logs folder is writable.</p>
<ul>
<li>Open: <strong>system/logs/doctrine_profiler.php</strong></li>
</ul>
<p>You should see something like this:</p>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?&gt;

Array
(
    [0] =&gt; Array
        (
            [type] =&gt; query
            [query] =&gt; SELECT c.id AS c__id, c.title AS c__title FROM category c
            [time] =&gt; 0.000220
        )

    [1] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT u.id AS u__id, u.username AS u__username, u.password AS u__password, u.email AS u__email, u.created_at AS u__created_at, u.updated_at AS u__updated_at FROM user u WHERE u.id = ? LIMIT 1
            [time] =&gt; 0.000310
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

    [2] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT f.id AS f__id, f.title AS f__title, f.description AS f__description, f.category_id AS f__category_id FROM forum f WHERE f.category_id IN (?)
            [time] =&gt; 0.000322
            [params] =&gt; Array
                (
                    [0] =&gt; 1
                )

        )

    [3] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000208
            [params] =&gt; Array
                (
                    [0] =&gt; 1
                )

        )

    [4] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000169
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

    [5] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT f.id AS f__id, f.title AS f__title, f.description AS f__description, f.category_id AS f__category_id FROM forum f WHERE f.category_id IN (?)
            [time] =&gt; 0.000322
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

    [6] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000238
            [params] =&gt; Array
                (
                    [0] =&gt; 3
                )

        )

    [7] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000171
            [params] =&gt; Array
                (
                    [0] =&gt; 4
                )

        )

    [8] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000160
            [params] =&gt; Array
                (
                    [0] =&gt; 5
                )

        )

)

Total Doctrine time: 0.013517618179321
Peak Memory: 5849232
</pre>
<p>Let&#8217;s see how we can optimize this and reduce the number of queries executed.</p>
<h3>Optimizing with DQL</h3>
<p>In the Day 5 &#8211; CRUD article, we had a first look at DQL. Now we are going to use it in our application.</p>
<p>If you are familiar with the CodeIgniter Active Records class, there are some similarities. However DQL is much more powerful.</p>
<h4>Reducing the Number of Queries</h4>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Home extends Controller {

	public function index() {

		// $vars['categories'] = Doctrine::getTable('Category')-&gt;findAll();
		$vars['categories'] = Doctrine_Query::create()
			-&gt;select('c.title, f.title, f.description')
			-&gt;from('Category c, c.Forums f')
			-&gt;execute();

		$this-&gt;load-&gt;view('home', $vars);
	}	

}
</pre>
<p>We just commented out the <strong>findAll()</strong> line, and added a DQL call instead.</p>
<p>In the <strong>select()</strong> call we specify which fields we want to fetch.</p>
<p>In the <strong>from()</strong> call, we put the Models and use short aliases for them (c and f). Note that, we used c.Forums instead c.Forum, even though the Model was named Forum. This is because we are joining two models here, and in the Category Model definition, we referred to the Forum model as Forums:</p>
<pre class="brush: php; highlight: [12];">
&lt;?php

// models/category.php

class Category extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
	}

	public function setUp() {
		$this-&gt;hasMany('Forum as Forums', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'category_id'
		));
	}
}
</pre>
<p>It was just more suitable to name in plural since it&#8217;s a one-to-many relationship.</p>
<p>Another thing to note is that we did not specify an ON clause in DQL. Normally when you join tables in SQL, you would specify the columns you are joining on. But since our model definitions know how these relationships are set up, ON clause is not necessary in this case.</p>
<p>Finally, we run <strong>execute()</strong> to fetch the Doctrine_Collection object.</p>
<p>Let&#8217;s load the home page again, and then look at the profiler output.</p>
<ul>
<li>First go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
<li>Then open: <strong>system/logs/doctrine_profiler.php</strong></li>
</ul>
<p>You should see something like this:</p>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?&gt;

Array
(
    [0] =&gt; Array
        (
            [type] =&gt; query
            [query] =&gt; SELECT c.id AS c__id, c.title AS c__title, f.id AS f__id, f.title AS f__title, f.description AS f__description FROM category c LEFT JOIN forum f ON c.id = f.category_id
            [time] =&gt; 0.000311
        )

    [1] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT u.id AS u__id, u.username AS u__username, u.password AS u__password, u.email AS u__email, u.created_at AS u__created_at, u.updated_at AS u__updated_at FROM user u WHERE u.id = ? LIMIT 1
            [time] =&gt; 0.000307
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

    [2] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000274
            [params] =&gt; Array
                (
                    [0] =&gt; 1
                )

        )

    [3] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000172
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

    [4] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000214
            [params] =&gt; Array
                (
                    [0] =&gt; 3
                )

        )

    [5] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000154
            [params] =&gt; Array
                (
                    [0] =&gt; 4
                )

        )

    [6] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT t.id AS t__id, t.title AS t__title, t.forum_id AS t__forum_id FROM thread t WHERE t.forum_id IN (?)
            [time] =&gt; 0.000311
            [params] =&gt; Array
                (
                    [0] =&gt; 5
                )

        )

)

Total Doctrine time: 0.012369155883789
Peak Memory: 5856440
</pre>
<p>Now we went down to 7 queries instead of 9. However, there is still room for improvement.</p>
<h4>Getting Count</h4>
<p>Currently, most of these queries are caused by the count() call in our Home View.</p>
<pre class="brush: php;">
(&lt;?php echo $forum-&gt;Threads-&gt;count(); ?&gt; threads)
</pre>
<p>Now we are going to fetch the thread count with DQL so that these extra queries do not need to run.</p>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php; highlight: [9,11,12];">
&lt;?php
class Home extends Controller {

	public function index() {

		// $vars['categories'] = Doctrine::getTable('Category')-&gt;findAll();
		$vars['categories'] = Doctrine_Query::create()
			-&gt;select('c.title, f.title, f.description')
			-&gt;addSelect('t.id, COUNT(t.id) as num_threads')
			-&gt;from('Category c, c.Forums f')
			-&gt;leftJoin('f.Threads t')
			-&gt;groupBy('f.id')
			-&gt;execute();
		$this-&gt;load-&gt;view('home', $vars);
	}	

}
</pre>
<p>Highlighted lines are where the changes are.</p>
<p><strong>Line 11:</strong> Now we are selecting from the Threads Model too, so we can count them. I could have added the &#8216;Threads&#8217; model into the from() call in Line 10. But I wanted to demonstrate another way you can do joins in DQL. There is also innerjoin() if you need it.</p>
<p><strong>Line 9:</strong> COUNT(t.id) will give us the number of threads. I could have added this into the select() in Line 8, but for demonstration purposes again, I used the addSelect() function.</p>
<p><strong>Line 12:</strong> Since we want individual Forums returned, and also are counting the Threads per Forum, we are grouping the results by the Forum id field.</p>
<p>If you wanted to do the same thing in raw SQL, the query would look like this:</p>
<pre>
SELECT c.id, c.title, f.id, f.title, f.description, COUNT(t.id) AS num_threads FROM category c LEFT JOIN forum f ON c.id = f.category_id LEFT JOIN thread t ON f.id = t.forum_id GROUP BY f.id
</pre>
<h4>One More Change</h4>
<p>Now we need to do one more change. Since we are going to use the returned &#8216;num_threads&#8217; value instead of calling $forum->Threads->count(), we need to change a line in the Home View.</p>
<ul>
<li>Edit: <strong>system/application/views/home.php</strong> around line #37</li>
<li>Just change the highlighted line.</li>
</ul>
<pre class="brush: php; highlight: [6]; html-script: true;">
&lt;!-- --&gt;
&lt;div class=&quot;forum&quot;&gt;

	&lt;h3&gt;
		&lt;?php echo anchor('forums/'.$forum-&gt;id, $forum-&gt;title) ?&gt;
		(&lt;?php echo $forum-&gt;Threads[0]-&gt;num_threads; ?&gt; threads)
	&lt;/h3&gt;

	&lt;div class=&quot;description&quot;&gt;
		&lt;?php echo $forum-&gt;description; ?&gt;
	&lt;/div&gt;

&lt;/div&gt;
&lt;!-- --&gt;
</pre>
<p>At the first glance, the structure might seem a bit odd. Why not &#8216;$forum->Threads->num_threads&#8217;? or even &#8216;$forum->num_threads&#8217;?</p>
<p>This has to do with the way the query is structured. We called COUNT() on the <strong>Threads.id</strong> field. Therefore the returned data belongs to the Threads relationship, and not to the $forum object directly.</p>
<p>Also, the relationship is <strong>one-to-many</strong>. Therefore $forum->Threads is a <strong>Doctrine_Collection</strong> by default, instead of a Doctrine_Record. So we treat it like an array, and add the [0] index first before we can get the data in num_threads.</p>
<p>The result is: <strong>$forum->Threads[0]->num_threads</strong></p>
<p>If you are ever unsure about the structure of the returned Doctrine_Collection object, you can convert it to an array using <strong>toArray(true)</strong> and dump it on the screen. Passing &#8216;true&#8217; makes it &#8216;deep&#8217;, otherwise you only get the outermost object.</p>
<p>For example, if you do this:</p>
<pre class="brush: php; highlight: [8];">
$vars['categories'] = Doctrine_Query::create()
	-&gt;select('c.title, f.title, f.description')
	-&gt;addSelect('COUNT(t.id) as num_threads')
	-&gt;from('Category c, c.Forums f')
	-&gt;leftJoin('f.Threads t')
	-&gt;groupBy('f.id')
	-&gt;execute();
print_r($vars['categories']-&gt;toArray(true));
</pre>
<p>You can get an output like this:</p>
<pre>
Array
(
    [0] => Array
        (
            [id] => 1
            [title] => The CodeIgniter Lounge
            [Forums] => Array
                (
                    [0] => Array
                        (
                            [id] => 1
                            [title] => Introduce Yourself!
                            [description] => Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.

                            [category_id] => 1
                            [Category] =>
                            [Threads] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] =>
                                            [title] =>
                                            [forum_id] => 1
                                            [Forum] =>
                                            [num_threads] => 2
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 2
                            [title] => The Lounge
                            [description] => CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.

                            [category_id] => 1
                            [Category] =>
                            [Threads] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] =>
                                            [title] =>
                                            [forum_id] => 2
                                            [Forum] =>
                                            [num_threads] => 0
                                        )

                                )

                        )

                )

            [num_threads] => 2
        )

    [1] => Array
        (
            [id] => 2
            [title] => CodeIgniter Development Forums
            [Forums] => Array
                (
                    [0] => Array
                        (
                            [id] => 3
                            [title] => CodeIgniter Discussion
                            [description] => This forum is for general topics related to CodeIgniter.
                            [category_id] => 2
                            [Category] =>
                            [Threads] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] =>
                                            [title] =>
                                            [forum_id] => 3
                                            [Forum] =>
                                            [num_threads] => 0
                                        )

                                )

                        )

                    [1] => Array
                        (
                            [id] => 4
                            [title] => Code and Application Development
                            [description] => Use the forum to discuss anything related to programming and code development.

                            [category_id] => 2
                            [Category] =>
                            [Threads] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] =>
                                            [title] =>
                                            [forum_id] => 4
                                            [Forum] =>
                                            [num_threads] => 0
                                        )

                                )

                        )

                    [2] => Array
                        (
                            [id] => 5
                            [title] => Ignited Code
                            [description] => Use this forum to post plugins, libraries, or other code contributions, or to ask questions about any of them.

                            [category_id] => 2
                            [Category] =>
                            [Threads] => Array
                                (
                                    [0] => Array
                                        (
                                            [id] =>
                                            [title] =>
                                            [forum_id] => 5
                                            [Forum] =>
                                            [num_threads] => 0
                                        )

                                )

                        )

                )

            [num_threads] => 0
        )

)
</pre>
<h4>Profile Again</h4>
<p>Let&#8217;s look at the profiling results again to see how the new DQL performed.</p>
<ul>
<li>First go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
<li>Then open: <strong>system/logs/doctrine_profiler.php</strong></li>
</ul>
<p>You should see something like this:</p>
<pre class="brush: php;">
&lt;?php  if ( ! defined('BASEPATH')) exit('No direct script access allowed'); ?&gt;

Array
(
    [0] =&gt; Array
        (
            [type] =&gt; query
            [query] =&gt; SELECT c.id AS c__id, c.title AS c__title, f.id AS f__id, f.title AS f__title, f.description AS f__description, COUNT(t.id) AS t__0 FROM category c LEFT JOIN forum f ON c.id = f.category_id LEFT JOIN thread t ON f.id = t.forum_id GROUP BY f.id
            [time] =&gt; 0.000493
        )

    [1] =&gt; Array
        (
            [type] =&gt; execute
            [query] =&gt; SELECT u.id AS u__id, u.username AS u__username, u.password AS u__password, u.email AS u__email, u.created_at AS u__created_at, u.updated_at AS u__updated_at FROM user u WHERE u.id = ? LIMIT 1
            [time] =&gt; 0.000354
            [params] =&gt; Array
                (
                    [0] =&gt; 2
                )

        )

)

Total Doctrine time: 0.011896848678589
Peak Memory: 6010440
</pre>
<p>Nice, we are all the way down to 2 queries! </p>
<p>The first one is for fetching all Categories, their Forums, and Thread counts all at once. And the second query was done by the Current_User class for getting user details. You can&#8217;t go much lower than this.</p>
<h3>Conclusions</h3>
<p>I admit that our code became a little more complicated when we switched from using findAll() to DQL. But if your web application is expecting a significant amount of traffic, you might need to utilize such optimizations. Also, with DQL you can achieve more complicated queries that would not be practical with the magic functions like findAll() or findBy*().</p>
<p>Optimization is a debatable subject. Some prefer to do it early, in small steps. Some prefer to do it all the way at the end of development. But as you gain experience, your initial code tends to be more optimized in the first place, and may not need many changes later on.</p>
<p>I guess the point is, using an ORM like Doctrine does not magically optimize your database interactions. You still need to put an effort into it.</p>
<h3>Stay Tuned</h3>
<p>Thank you for reading. Learning more about DQL was an important step, as it is an integral part of Doctrine. Also, Hooks and Profiling gave us an opportunity to look at what is going on behind the scenes.</p>
<p>And thank you for all the encouraging comments. It makes writing these articles even more enjoyable.</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/kM1ulA7TBG8" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql/feed</wfw:commentRss>
		<slash:comments>46</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql</feedburner:origLink></item>
		<item>
		<title>Top 20+ MySQL Best Practices</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/xEAv8fBRmcQ/top-20-mysql-best-practices</link>
		<comments>http://www.phpandstuff.com/articles/top-20-mysql-best-practices#comments</comments>
		<pubDate>Wed, 25 Nov 2009 18:05:32 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[MySQL]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=629</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-630" /> Nettuts+ just published my article!  

<a href="http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/" rel="nofollow">http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/</a>

Database operations often tend to be the main bottleneck for most web applications today. It's not only the DBA's (database administrators) that have to worry about these performance issues. We as programmers need to do our part by structuring tables properly, writing optimized queries and better code. Here are some MySQL optimization techniques for programmers.

<a href="http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/">Read more</a>]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Ftop-20-mysql-best-practices"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-630" /> Nettuts+ just published my article!  </p>
<p><a href="http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/" rel="nofollow">http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/</a></p>
<p>Database operations often tend to be the main bottleneck for most web applications today. It&#8217;s not only the DBA&#8217;s (database administrators) that have to worry about these performance issues. We as programmers need to do our part by structuring tables properly, writing optimized queries and better code. Here are some MySQL optimization techniques for programmers.</p>
<p><a href="http://net.tutsplus.com/tutorials/other/top-20-mysql-best-practices/">Read more</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/xEAv8fBRmcQ" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/top-20-mysql-best-practices/feed</wfw:commentRss>
		<slash:comments>13</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/top-20-mysql-best-practices</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 7 – Fixtures &amp; Forum List</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/ftmjK-BotRo/codeigniter-doctrine-scratch-day-7-fixtures-forum-list</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list#comments</comments>
		<pubDate>Fri, 20 Nov 2009 08:33:17 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=536</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> Today we will continue building our <strong>Message Board</strong> project. First we will start building the Home Page, which will be a <strong>Forum List</strong>. Then we will learn about <strong>Doctrine Data Fixtures</strong>. This will help us create some test data to play with.

<div class="clear"></div>

<img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7_4.png" alt="ci_doctrine_day7_4" title="ci_doctrine_day7_4" width="600" height="422" class="aligncenter size-full wp-image-556" />]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-7-fixtures-forum-list"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> Today we will continue building our <strong>Message Board</strong> project. First we will start building the Home Page, which will be a <strong>Forum List</strong>. Then we will learn about <strong>Doctrine Data Fixtures</strong>. This will help us create some test data to play with.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>First, Some Styling</h3>
<p>Before we get started, let&#8217;s add some style so that pages look somewhat decent. Just copy-paste, and don&#8217;t read it. CSS is not our focus today.</p>
<ul>
<li>Edit: <strong>css/style.css</strong></li>
</ul>
<pre class="brush: css;">
body {
	font-family: &quot;Trebuchet MS&quot;,Arial;
	font-size: 14px;
	background-color: #212426;
	color: #B9AA81;
}

a {
	color: #FFF;
}

a:hover {
	color: #B9AA81;
}

input, textarea, select {
	font-family:inherit;
	font-size:inherit;
	font-weight:inherit;
}

/* FORUMS -----------------------------------------*/

div.forums {
	width: 720px;
	margin: auto;
}

.forums h2 {
	font-size: 16px;
	color: #000;
	padding: 5px 10px 5px 10px;
	margin: 0px;
	background-color: #BBB;
	-moz-border-radius-topleft: 6px;
	-moz-border-radius-topright: 6px;
	-webkit-border-top-left-radius: 6px;
	-webkit-border-top-right-radius: 6px;
}

.forums h3 {
	font-size: 15px;
	margin: 0px;
}

.category {
	margin-bottom: 40px;
}

.forum {
	border-bottom: 1px solid #666;
	padding: 10px;
}

.forum .description {
	font-size: 14px;
}

/* SIGNUP FORM ------------------------------------*/
#signup_form {
	margin-left: auto;
	margin-right: auto;
	width: 360px;
	font-size: 16px;
}

#signup_form .heading {
	text-align: center;
	font-size: 22px;
	font-weight: bold;
	color: #B9AA81;
}

#signup_form form {
	background-color: #B9AA81;
	padding: 10px;
	border-radius: 8px;
	-moz-border-radius: 8px;
	-webkit-border-radius: 8px;
}

#signup_form form label {
	font-weight: bold;
	color: #11151E;
}

#signup_form form input[type=text],input[type=password] {
	width: 316px;
	font-weight: bold;
	padding: 8px;
	border: 1px solid #FFF;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}

#signup_form form input[type=submit] {
	display: block;
	margin: auto;
	width: 200px;
	font-size: 18px;
	background-color: #FFF;
	border: 1px solid #BBB;

}

#signup_form form input[type=submit]:hover {
	border-color: #000;
}

#signup_form .error {
	font-size: 13px;
	color: #690C07;
	font-style: italic;
}
</pre>
<p>Ok, now we&#8217;re ready to get more coding done!</p>
<h3>The Home Page</h3>
<p>We are about to work on the <strong>Controller</strong> and the <strong>View</strong> for our <strong>Home Page</strong> (i.e. Forum List). We want this page to show all of the <strong>Forums</strong> broken down by <strong>Categories</strong>.</p>
<h4>Home Controller</h4>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Home extends Controller {

	public function index() {

		$vars['categories'] = Doctrine::getTable('Category')-&gt;findAll();

		$this-&gt;load-&gt;view('home', $vars);
	}	

}
</pre>
<p>As mentioned before, variables are passed to a <strong>View</strong> in an array, and the array indexes become variable names. In other words, $vars['categories'] becomes $categories inside the View.</p>
<p><strong>Doctrine::getTable(&#8216;Category&#8217;)->findAll();</strong> gives us all of the Category records, in the form of a <strong>Doctrine_Collection</strong> object.</p>
<h4>Home View</h4>
<p>(I&#8217;m going build this page in a few steps)</p>
<ul>
<li>Edit: <strong>system/application/views/home.php</strong></li>
</ul>
<p>First we make a blank page, with a container div and a heading:</p>
<pre class="brush: php; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Home&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;forums&quot;&gt;

	&lt;h1&gt;CI+Doctrine Message Board&lt;/h1&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>Next, we loop thru the <strong>$categories</strong> object, and display titles for each Category:</p>
<pre class="brush: php; highlight: [15,16,17,18,19,20,21,22,23]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Home&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;forums&quot;&gt;

	&lt;h1&gt;CI+Doctrine Message Board&lt;/h1&gt;

	&lt;?php foreach($categories as $category): ?&gt;

		&lt;div class=&quot;category&quot;&gt;

			&lt;h2&gt;&lt;?php echo $category-&gt;title; ?&gt;&lt;/h2&gt;

		&lt;/div&gt;

	&lt;?php endforeach; ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>Note:</strong> $categories is a <strong>Doctrine_Collection</strong> object here, but it can be treated like an array. So we can use <strong>foreach</strong> on it.</p>
<p>Now we are going to show each <strong>Forum</strong>, their <strong>descriptions</strong>, and number of <strong>Threads</strong>.</p>
<pre class="brush: php; highlight: [21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Home&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div class=&quot;forums&quot;&gt;

	&lt;h1&gt;CI+Doctrine Message Board&lt;/h1&gt;

	&lt;?php foreach($categories as $category): ?&gt;

		&lt;div class=&quot;category&quot;&gt;

			&lt;h2&gt;&lt;?php echo $category-&gt;title; ?&gt;&lt;/h2&gt;

			&lt;?php foreach($category-&gt;Forums as $forum): ?&gt;

				&lt;div class=&quot;forum&quot;&gt;

					&lt;h3&gt;
						&lt;?php echo anchor('forums/'.$forum-&gt;id, $forum-&gt;title) ?&gt;
						(&lt;?php echo $forum-&gt;Threads-&gt;count(); ?&gt; threads)
					&lt;/h3&gt;

					&lt;div class=&quot;description&quot;&gt;
						&lt;?php echo $forum-&gt;description; ?&gt;
					&lt;/div&gt;

				&lt;/div&gt;

			&lt;?php endforeach; ?&gt;

		&lt;/div&gt;

	&lt;?php endforeach; ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>As you can see, getting all Forums under a Category is as easy as calling <strong>$category->Forums</strong>. And again, we can treat it as an array and loop thru it.</p>
<p><strong>Line 26:</strong> We are creating a <strong>link</strong> to the Forum. It will link to a <strong>Controller</strong> named <strong>Forums</strong> and pass the <strong>id</strong> in the url. And the link text is the Forum title.</p>
<p><strong>Note:</strong> In CodeIgniter, <strong>Controllers</strong> and <strong>Models</strong> cannot have the same name. That&#8217;s why I linked to &#8216;forums&#8217; instead of &#8216;forum&#8217;. Some people might prefer &#8216;view_forum&#8217; or &#8216;show_forum&#8217; etc&#8230;</p>
<p><strong>Line 27:</strong> This is the first time we are using <strong>count()</strong>. That&#8217;s how we get the <strong>number of Threads</strong> that belong to that <strong>Forum</strong> object.</p>
<h4>The Result</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p>You will see this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7_1.png" alt="ci_doctrine_day7_1" title="ci_doctrine_day7_1" width="600" height="377" class="aligncenter size-full wp-image-547" /></p>
<p>Looks nice. But the links are broken since we haven&#8217;t created the <strong>Forums Controller</strong> (i.e. Forum Page) yet.</p>
<p>Now, we could go ahead and build the Forum Page, but it&#8217;s just not going to look very good since we have no Threads or Posts whatsoever. This is a great time to start talking about <strong>Data Fixtures</strong>.</p>
<h3>Doctrine Data Fixtures</h3>
<h4>What are Data Fixtures?</h4>
<p>&#8220;<strong>Data fixtures</strong> are meant for loading small sets of test data through your models to populate your database with data to test against.&#8221; (from <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/data-fixtures" rel="nofollow">here</a>).</p>
<p>This will do the job for filling the database with some data, so we can do proper testing as we develop our project.</p>
<p>In the last article, we created a Test Controller for inserting some data. That worked well for this tutorial, and we saw some code examples along the way. But on a real development environment, it&#8217;s better to just use Data Fixtures.</p>
<h4>Creating Fixtures</h4>
<p>First, we need to have a place to put our Fixtures. You can put this folder anywhere, but I would like to create it directly under the applications folder.</p>
<ul>
<li>Create Folder: <strong>system/application/fixtures</strong></li>
<li>Create: <strong>system/application/fixtures/data.yml</strong></li>
</ul>
<p>That&#8217;s right, we are creating a <strong>YAML</strong> file. Don&#8217;t worry if you are not familiar with this file format.</p>
<p>We are going to start small with an example:</p>
<pre class="brush: yaml;">
User:
  Admin:
    username: Administrator
    password: testing
    email: programming@gmail.com
  Test:
    username: TestUser
    password: mypass
    email: test@test.com
</pre>
<p>Even if you are not familiar with YAML, the structure is easy to understand.<br />
This code just creates 2 <strong>User</strong> records.</p>
<p><strong>Note</strong>: I used 2 spaces for <strong>indentation</strong>, but it can be any number of spaces. And Tabs do NOT work.</p>
<ul>
<li>First line is the name of the <strong>Model</strong> we are loading data for.</li>
<li><strong>Line 2 and 6</strong>: These are just names for these records. They can be anything. We can use them later in the fixture to reference these records.</li>
<li>The rest should be obvious. We are assigning data to each field for these records.</li>
</ul>
<p>Now, we need to load this fixture into the database.</p>
<ul>
<li>Edit: <strong>system/application/controllers/doctrine_tools.php</strong></li>
</ul>
<pre class="brush: php; highlight: [16];">
&lt;?php
class Doctrine_Tools extends Controller {

// ....

	function load_fixtures() {
		echo 'This will delete all existing data!&lt;br /&gt;
		&lt;form action=&quot;&quot; method=&quot;POST&quot;&gt;
		&lt;input type=&quot;submit&quot; name=&quot;action&quot; value=&quot;Load Fixtures&quot;&gt;&lt;br /&gt;&lt;br /&gt;';

		if ($this-&gt;input-&gt;post('action')) {

			Doctrine_Manager::connection()-&gt;execute(
				'SET FOREIGN_KEY_CHECKS = 0');

			Doctrine::loadData(APPPATH.'/fixtures');
			echo &quot;Done!&quot;;
		}
	}

}
</pre>
<p>We added a function named <strong>load_fixtures()</strong> to this Controller.</p>
<p><strong>Doctrine:loadData()</strong> does the work. Every time it is called, it will purge existing data from the tables, and load the <strong>Data Fixtures</strong> from the given path. If you don&#8217;t want the table purge to happen, you need to pass a second argument as <strong>true</strong>.</p>
<p>(I also had to disable FOREIGN_KEY_CHECKS to avoid some foreign key related errors during the purge.)</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/load_fixtures" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/load_fixtures</a> and click the button.</li>
<li>Now check the <strong>user table</strong> in phpmyadmin.</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7_2.png" alt="ci_doctrine_day7_2" title="ci_doctrine_day7_2" width="600" height="290" class="aligncenter size-full wp-image-552" /></p>
<p>Now that everything seems to be working, let&#8217;s expand our fixture so we have more data to work with.</p>
<ul>
<li>Edit: <strong>system/application/fixtures/data.yml</strong></li>
</ul>
<pre class="brush: yaml; highlight: [18,43,51];">
User:
  Admin:
    username: Administrator
    password: testing
    email: programming@gmail.com
  Test:
    username: TestUser
    password: mypass
    email: test@test.com
  Foo:
    username: Foobar
    password: mypass
    email: test2@test2.com

Forum:
  Forum_1:
    title: Introduce Yourself!
    description: &gt;
      Use this forum to introduce yourself to the CodeIgniter community,
      or to announce your new CI powered site.
  Forum_2:
    title: The Lounge
    description: &gt;
      CodeIgniter's social forum where you can discuss anything not related
      to development. No topics off limits... but be civil.
  Forum_3:
    title: CodeIgniter Discussion
    description: This forum is for general topics related to CodeIgniter.
  Forum_4:
    title: Code and Application Development
    description: &gt;
      Use the forum to discuss anything related to
      programming and code development.
  Forum_5:
    title: Ignited Code
    description: &gt;
      Use this forum to post plugins, libraries, or other code contributions,
      or to ask questions about any of them.

Category:
  Lounge:
    title: The CodeIgniter Lounge
    Forums: [Forum_1, Forum_2]
  Dev:
    title: CodeIgniter Development Forums
    Forums: [Forum_3, Forum_4, Forum_5]

Thread:
  Thread_1:
    title: Hi there!
    Forum: Forum_1
  Thread_2:
    title: Greetings to all
    Forum: Forum_1

Post:
  Post_1:
    Thread: Thread_1
    User: Test
    created_at: 2009-11-20 01:20:30
    content: &gt;
      Hello everyone! My name is Test, and I go to school at
      Test Institute of Technology in the US.
      I just found CodeIgniter some time last week and have been
      reading through the documentation trying to get myself acquainted.

      Hopefully the forums will be a great help! I already have some questions.
      Thanks!
  Post_2:
    Thread: Thread_1
    User: Admin
    created_at: 2009-11-20 02:15:33
    content: Welcome Test! Nice to meet you.
  Post_3:
    Thread: Thread_2
    User: Foo
    created_at: 2009-11-19 12:14:50
    content: I am new here. Just wanted to say hi.
</pre>
<p>This is just a bunch of structured data, nothing complicated. For each Model, we create a few records. And we have a few new things to mention:</p>
<p><strong>Line 18</strong>: Here you can see the syntax for adding a long string value in multiple lines.<br />
<strong>Line 51</strong>: We are setting up the <strong>relationships</strong> between records. This line says Thread_1 belongs to Forum_1.<br />
<strong>Line 43</strong>: Again, we are setting up relationships, but this time we are assigning multiple records, and you see the syntax for that.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/load_fixtures" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/load_fixtures</a> and click the button.</li>
<li>And, go to <strong>phpmyadmin</strong> and look at all the tables.</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7_3.png" alt="ci_doctrine_day7_3" title="ci_doctrine_day7_3" width="524" height="225" class="aligncenter size-full wp-image-555" /></p>
<p>We just created 15 records!</p>
<h4>See the Results</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/" rel="nofollow">http://localhost/ci_doctrine/</a></li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day7_4.png" alt="ci_doctrine_day7_4" title="ci_doctrine_day7_4" width="600" height="422" class="aligncenter size-full wp-image-556" /></p>
<p>We can see all the <strong>Categories</strong> and <strong>Forums</strong> we just created. Also there are 2 <strong>Threads</strong> now, as we can see from the count.</p>
<h3>Stay Tuned</h3>
<p>Our Message Board is starting to take shape. Meanwhile we learned about a new concept called <strong>Data Fixtures</strong>, which is very helpful during the development process.</p>
<p>In the next tutorials we will go deeper into the project and keep building more functional pages.</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/ftmjK-BotRo" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list/feed</wfw:commentRss>
		<slash:comments>66</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 6 – Models with Relationships</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/8aEaL1B3SKc/codeigniter-doctrine-day-6-models-relationships</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships#comments</comments>
		<pubDate>Fri, 13 Nov 2009 06:57:27 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=500</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this episode of the series, we will continue building our <strong>Message Board</strong> project. First we will have a quick overview of <strong>Doctrine Model Relationships</strong>. Then we will create <strong>Models</strong> for our Message Board, such as: Forums, Threads, Posts etc... with proper relationships. Finally we will learn how to <strong>add data</strong> into such Models.
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-day-6-models-relationships"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> In this episode of the series, we will continue building our <strong>Message Board</strong> project. First we will have a quick overview of <strong>Doctrine Model Relationships</strong>. Then we will create <strong>Models</strong> for our Message Board, such as: Forums, Threads, Posts etc&#8230; with proper relationships. Finally we will learn how to <strong>add data</strong> into such Models.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day6.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Doctrine Model Relationships (a quick overview)</h3>
<p>One of the key features of <strong>Doctrine</strong> is the handling of <strong>Relationships</strong> between <strong>Models</strong>. At this point in our project, we will start utilizing it.</p>
<p>On a typical <strong>Message Board</strong>:</p>
<ul>
<li>There are <strong>Forums</strong></li>
<li><strong>Forums</strong> have <strong>Threads</strong></li>
<li><strong>Threads</strong> have <strong>Posts</strong></li>
<li><strong>Users</strong> have <strong>Posts</strong></li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day6_1.png" alt="ci_doctrine_day6_1" title="ci_doctrine_day6_1" width="450" height="450" class="aligncenter size-full wp-image-501" /></p>
<p>We will learn how to define these relationships in our Models. <strong>Doctrine</strong> supports the following types of relationships:</p>
<ul>
<li><strong>One to Many</strong> (or Many to One)</li>
<li><strong>One to One</strong></li>
<li><strong>Many to Many</strong></li>
<li><strong>Tree</strong> Structure</li>
<li><strong>Nest</strong> Relations</li>
</ul>
<p>Today we will be talking about only the first two.</p>
<h4>Foreign Keys</h4>
<p>To setup relationships between models (and tables in the database), we need to have certain fields in our tables. These are used as <strong>Foreign Keys</strong>.</p>
<p>For example, if each <strong>Post</strong> belongs to a <strong>User</strong>, we need a <strong>user_id</strong> field in the Post table. We can specify this in our model:</p>
<pre class="brush: php;">
class Post extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('content', 'string', 65535);
		$this-&gt;hasColumn('user_id', 'integer');
	}

}
</pre>
<p>But to specify the type of relationship, we are going to have to do more than that.</p>
<h4>One to Many Relationships</h4>
<p>Just like the name suggests, this creates a relationship<strong> between one instance of a Model and multiple instances of another Model</strong>.</p>
<p>For example: <strong>one</strong> User has <strong>many</strong> Posts. </p>
<p>In Doctrine, this kind of relationship is setup using the <strong>hasOne()</strong> and <strong>hasMany()</strong> functions.</p>
<p><strong>Post Example:</strong></p>
<pre class="brush: php; highlight: [5,9,10,11,12];">
class Post extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('content', 'string', 65535);
		$this-&gt;hasColumn('user_id', 'integer');
	}

	public function setUp() {
		$this-&gt;hasOne('User', array(
			'local' =&gt; 'user_id',
			'foreign' =&gt; 'id'
		));
	}

}
</pre>
<p><strong>hasOne()</strong> says that the Post is associated with one User. The first parameter is the <strong>Model name</strong> and the second parameter is an array that sets the <strong>foreign keys</strong>. </p>
<p>It links the two Models by the <strong>user_id</strong> field in the <strong>local</strong> Model (i.e. Post), with the <strong>id</strong> field in the <strong>foreign</strong> Model (i.e. User).</p>
<p>Now we can access the User object for a post like this: <strong>$post->User</strong>. We&#8217;ll see more of that later.</p>
<p><strong>User Example:</strong></p>
<pre class="brush: php; highlight: [9,10,11,12];">
class User extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('username', 'string', 255, array('unique' =&gt; 'true'));
		$this-&gt;hasColumn('password', 'string', 255);
	}

	public function setUp() {
		$this-&gt;hasMany('Post as Posts', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'user_id'
		));
	}
}
</pre>
<p>On this side of the relationship, there are no additional fields for the foreign key. But we still define it by the <strong>hasMany()</strong> call.</p>
<p>The first parameter looks a bit different this time. When we say <strong>Post as Posts</strong>, we link to the <strong>Model</strong> named Post, but we name the <strong>property</strong> Posts.</p>
<p>This way we are going to access it like <strong>$user->Posts</strong>, instead of <strong>$user->Post</strong>. This is just a matter of preference, because it sounds better.</p>
<p><strong>Note:</strong> As a rule of thumb, the Model that has the <strong>hasOne()</strong> call is the one with the foreign key field. (Post.user_id in this case).</p>
<h4>One to One Relationships</h4>
<p>This type of relationship is used when each Model is linked to only one instance of the other Model.</p>
<p>For example, if you have separate Models/Tables for <strong>User</strong> and <strong>Email</strong>, and if you want each User to have <strong>only one</strong> Email, you might use this.</p>
<p>The syntax is exactly the same as the <strong>One to Many</strong> Relationships, but this time <strong>both Models</strong> call the <strong>hasOne()</strong> function, instead of <strong>hasMany()</strong>.</p>
<h4>for more info</h4>
<p>This is all we needed to know to continue our project for now. But if you want to find out about all types of relationships in Doctrine, you can read the whole documentation section on this subject <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/defining-models#relationships" rel="nofollow">here</a>.</p>
<h3>Let&#8217;s Create Some Models</h3>
<p>Let&#8217;s use what we just learned to create our new Models.</p>
<p><strong>Note:</strong> I would like to build this project similar to the <a href="http://codeigniter.com/forums/" rel="nofollow">CodeIgniter Message Board</a>. They also seem to have <strong>Categories</strong>, that contain multiple Forums, so we are going to create a Model for that too.</p>
<h4>Category Model</h4>
<ul>
<li>Create: <strong>system/application/models/category.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Category extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
	}

	public function setUp() {
		$this-&gt;hasMany('Forum as Forums', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'category_id'
		));
	}
}
</pre>
<p>Looks simple. We have a <strong>Category</strong> Model that has a title, and can have many <strong>Forums</strong>. Also we are expecting that the Forum Model to have a field named <strong>category_id</strong>.</p>
<h4>Forum Model</h4>
<ul>
<li>Create: <strong>system/application/models/forum.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Forum extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
		$this-&gt;hasColumn('description', 'string', 255);
		$this-&gt;hasColumn('category_id', 'integer', 4);
	}

	public function setUp() {
		$this-&gt;hasOne('Category', array(
			'local' =&gt; 'category_id',
			'foreign' =&gt; 'id'
		));
		$this-&gt;hasMany('Thread as Threads', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'forum_id'
		));
	}

}
</pre>
<p>As expected, we have a <strong>category_id</strong> field for the <strong>foreign key</strong>.</p>
<p>Also we have 2 relationships now. First one is with <strong>Category</strong> Model, as Forums have (or belong to) a single Category. The second one is with <strong>Thread</strong> Model. Each Forum can have many Threads.</p>
<h4>Thread Model</h4>
<ul>
<li>Create: <strong>system/application/models/thread.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Thread extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('title', 'string', 255);
		$this-&gt;hasColumn('forum_id', 'integer', 4);
	}

	public function setUp() {
		$this-&gt;hasOne('Forum', array(
			'local' =&gt; 'forum_id',
			'foreign' =&gt; 'id'
		));
		$this-&gt;hasMany('Post as Posts', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'thread_id'
		));
	}

}
</pre>
<h4>Post Model</h4>
<ul>
<li>Create: <strong>system/application/models/post.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Post extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('content', 'string', 65535);
		$this-&gt;hasColumn('thread_id', 'integer', 4);
		$this-&gt;hasColumn('user_id', 'integer', 4);
	}

	public function setUp() {
		$this-&gt;actAs('Timestampable');
		$this-&gt;hasOne('Thread', array(
			'local' =&gt; 'thread_id',
			'foreign' =&gt; 'id'
		));
		$this-&gt;hasOne('User', array(
			'local' =&gt; 'user_id',
			'foreign' =&gt; 'id'
		));
	}

}
</pre>
<p>Notice this time we have 2 foreign keys. Because a Post belongs to a <strong>Thread</strong>, and also belongs to a <strong>User</strong>.</p>
<h4>User Model</h4>
<p>We already have this Model, we are just making changes.</p>
<ul>
<li>Edit: <strong>system/application/models/user.php</strong></li>
</ul>
<pre class="brush: php; highlight: [11,12,13,14];">
&lt;?php
class User extends Doctrine_Record {

// ...

	public function setUp() {
		$this-&gt;setTableName('user');
		$this-&gt;actAs('Timestampable');
		$this-&gt;hasMutator('password', '_encrypt_password');

		$this-&gt;hasMany('Post as Posts', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'user_id'
		));
	}
//...
}
</pre>
<h4>Create the Tables</h4>
<p>Remember our Controller that creates Tables from Models? It&#8217;s time to use that again.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/doctrine_tools/create_tables" rel="nofollow">http://localhost/ci_doctrine/doctrine_tools/create_tables</a></li>
<li>Press the button, and it should create the tables.</li>
<li>Look at phpmyadmin at: <a href="http://localhost/phpmyadmin" rel="nofollow">http://localhost/phpmyadmin</a>.</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day6_2.png" alt="ci_doctrine_day6_2" title="ci_doctrine_day6_2" width="510" height="340" class="aligncenter size-full wp-image-510" /></p>
<p>Looks great! </p>
<p>Now let&#8217;s see how we can add some data using these Models.</p>
<h3>Creating Records</h3>
<p>We are going to write a quick test controller to demonstrate how we can <strong>add data</strong>.</p>
<ul>
<li>Create: <strong>system/application/controllers/test.php</strong></li>
</ul>
<pre class="brush: php; highlight: [14];">
&lt;?php
class Test extends Controller {

	function index() {

		$category = new Category();
		$category-&gt;title = &quot;The CodeIgniter Lounge&quot;;
		$category-&gt;save();

		$forum = new Forum();
		$forum-&gt;title = &quot;Introduce Yourself!&quot;;
		$forum-&gt;description = &quot;Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.&quot;;

		$forum-&gt;Category = $category;

		$forum-&gt;save();
	}

}
</pre>
<p>Do you see how intuitive it is?</p>
<p><strong>$forum->Category</strong> represents the relationship that the Forum object has with the Category Model. We can directly assign a Category object to it to link them.</p>
<p>Let&#8217;s expand this so we have a bit more data.</p>
<ul>
<li>Edit: <strong>system/application/controllers/test.php</strong></li>
</ul>
<pre class="brush: php; highlight: [13,21,36,37];">
&lt;?php
class Test extends Controller {

	function index() {

		$category = new Category();
		$category-&gt;title = &quot;The CodeIgniter Lounge&quot;;

		$forum = new Forum();
		$forum-&gt;title = &quot;Introduce Yourself!&quot;;
		$forum-&gt;description = &quot;Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.&quot;;
		// add category to the forum
		$forum-&gt;Category = $category;

		$forum2 = new Forum();
		$forum2-&gt;title = &quot;The Lounge&quot;;
		$forum2-&gt;description = &quot;CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.&quot;;

		// you can also add the other way around
		// add forum to the category
		$category-&gt;Forums []= $forum2;

		// a different syntax (array style)

		$category2 = new Category();
		$category2['title'] = &quot;CodeIgniter Development Forums&quot;;

		$forum3 = new Forum();
		$forum3['title'] = &quot;CodeIgniter Discussion&quot;;
		$forum3['description'] = &quot;This forum is for general topics related to CodeIgniter&quot;;

		$forum4 = new Forum();
		$forum4['title'] = &quot;Code and Application Development&quot;;
		$forum4['description'] = &quot;Use the forum to discuss anything related to programming and code development.&quot;;

		$category2['Forums'] []= $forum3;
		$category2['Forums'] []= $forum4;

		// flush() saves all unsaved objects
		$conn = Doctrine_Manager::connection();
		$conn-&gt;flush();

		echo &quot;Success!&quot;;

	}

}
</pre>
<p>We just created 2 categories, and 2 forums in each of them, in a few different ways.</p>
<ul>
<li><strong>Line 21:</strong> We add a Forum to the Category, instead of the other way around. But this time, since <strong>$category->Forums</strong> contains multiple Forums, we push to it like you would to an array, instead of direct assignment like on line 13.</li>
<li><strong>Lines 25-37:</strong> Here you can see how we can access all elements of the Doctrine Model objects like <strong>array elements</strong>. Some people prefer this syntax.</li>
<li><strong>Lines 40-41:</strong> Instead of calling save() on every single object, we can just use <strong>flush()</strong> to save everything.</li>
</ul>
<p>Let&#8217;s test this.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/test" rel="nofollow">http://localhost/ci_doctrine/test</a></li>
</ul>
<p>You should see the success message:</p>
<pre>
Success!
</pre>
<p>Now let&#8217;s look at the <strong>category table</strong>:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day6_3.png" alt="ci_doctrine_day6_3" title="ci_doctrine_day6_3" width="339" height="76" class="aligncenter size-full wp-image-516" /></p>
<p>You can see our new 2 categories, with id&#8217;s 1 and 2. Let&#8217;s see if the forums got the correct associations.</p>
<p>Look at the <strong>forum table</strong>:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day6_4.png" alt="ci_doctrine_day6_4" title="ci_doctrine_day6_4" width="600" height="96" class="aligncenter size-full wp-image-517" /></p>
<p>Everything looks good! The Forums each have proper category_id&#8217;s assigned.</p>
<h3>Stay Tuned</h3>
<p>Today we learned about one of main features of Doctrine. We were able to create foreign key relationships without using any queries whatsoever! That is one of the nice things about using an ORM like Doctrine. I hope you are able to see how much time you can save by developing like this.</p>
<p>In the next episode we will continue on our project, with a little more CodeIgniter stuff.</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/8aEaL1B3SKc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships/feed</wfw:commentRss>
		<slash:comments>83</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 5 – Database CRUD</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/CKAZMry6OrI/codeigniter-doctrine-day-5-database-crud</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud#comments</comments>
		<pubDate>Mon, 09 Nov 2009 14:00:09 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=481</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> <strong>CRUD</strong> stands for <strong>Create, Read, Update and Delete</strong>, the basic operations performed on the database. With regular <strong>CodeIgniter</strong> setups, most developers would use the <strong>Active Record Class</strong> for performing such operations. But we are not going to be doing that.

In this episode of the series, I will show you how to perform <strong>CRUD with Doctrine</strong>.
]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-day-5-database-crud"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" /> <strong>CRUD</strong> stands for <strong>Create, Read, Update and Delete</strong>, the basic operations performed on the database. With regular <strong>CodeIgniter</strong> setups, most developers would use the <strong>Active Record Class</strong> for performing such operations. But we are not going to be doing that.</p>
<p>In this episode of the series, I will show you how to perform <strong>CRUD with Doctrine</strong>.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p>In <strong>Doctrine</strong>, there can be multiple ways of accomplishing the same task. This gives you flexibility to pick the best approach suitable for each situation. Therefore we shall explore these different methods for each part of the <strong>CRUD</strong>.</p>
<h3>1. CREATE</h3>
<p>The act of inserting new data/records into the database:</p>
<h4>Record Object</h4>
<p>This is the way we have been creating our user records in the previous tutorials. It&#8217;s pretty simple:</p>
<pre class="brush: php;">
$u = new User();

$u-&gt;username = 'myuser';
$u-&gt;password = 'mypass';

$u-&gt;save();
</pre>
<p>When the <strong>save()</strong> method is called, the new record is created.</p>
<h4>fromArray()</h4>
<p>Sometimes you have all the data already in an array. Instead of assigning every value to the record object separately, you can simply use the <strong>fromArray()</strong> method.</p>
<pre class="brush: php;">
$data = array(
	'username' =&gt; 'myuser',
	'password' =&gt; 'mypass',
	'email' =&gt; 'my@email.com'
);

$u = new User();

$u-&gt;fromArray($data);

$u-&gt;save();
</pre>
<h4>flush()</h4>
<p>When you call the <strong>flush()</strong> method on the <strong>Doctrine_Connection</strong> object, all unsaved record objects automatically get saved. And Doctrine performs this in a single <strong>transaction</strong>.</p>
<pre class="brush: php;">
$u = new User();
$u-&gt;username = 'myuser';
$u-&gt;password = 'mypass';

$u2 = new User();
$u2-&gt;username = 'foouser';
$u2-&gt;password = 'foopass';

$conn = Doctrine_Manager::connection();

$conn-&gt;flush();
</pre>
<p>This way you don&#8217;t need to call the save() method for each object.</p>
<h4>Raw SQL</h4>
<p>We can just give a plain SQL query to the <strong>Doctrine_Connection</strong> object and call the <strong>execute()</strong> method.</p>
<p>This also supports binding of values to the query (with the usage of &#8216;?&#8217;), which automatically filters against SQL injection.</p>
<pre class="brush: php;">
$data = array('myuser','mypass');

$conn = Doctrine_Manager::connection();

$conn-&gt;execute('INSERT INTO user (username, password) VALUES (?,?)',  $data);
</pre>
<h3>2. READ</h3>
<p>The act of fetching records from the database.</p>
<p>Most of these are performed on <strong>Doctrine_Table</strong> objects, which is obtained by calling <strong>Doctrine::getTable()</strong> and passing the model class name to it.</p>
<h4>find()</h4>
<p>The <strong>find()</strong> method fetches a record by the <strong>Primary Key</strong> value.</p>
<pre class="brush: php;">
$user_id = 1;

$u = Doctrine::getTable('User')-&gt;find($user_id);

echo $u-&gt;username;
</pre>
<h4>findOneBy*()</h4>
<p>This is a <strong>magic</strong> method. You can simply append the column name, and it will search the table by that column.</p>
<p>For example, to find a user record by username:</p>
<pre class="brush: php;">
$username = 'myuser';

$u = Doctrine::getTable('User')-&gt;findOneByUsername($username);

echo $u-&gt;username;
</pre>
<p>It fetches only one record.</p>
<h4>findBy*()</h4>
<p>Another <strong>magic</strong> method, which works similarly, but fetches multiple rows. It returns a <strong>Doctrine_Collection</strong> object.</p>
<p>You can treat this returned object just like an <strong>array</strong>, to get to the individual record.</p>
<p>(let&#8217;s assume we have a column named &#8216;status&#8217;):</p>
<pre class="brush: php;">
$users = Doctrine::getTable('User')-&gt;findByStatus('active');

echo $users[0]-&gt;username;
echo $users[1]-&gt;username;
</pre>
<p>Even if the actual column name is all lowercase, it can be used as capitalized in that magic function call (status vs. Status).</p>
<h4>DQL</h4>
<p>This is our first look at <strong>DQL</strong> in these tutorials. It stands for <strong>Doctrine Query Language</strong>. It is actually a major feature. Most advanced queries are performed using DQL.</p>
<p>In this example, we first create the query object, and add the components of the query to it. All the method calls can be <strong>chained</strong> nicely. Finally we execute the query, which returns us a <strong>Doctrine_Collection</strong> object, like that last example.</p>
<pre class="brush: php;">
$status = 'active';

$q = Doctrine_Query::create()
	-&gt;select('username')
	-&gt;from('User')
	-&gt;where('status = ?', $status)
	-&gt;limit(20);

$users = $q-&gt;execute();

echo $users[0]-&gt;username;
echo $users[1]-&gt;username;
</pre>
<p>We will see many more examples of DQL in our project. But if you want more info right now, there is a long documentation chapter <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/dql-doctrine-query-language" rel="nofollow">here</a>.</p>
<h4>toArray()</h4>
<p>A <strong>Doctrine_Record</strong> object contains a lot of stuff behind the scenes. If you ever try to print_r() that object directly, you will see a long list of data.</p>
<p>However, when you simply want the data of the record, you can convert it to an array with the <strong>toArray()</strong> call.</p>
<pre class="brush: php;">
$user_id = 1;

$u = Doctrine::getTable('User')-&gt;find($user_id);

$u_arr = $u-&gt;toArray();

print_r($u_arr);
</pre>
<p>What you get will be similar to what you get from a <strong>mysql_fetch_assoc()</strong> call.</p>
<h3>3. UPDATE</h3>
<p>The act of updating existing records.</p>
<h4>Record Object</h4>
<p>You can make direct changes to any Doctrine_Record object. Once you call save(), it will perform an UPDATE.</p>
<pre class="brush: php;">
$user_id = 1;

$u = Doctrine::getTable('User')-&gt;find($user_id);

$u-&gt;password = 'newpassword';

$u-&gt;save();
</pre>
<h4>DQL</h4>
<p>When you want to update multiple rows at once, the preferred way is to use <strong>DQL</strong>.</p>
<pre class="brush: php;">
$status = 'active';

$q = Doctrine_Query::create()
	-&gt;update('User')
	-&gt;set('status', '?', $status)
	-&gt;where('id &lt; 10');

$numrows = $q-&gt;execute();
echo &quot;$numrows records updated&quot;;
</pre>
<p>The <strong>execute()</strong> call in this case returns the number of updated rows.</p>
<h3>4. DELETE</h3>
<p>The act of deleting records from the database.</p>
<h4>Record Object</h4>
<p>You can simply call the <strong>delete()</strong> method to delete a Doctrine_Record object directly.</p>
<pre class="brush: php;">
$user_id = 1;

$u = Doctrine::getTable('User')-&gt;find($user_id);

$u-&gt;delete();
</pre>
<h4>DQL</h4>
<p>When deleting multiple records, use DQL.</p>
<pre class="brush: php;">
$q = Doctrine_Query::create()
	-&gt;delete('User')
	-&gt;where('id &lt; 10');

$numrows = $q-&gt;execute();
echo &quot;$numrows records deleted&quot;;
</pre>
<p>The <strong>execute()</strong> method call will return the number of deleted records.</p>
<h3>Stay Tuned</h3>
<p>Today, we took a short break from coding our project and explored some important subjects regarding the usage of <strong>CRUD with Doctrine</strong>. What we learned today will be very useful as we continue building our project in the next tutorials. </p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/CKAZMry6OrI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud/feed</wfw:commentRss>
		<slash:comments>46</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud</feedburner:origLink></item>
		<item>
		<title>Top 10 Reasons Why You Should Use a PHP Framework</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/M0ue6-P3H5w/top-10-reasons-why-you-should-use-a-php-framework</link>
		<comments>http://www.phpandstuff.com/articles/top-10-reasons-why-you-should-use-a-php-framework#comments</comments>
		<pubDate>Sat, 07 Nov 2009 01:45:44 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[frameworks]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=452</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/frameworks.png" alt="frameworks" title="frameworks" width="128" height="128" class="alignleft size-full wp-image-470" /> 

<strong>PHP Frameworks</strong> have been receiving a lot of attention in the past few years from the web development community. What's this hype all about?

If you look at PHP Job listings, you will often see "MVC Framework Experience" as one of their requirements. It is becoming one of those must-have skill sets for web developers.

There are pretty good reasons behind all of this. In this article we will explore why you, as a PHP programmer, should be using a <strong>PHP Framework</strong>.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Ftop-10-reasons-why-you-should-use-a-php-framework"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/frameworks.png" alt="frameworks" title="frameworks" width="128" height="128" class="alignleft size-full wp-image-470" /> </p>
<p><strong>PHP Frameworks</strong> have been receiving a lot of attention in the past few years from the web development community. What&#8217;s this hype all about?</p>
<p>If you look at PHP Job listings, you will often see &#8220;MVC Framework Experience&#8221; as one of their requirements. It is becoming one of those must-have skill sets for web developers.</p>
<p>There are pretty good reasons behind all of this. In this article we will explore why you, as a PHP programmer, should be using a <strong>PHP Framework</strong>.</p>
<div class="clear"></div>
<h3>1. Code and File Organization</h3>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/php_frameworks_reasons_1.png" alt="php_frameworks_reasons_1" title="php_frameworks_reasons_1" width="282" height="307" class="alignright size-full wp-image-456" /></p>
<p>Just because you created an &#8220;/inc&#8221; folder and made a &#8220;functions.php&#8221; file does not mean your code is organized. </p>
<p>When you setup a <strong>PHP Framework</strong>, it already has a certain folder structure. It is expected from you to follow the same standards and keep everything organized in a certain way.</p>
<p>Once you get used to this model, you will never want to go back. </p>
<p>Unfortunately for some command line champions that still use vi, this can be a challenge. You will need to work with more files, that are smaller in size. But when you use a decent modern <strong>code editor</strong> or an <strong>IDE</strong>, it will be a breeze to browse through your application code and find what you need, quickly.</p>
<div class="clear"></div>
<h3>2. Utilities and Libraries</h3>
<p><strong>PHP</strong> is a great language for web development and provides countless number of tools and libraries.</p>
<p>However, if you ever try to build a whole website with PHP alone, you will find yourself either hunting down a lot of 3rd party code and libraries, or have to write them yourself.</p>
<p>All top PHP frameworks come with certain <strong>Libraries</strong> and <strong>Helpers</strong>, that help you with:</p>
<ul>
<li>Form Validation</li>
<li>Input/Output filtering</li>
<li>Database Abstraction</li>
<li>Session and Cookie Handling</li>
<li>Email, Calendar, Pagination etc&#8230;</li>
</ul>
<p>The list goes on. Not to mention, there is plenty of <strong>plugins</strong> provided by the community that you can add to your framework.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/appflowchart.gif" alt="appflowchart" title="appflowchart" width="697" height="205" class="aligncenter size-full wp-image-466" /></p>
<h3>3. The MVC Pattern</h3>
<p>The famous <strong>Model View Controller Pattern</strong> dates all the way back to 1979, when a guy named <strong>Trygve Reenskaug</strong> (a Norwegian computer scientist) first described it.</p>
<p>PHP itself works like a template engine. However, when used irresponsibly, it leads to very ugly and unmaintainable code.</p>
<p>The way the <strong>MVC Pattern</strong> applies to PHP applications:</p>
<ul>
<li><strong>Models</strong> represent your data structures, usually by interfacing with the database.</li>
<li><strong>Views</strong> contain page templates and output.</li>
<li><strong>Controllers</strong> handle page requests and bind everything together.</li>
</ul>
<p>This kind of separation leads to cleaner and more maintainable code.</p>
<h3>4. Security</h3>
<p>In PHP you can already find many input and output filtering functions to protect your website against certain attacks.</p>
<p>However, manually using these functions can get tiring and you may forget about them every once in a while.</p>
<p>With a framework, most of the work can be done for you automatically. For example in CodeIgniter:</p>
<ul>
<li>Any value passed to database object gets filtered against SQL injection attacks.</li>
<li>All html generating functions, such as form helpers and url helpers filter the output automatically.</li>
<li>All user input can be filtered against XSS attacks.</li>
<li>Encrypting cookies automatically is only a matter of changing a config option.</li>
</ul>
<h3>5. Less Code &#038; Faster Development</h3>
<p>There is of course a learning curve for all PHP Frameworks. But once you get over this hump, you will enjoy the benefits of <strong>rapid application development</strong>.</p>
<p>You will write less code, which means less time spent typing. You will not have to chase down 3rd party libraries all the time for every new project because most of them will come with the default framework install.</p>
<p>Also, since you are being more organized, it will be much faster to chase down bugs, maintain code, and make changes to existing code.</p>
<h3>6. Community Support</h3>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/php_frameworks_reasons_2.png" alt="php_frameworks_reasons_2" title="php_frameworks_reasons_2" width="600" height="154" class="aligncenter size-full wp-image-463" /></p>
<p>All popular PHP Frameworks have great active <strong>communities</strong> behind them. You can talk to other developers, get help, feedback and also give back to the community yourself.</p>
<p>There are message boards and mailing lists&#8230; You can also learn a lot by just browsing the forums and look at what other people are talking about.</p>
<h3>7. Job Opportunities</h3>
<p>Have you looked at any PHP Job postings lately? Most of them require experience with either Frameworks or a CMS. Follow the demand!</p>
<p>Example from Careerbuilder.com:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/php_frameworks_reasons_3.png" alt="php_frameworks_reasons_3" title="php_frameworks_reasons_3" width="508" height="106" class="aligncenter size-full wp-image-465" /></p>
<p>Experience with PHP Frameworks greatly increases your job qualifications as a web developer.</p>
<h3>8. Performance Tools</h3>
<p>One of the main arguments from the naysayers comes in this subject. There is obviously a performance hit when you build a &#8220;Hello World&#8221; application with a framework vs. plain PHP code.</p>
<p>But those benchmarks are just bad examples. First of all, you should understand that <strong>developers are more expensive than servers</strong>. Saving time from development and maintenance is likely to outweigh any extra money you need to spend on servers.</p>
<p>Putting all of that aside, you can actually gain performance <strong>benefits</strong> by using a PHP framework. They come with tools that help you do <strong>caching</strong>, <strong>benchmarks</strong>, <strong>profiling</strong> etc&#8230;</p>
<p>Modern frameworks are also great with <strong>dynamic loading</strong>, as they load code only as needed. Different page requests can load different amount of library code based on what needs to be used.</p>
<h3>9. Suitable for Teamwork</h3>
<p>The way your project is organized in a PHP Framework also helps you create a suitable environment for teamwork.</p>
<p>You can let your designers work on the <strong>Views</strong>, database guru work on the <strong>Models</strong>, let the smart programmer (yourself <img src='http://www.phpandstuff.com/wp-includes/images/smilies/icon_wink.gif' alt=';)' class='wp-smiley' /> ) build reusable Libraries and Plugins etc&#8230; </p>
<p>Also you can let someone build <strong>unit tests</strong>, because they come with tools for that too.</p>
<h3>10. And It&#8217;s Fun!</h3>
<p>This might actually be most important point of all. When you have fun doing your work, you will be more productive and happier in general.</p>
<p>If you have been coding plain old PHP for years, and getting really bored with it, getting started with a Framework can give you that crucial morale boost you have been lacking.</p>
<p>It&#8217;s like getting a new toy, and being able to build cool things with it. At least that&#8217;s how I felt when I first got started with Frameworks. I&#8217;m sure many of the web developers have gone through similar experiences.</p>
<h3>Conclusion</h3>
<p>Using a <strong>PHP Framework</strong> may or may not be the best choice for you. However, you should always keep an open mind and keep up to date with all the new developments in the web development world.</p>
<p>Frameworks are cool and hot today, and we can&#8217;t tell what tomorrow is going to bring. I guess all I&#8217;m saying is that they are definitely worth looking into.</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/M0ue6-P3H5w" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/top-10-reasons-why-you-should-use-a-php-framework/feed</wfw:commentRss>
		<slash:comments>24</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/top-10-reasons-why-you-should-use-a-php-framework</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 4 – User Login</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/85tshf1Ug60/codeigniter-doctrine-scratch-day-4-user-login</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login#comments</comments>
		<pubDate>Fri, 06 Nov 2009 07:16:30 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=418</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode we are going to build a <strong>User Signup Form</strong> following these steps:

- We build a <strong>Login Form View</strong> and a <strong>Login Controller</strong>.
- Learn about some <strong>URL Helpers</strong>.
- Change the <strong>Default Controller</strong>.
- Implement <strong>User Authentication</strong>.
- Learn about <strong>Singleton Pattern</strong> and use it to improve our code design.
- Learn about the <strong>Sessions Library</strong>. 
- Implement <strong>User Logout</strong>.

<img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_1.png" alt="ci_doctrine_day4_1" title="ci_doctrine_day4_1" width="434" height="421" class="aligncenter size-full wp-image-423" />]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-4-user-login"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="Codeigniter Doctrine" title="Codeigniter Doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode we are going to build a <strong>User Login</strong> system following these steps:</p>
<p>- We will build a <strong>Login Form View</strong> and a <strong>Login Controller</strong>.<br />
- Learn about some <strong>URL Helpers</strong>.<br />
- Change the <strong>Default Controller</strong>.<br />
- Implement <strong>User Authentication</strong>.<br />
- Learn about <strong>Singleton Pattern</strong> and use it to improve our code design.<br />
- Learn about the <strong>Sessions Library</strong>.<br />
- Implement <strong>User Logout</strong>.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_1.png" alt="ci_doctrine_day4_1" title="ci_doctrine_day4_1" width="434" height="421" class="aligncenter size-full wp-image-423" /></p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Login Form View</h3>
<p>First thing we are going to do is to create the <strong>View</strong> for the <strong>Login Form</strong>.</p>
<p>We are going to make this one very similar to the <strong>Signup Form</strong> we created in the <a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">last article</a>.</p>
<ul>
<li>Create: <strong>system/application/views/login_form.php</strong></li>
</ul>
<pre class="brush: php; highlight: [33]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Login Form&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;User Login&lt;/p&gt;

	&lt;?php echo form_open('login/submit'); ?&gt;

	&lt;?php echo validation_errors('&lt;p class=&quot;error&quot;&gt;','&lt;/p&gt;'); ?&gt;

	&lt;p&gt;
		&lt;label for=&quot;username&quot;&gt;Username: &lt;/label&gt;
		&lt;?php echo form_input('username',set_value('username')); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;password&quot;&gt;Password: &lt;/label&gt;
		&lt;?php echo form_password('password'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;?php echo form_submit('submit','Login'); ?&gt;
	&lt;/p&gt;

	&lt;?php echo form_close(); ?&gt;
	&lt;p&gt;
		&lt;?php echo anchor('signup','Create an Account'); ?&gt;
	&lt;/p&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>All I did was copy the contents of the signup form, change the page title, remove some form fields and added a link at the bottom to the signup form.</p>
<h4>anchor()</h4>
<p>On <strong>Line 33</strong> in the file above, I used a function named <strong>anchor()</strong>. This is part of the <strong>URL Helper</strong> in CodeIgniter. It helps us create links with ease. The first argument is the <strong>Controller Name</strong>, and the second argument is the <strong>Link Text</strong>. You can also pass an optional third argument for extra html attributes. The result is:</p>
<pre class="brush: xml;">
&lt;a href=&quot;http://localhost/ci_doctrine/signup&quot;&gt;Create an Account&lt;/a&gt;
</pre>
<h4>Style the links</h4>
<p>I am just going to make a small addition to the <strong>stylesheet</strong> so our links look better.</p>
<ul>
<li>Edit: css/style.css</li>
</ul>
<pre class="brush: css; highlight: [8,9,10,11,12,13,14];">
body {
	font-family: &quot;Trebuchet MS&quot;,Arial;
	font-size: 14px;
	background-color: #212426;
	color: #11151E;
}

a {
	color: #FFF;
}

a:hover {
	color: #B9AA81;
}

/* ... */
</pre>
<p>I only added the highlighted lines.</p>
<h4>Link from the Signup Form</h4>
<p>Likewise, we will add a link from the <strong>Signup Form</strong> to the new <strong>Login Form</strong>.</p>
<ul>
<li>Edit: <strong>system/application/views/signup_form.php</strong></li>
</ul>
<pre class="brush: php; highlight: [39,40,41]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;New User Signup&lt;/p&gt;

	&lt;?php echo form_open('signup/submit'); ?&gt;

	&lt;?php echo validation_errors('&lt;p class=&quot;error&quot;&gt;','&lt;/p&gt;'); ?&gt;

	&lt;p&gt;
		&lt;label for=&quot;username&quot;&gt;Username: &lt;/label&gt;
		&lt;?php echo form_input('username',set_value('username')); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;password&quot;&gt;Password: &lt;/label&gt;
		&lt;?php echo form_password('password'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;passconf&quot;&gt;Confirm Password: &lt;/label&gt;
		&lt;?php echo form_password('passconf'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;email&quot;&gt;E-mail: &lt;/label&gt;
		&lt;?php echo form_input('email',set_value('email')); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;?php echo form_submit('submit','Create my account'); ?&gt;
	&lt;/p&gt;
	&lt;?php echo form_close(); ?&gt;
	&lt;p&gt;
		&lt;?php echo anchor('login','Login Form'); ?&gt;
	&lt;/p&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I only added the highlighted lines.</p>
<p><strong>Note:</strong> We just linked to a <strong>Controller</strong> named <strong>login</strong>. This Controller does not exist yet. So let&#8217;s create it.</p>
<h3>Login Controller</h3>
<p>First we are going create a sort of skeleton structure for our new Controller.</p>
<ul>
<li>Create: <strong>system/application/controllers/login.php</strong></li>
</ul>
<pre class="brush: php; highlight: [22];">
&lt;?php
class Login extends Controller {

	public function __construct() {
		parent::Controller();

		$this-&gt;load-&gt;helper(array('form','url'));
		$this-&gt;load-&gt;library('form_validation');
	}

	public function index() {
		$this-&gt;load-&gt;view('login_form');
	}

	public function submit() {

		if ($this-&gt;_submit_validate() === FALSE) {
			$this-&gt;index();
			return;
		}

		redirect('/');

	}

	private function _submit_validate() {

	}

}
</pre>
<p>This looks very similar to the <strong>submit Controller</strong> we created in the last article. The only new thing is the highlighted line.</p>
<h4>redirect()</h4>
<p>This function is part of the <strong>URL Helper</strong>. It forwards the surfer to a specified Controller. In this case we only passed <strong>&#8216;/&#8217;</strong>, which will basically send the surfer to the <strong>Home Page</strong> or in other words the <strong>Default Controller</strong>.</p>
<p>So the user will end up at <strong>http://localhost/ci_doctrine/</strong>.</p>
<h4>Test The Login Controller+View</h4>
<ul>
<li>Go here: <a href="http://localhost/ci_doctrine/login" rel="nofollow">http://localhost/ci_doctrine/login</a></li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_41.png" alt="ci_doctrine_day4_4" title="ci_doctrine_day4_4" width="423" height="378" class="aligncenter size-full wp-image-437" /></p>
<ul>
<li>Now click the link that says <strong>Create an Account</strong>.</li>
</ul>
<p>You should see our old <strong>Signup Form</strong> page.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_3.png" alt="ci_doctrine_day3_3" title="ci_doctrine_day3_3" width="484" height="501" class="aligncenter size-full wp-image-390" /></p>
<p>Works great!</p>
<h3>Default Controller</h3>
<p>When someone visits the main page of our website (i.e. there is no controller name in the url), it calls the <strong>Default Controller</strong>. Right now if you go to <strong>http://localhost/ci_doctrine/</strong>, you will see this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_3.png" alt="ci_doctrine_day1_3" title="ci_doctrine_day1_3" width="500" height="276" class="aligncenter size-full wp-image-184" /></p>
<p>Because CodeIgniter is loading a Controller named <strong>welcome</strong> by default.</p>
<p>Let&#8217;s say we would like to have a Default Controller named <strong>home</strong> instead.</p>
<ul>
<li>Create: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Home extends Controller {

	public function index() {
		echo &quot;Home Sweet Home!&quot;;
	}	

}
</pre>
<h4>Routes File</h4>
<ul>
<li>Edit: <strong>system/application/config/routes.php</strong></li>
</ul>
<p>Changing just one line:</p>
<pre class="brush: php; highlight: [2];">
// ...
$route['default_controller'] = &quot;home&quot;;
$route['scaffolding_trigger'] = &quot;&quot;;
// ...
</pre>
<p>That&#8217;s it. Now when you go to <a href="http://localhost/ci_doctrine/" ref="nofollow">http://localhost/ci_doctrine/</a>, you will see our controller:</p>
<pre>
Home Sweet Home!
</pre>
<p>The Routes File has some other purposes, which we will not get into right now. But you can read more about it <a rel="nofollow" href="http://codeigniter.com/user_guide/general/routing.html">here</a>.</p>
<h3>User Login (Authentication)</h3>
<p>Now that our forms are in place, we need to add authentication functionality to our application.</p>
<p>First I want to show you how to accomplish it in a simple and most common way. Once we cover that, I will show you a better way of handling this.</p>
<h4>Authentication with Form Validation</h4>
<ul>
<li>Edit: <strong>system/application/controllers/login.php</strong></li>
</ul>
<pre class="brush: php; highlight: [26,40];">
&lt;?php
class Login extends Controller {

	public function __construct() {
		parent::Controller();

		$this-&gt;load-&gt;helper(array('form','url'));
		$this-&gt;load-&gt;library('form_validation');
	}

	public function index() {
		$this-&gt;load-&gt;view('login_form');
	}

	public function submit() {

		if ($this-&gt;_submit_validate() === FALSE) {
			$this-&gt;index();
			return;
		}

		redirect('/');

	}

	private function _submit_validate() {

		$this-&gt;form_validation-&gt;set_rules('username', 'Username',
			'trim|required|callback_authenticate');

		$this-&gt;form_validation-&gt;set_rules('password', 'Password',
			'trim|required');

		$this-&gt;form_validation-&gt;set_message('authenticate','Invalid login. Please try again.');

		return $this-&gt;form_validation-&gt;run();

	}

	public function authenticate() {

		// get User object by username
		if ($u = Doctrine::getTable('User')-&gt;findOneByUsername($this-&gt;input-&gt;post('username'))) {

			// this mutates (encrypts) the input password
			$u_input = new User();
			$u_input-&gt;password = $this-&gt;input-&gt;post('password');

			// password match (comparing encrypted passwords)
			if ($u-&gt;password == $u_input-&gt;password) {
				unset($u_input);
				return TRUE;
			}
			unset($u_input);
		}

		return FALSE;
	}
}
</pre>
<p>Highlighted functions have been updated.</p>
<p>First I added some form validation rules inside the <strong>_submit_validate()</strong> function, like in the last article. But this time I added a <strong>Callback</strong> rule. Notice on Line 29: <strong>callback_authenticate</strong>. The format is <strong>callback_[function_name]</strong>.</p>
<p>On <strong>Line 34</strong> I set a custom message for this validation rule, in case it fails.</p>
<p>Then I added the function named <strong>authenticate</strong>. This callback function needs to return TRUE when everything is good, and FALSE when the validation fails.</p>
<p><strong>Lines 43-53:</strong> This is where I perform the username and password check for the login. First I attempt to get the <strong>User Record</strong> searching by the input <strong>username</strong>. (We learned about the getTable and findOneBy* functions in the last article).</p>
<h4>Applying the Mutator to an external value</h4>
<p>Remember we added a <strong>Mutator</strong> to the password field in the last article?</p>
<p>Since the stored passwords are encrypted, I need to apply the same encryption to the user input, before I can compare the two.</p>
<p>That&#8217;s why I create a new User object named <strong>$u_input</strong>. on <strong>Line 46</strong> and assigned the input password to it. This is how I trigger the <strong>Mutator</strong> function on the password that was entered in the form. (If anyone knows a better of doing this, let me know!)</p>
<p>Now the encrypted version of the input password resides in <strong>$u_input->password</strong>. So I was able to compare it to <strong>$u->password</strong>.</p>
<p>I also <strong>unset</strong> the $u_input object, just to make sure it doesn&#8217;t get saved as a new record by accident.</p>
<h4>Testing the Form</h4>
<p>First create a new user by going to the <strong>Signup Form</strong> at <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a>.</p>
<p>Now go to: <a href="http://localhost/ci_doctrine/login" rel="nofollow">http://localhost/ci_doctrine/login</a> and use a <strong>wrong</strong> login. You should see:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_1.png" alt="ci_doctrine_day4_1" title="ci_doctrine_day4_1" width="434" height="421" class="aligncenter size-full wp-image-423" /></p>
<p>When you use a <strong>correct</strong> login, you should get forwarded back to the <strong>home</strong> page.</p>
<pre>
Home Sweet Home!
</pre>
<p>Our Login Form works!</p>
<h3>Now the Better Way!</h3>
<p>I mentioned I was going to change things a bit and show you how to do this in a better way.</p>
<h4>What&#8217;s wrong with the current method?</h4>
<ol>
<li>I don&#8217;t like how the authentication code is all inside the <strong>Controller</strong>. This is not good for code reusability.</li>
<li>It should be part of the <strong>User Model</strong>, since it&#8217;s directly related to it.</li>
<li>We stored the <strong>User Record</strong> in a variable named <strong>$u</strong>. But it&#8217;s inside a function and not <strong>global</strong>. So, if other Controllers need to use it, they can&#8217;t.</li>
<li>Turning the object <strong>$u</strong> directly into a <strong>Global Variable</strong> would be a bad design decision.</li>
<li>We do not want to store the whole user object inside the <strong>session</strong>. Doctrine Models have a lot of internal data, which could quickly inflate the size of our session storage. Only thing we are going store in the session is the <strong>user_id</strong>.</li>
</ol>
<h4>Singleton Pattern to the rescue!</h4>
<p>Some of you may not know what <strong>Singleton Pattern</strong> means. It&#8217;s one of the most popular <strong>design patterns</strong>, and I will show you how we are going to use it.</p>
<p>With this new class I am going to create, we will have a better design for our authentication functionality, and we will also make the User Model instance for the logged in user globally available in our application.</p>
<h3>Singleton Pattern for Current User</h3>
<p>First let&#8217;s build the skeleton:</p>
<ul>
<li>Create: <strong>system/application/models/current_user.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Current_User {

	private static $user;

	private function __construct() {}

	public static function user() {

		if(!isset(self::$user)) {

			// put the User record into $this-&gt;user
			// ...

		}

		return self::$user;
	}

	public function __clone() {
		trigger_error('Clone is not allowed.', E_USER_ERROR);
	}

}
</pre>
<p>Now let&#8217;s go over the code:</p>
<ul>
<li>There is a reason I called the class <strong>Current_User</strong>. Because this <strong>static</strong> class will always return an instance of the <strong>User</strong> class, for the <strong>current logged in user</strong>.</li>
<li>This class does NOT extend <strong>Doctrine_Record</strong>, because we are not really creating a Doctrine Model.</li>
<li>The <strong>$user</strong> variable will contain the User object for the logged in user. And we will access it by <strong>Current_User::user()</strong>. That is the syntax for calling a <strong>static</strong> class function.</li>
<li>We will never create an instance of this Current_User class, so the <strong>constructor</strong> is set to <strong>private</strong>.</li>
<li>We also disallow <strong>cloning</strong> of this class so the <strong>__clone()</strong> function triggers an error.</li>
</ul>
<p>Now I&#8217;m going to add a bit more code to make this functional.</p>
<ul>
<li>Edit: <strong>system/application/models/current_user.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Current_User {

	private static $user;

	private function __construct() {}

	public static function user() {

		if(!isset(self::$user)) {

			$CI =&amp; get_instance();
			$CI-&gt;load-&gt;library('session');

			if (!$user_id = $CI-&gt;session-&gt;userdata('user_id')) {
				return FALSE;
			}

			if (!$u = Doctrine::getTable('User')-&gt;find($user_id)) {
				return FALSE;
			}

			self::$user = $u;
		}

		return self::$user;
	}

	public static function login($username, $password) {

		// get User object by username
		if ($u = Doctrine::getTable('User')-&gt;findOneByUsername($username)) {

			// this mutates (encrypts) the input password
			$u_input = new User();
			$u_input-&gt;password = $password;

			// password match (comparing encrypted passwords)
			if ($u-&gt;password == $u_input-&gt;password) {
				unset($u_input);

				$CI =&amp; get_instance();
				$CI-&gt;load-&gt;library('session');
				$CI-&gt;session-&gt;set_userdata('user_id',$u-&gt;id);
				self::$user = $u;

				return TRUE;
			}

			unset($u_input);
		}

		// login failed
		return FALSE;

	}

	public function __clone() {
		trigger_error('Clone is not allowed.', E_USER_ERROR);
	}

}
</pre>
<p>Let&#8217;s go over the code in <strong>user()</strong> method first:</p>
<ul>
<li>The usage for this function is: Current_User::user() and it returns the User object for the logged in user.</li>
<li><strong>Line 10</strong>: We check to see if the user object is already there. If it is, we return it at line 26 . </li>
<li><strong>Lines 12-17</strong>: We load the session library, so we can read/write in the session. If the user is logged in, his id should be stored there. If we don&#8217;t see the <strong>user_id</strong>, it returns FALSE.</li>
<li>We had to use the <strong>$CI</strong> object to load the session library because this is a static class.</li>
<li><strong>Lines 19-21</strong>: Fetch the User object by id. If we can&#8217;t, return FALSE. Note that we used a function named <strong>find()</strong> to look up by id.</li>
<li><strong>Lines 23 and 26</strong>: Everything went well, so we store the user object in the static variable <strong>$user</strong> and return it.</li>
</ul>
<p>Now, when we call <strong>Current_User::user()</strong> , we can get the User object as if it&#8217;s a <strong>global variable</strong>. And if it returns false, it means the user is NOT logged in.</p>
<p>Let&#8217;s go over the <strong>login()</strong> method:</p>
<ul>
<li>I copied most of the code from the <strong>login</strong> Controller we created earlier. The code is from the <strong>authenticate()</strong> method.</li>
<li>I added loading of the <strong>session library</strong> at <strong>line 42-43</strong>, so I could store the user_id in the session at <strong>line 44</strong></li>
<li>I also added <strong>line 45</strong>. Once the user gets logged in, the <strong>$user</strong> static variable is set, so it can be returned by the <strong>user()</strong> function later.</li>
</ul>
<p>By the way, we just learned how to use <strong>Sessions</strong> in CodeIgniter. It&#8217;s not very complicated. All you need to do is to load the <strong>library</strong> and you can use the <strong>userdata()</strong> and <strong>set_userdata()</strong> function to read and write the variables. You can read more about it <a href="http://codeigniter.com/user_guide/libraries/sessions.html" rel="nofollow">here</a>.</p>
<p>Now we can call the static function like this: <strong>Current_User::login($username,$password)</strong> , and it will take care of the rest.</p>
<p>Phew! I hope that was not very complicated. But I&#8217;m sure you will soon  understand why we went through all of that.</p>
<h4>Simplified Login Controller</h4>
<p>We are about the see the first benefit of creating all that code above.</p>
<ul>
<li>Edit: <strong>system/application/controllers/login.php</strong></li>
</ul>
<p>Only editing the authenticate() function:</p>
<pre class="brush: php;">
&lt;?php
class Login extends Controller {

	// ...

	public function authenticate() {

		return Current_User::login($this-&gt;input-&gt;post('username'),
									$this-&gt;input-&gt;post('password'));

	}
}
</pre>
<p>See how easy that is now?</p>
<p>When we call <strong>Current_User::login()</strong> it attempts to login the user, and returns <strong>TRUE</strong> on success. If the login information is <strong>incorrect</strong>, it returns <strong>FALSE</strong>. </p>
<p>Once the user is logged in this way, we can retrieve the <strong>User</strong> object for the logged in user, anywhere in our application by simply calling <strong>Current_User::user()</strong>.</p>
<p>Also note that we didn&#8217;t need to put &#8220;$this->load->model(&#8216;Current_User&#8217;)&#8221; in the code, and we will never have to. The Current_User class will always be globally available in the application, because of the Doctrine autoloader that was registered in the &#8220;system/application/plugins/doctrine_pi.php&#8221; file.</p>
<h3>Logout</h3>
<p>Now we are going to let users <strong>logout</strong> by clicking a link. But first:</p>
<h4>Autoloading Libraries</h4>
<p>It seems like we are going to be using the Session Library almost everywhere in our application. Let&#8217;s have it autoloaded by CodeIgniter so we don&#8217;t have to keep calling <strong>$this->library->load(&#8216;session&#8217;)</strong> all the time.</p>
<ul>
<li>Edit: <strong>system/application/config/autoload.php</strong></li>
</ul>
<p>Find this line:</p>
<pre class="brush: php;">
// ...
$autoload['libraries'] = array('session');
// ...
</pre>
<p>Let&#8217;s also autoload the <strong>URL Helper</strong>.</p>
<ul>
<li>Edit: <strong>system/application/config/autoload.php</strong></li>
</ul>
<p>Find this line:</p>
<pre class="brush: php;">
// ...
$autoload['helper'] = array('url');
// ...
</pre>
<p>Now that&#8217;s out of the way.</p>
<h4>Logout Controller</h4>
<ul>
<li>Create: <strong>system/application/controllers/logout.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Logout extends Controller {

	public function index() {

		$this-&gt;session-&gt;sess_destroy();
		$this-&gt;load-&gt;view('logout');
	}

}
</pre>
<p>We remove all of the <strong>session data</strong> by calling <strong>$this->session->sess_destroy()</strong>. Now the user will no longer be logged in.</p>
<h4>Logout View</h4>
<ul>
<li>Create: <strong>system/application/views/logout.php</strong></li>
</ul>
<pre class="brush: php; highlight: [8];">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Logout&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
	&lt;meta http-equiv=&quot;refresh&quot; content=&quot;3;url=&lt;?php echo base_url(); ?&gt;&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div&gt;

	&lt;p&gt;
		You are now logged out.
	&lt;/p&gt;
	&lt;p&gt;
		Redirecting you &lt;?php echo anchor('/','home'); ?&gt;.
	&lt;/p&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>This logout page will display a short message and redirect the surfer using a <strong>meta refresh</strong>.</p>
<h4>Style Changes</h4>
<p>I have made some css changes, so just copy paste the following:</p>
<ul>
<li>Edit: <strong>css/style.css</strong></li>
</ul>
<pre class="brush: css;">
body {
	font-family: &quot;Trebuchet MS&quot;,Arial;
	font-size: 14px;
	background-color: #212426;
	color: #B9AA81;
}

a {
	color: #FFF;
}

a:hover {
	color: #B9AA81;
}

input, textarea, select {
	font-family:inherit;
	font-size:inherit;
	font-weight:inherit;
}

#signup_form {
	margin-left: auto;
	margin-right: auto;
	width: 360px;

	font-size: 16px;

}

#signup_form .heading {
	text-align: center;
	font-size: 22px;
	font-weight: bold;
	color: #B9AA81;
}

#signup_form form {

	background-color: #B9AA81;
	padding: 10px;

	border-radius: 8px;
	-moz-border-radius: 8px;
	-webkit-border-radius: 8px;

}

#signup_form form label {
	font-weight: bold;
	color: #11151E;
}

#signup_form form input[type=text],input[type=password] {
	width: 316px;
	font-weight: bold;
	padding: 8px;

	border: 1px solid #FFF;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}

#signup_form form input[type=submit] {
	display: block;
	margin: auto;
	width: 200px;
	font-size: 18px;
	background-color: #FFF;
	border: 1px solid #BBB;

}

#signup_form form input[type=submit]:hover {
	border-color: #000;
}

#signup_form .error {
	font-size: 13px;
	color: #690C07;
	font-style: italic;
}
</pre>
<h4>Home View</h4>
<p>Now we are going to see how easy it is to fetch user information for the logged in user.</p>
<ul>
<li>Create: <strong>system/application/views/home.php</strong></li>
</ul>
<pre class="brush: php; highlight: [13,14]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Home&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div&gt;

	&lt;?php if(Current_User::user()): ?&gt;
		&lt;h2&gt;Hello &lt;em&gt;&lt;?php echo Current_User::user()-&gt;username; ?&gt;&lt;/em&gt;.&lt;/h2&gt;
		&lt;h2&gt;&lt;?php echo anchor('logout','Logout'); ?&gt;&lt;/h2&gt;
	&lt;?php else: ?&gt;
		&lt;h2&gt;New Users: &lt;?php echo anchor('signup','Create an Account'); ?&gt;.&lt;/h2&gt;
		&lt;h2&gt;Members: &lt;?php echo anchor('login','Login'); ?&gt;.&lt;/h2&gt;
	&lt;?php endif; ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<h4>Home Controller</h4>
<ul>
<li>Edit: <strong>system/application/controllers/home.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
class Home extends Controller {

	public function index() {
		$this-&gt;load-&gt;view('home');
	}	

}
</pre>
<p>That&#8217;s it!</p>
<h3>Let&#8217;s Test It</h3>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/logout" rel="nofollow">http://localhost/ci_doctrine/logout</a> to make sure you are logged out.</li>
</ul>
<p>First you will see:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_2.png" alt="ci_doctrine_day4_2" title="ci_doctrine_day4_2" width="372" height="175" class="aligncenter size-full wp-image-431" /></p>
<p>And it will forward you home:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_3.png" alt="ci_doctrine_day4_3" title="ci_doctrine_day4_3" width="424" height="271" class="aligncenter size-full wp-image-432" /></p>
<ul>
<li>Click the <strong>Login link</strong> to be forwarded to our <strong>Login Form</strong>.</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_4.png" alt="ci_doctrine_day4_4" title="ci_doctrine_day4_4" width="423" height="378" class="aligncenter size-full wp-image-433" /></p>
<ul>
<li>Enter a <strong>correct</strong> login info and you will be redirected <strong>home</strong> again.</li>
</ul>
<p>Now you should see:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day4_5.png" alt="ci_doctrine_day4_5" title="ci_doctrine_day4_5" width="348" height="255" class="aligncenter size-full wp-image-434" /></p>
<p>In this case my username is <strong>burak</strong>, and it was displayed back to me.</p>
<p>Voila!</p>
<h3>Stay Tuned</h3>
<p>We covered quite a few new concepts in today&#8217;s tutorial. I hope you enjoyed it and learned from it.</p>
<p>In the next tutorial we will explore the <strong>CRUD</strong> (<strong>Create</strong>, <strong>Read</strong>, <strong>Update</strong> and <strong>Delete</strong>) functionality with <strong>Doctrine</strong> in more detail.</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/85tshf1Ug60" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login/feed</wfw:commentRss>
		<slash:comments>152</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 3 – User Signup Form</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/PHakQBN6nSk/codeigniter-doctrine-scratch-day-3-user-signup-form</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form#comments</comments>
		<pubDate>Mon, 02 Nov 2009 20:59:01 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=348</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode we are going to build a <strong>User Signup Form</strong> following these steps:

- We build a <strong>"User" Model</strong> with Doctrine.
- Learn about <strong>Mutators</strong>.
- Create <strong>tables</strong> using Doctrine.
- <strong>Remove index.php</strong> from CodeIgniter urls
- <strong>Build</strong> and <strong>Style</strong> the Signup Form.
- Learn about <strong>Helpers</strong>, <strong>Libraries</strong> and how to <strong>extend</strong> them. 
- <strong>Form Validation</strong> and checking for <strong>duplicates</strong>.

<img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_3.png" alt="ci_doctrine_day3_3" title="ci_doctrine_day3_3" width="484" height="501" class="aligncenter size-full wp-image-390" />]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-3-user-signup-form"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode we are going to build a <strong>User Signup Form</strong> following these steps:</p>
<p>- We build a <strong>&#8220;User&#8221; Model</strong> with Doctrine.<br />
- Learn about <strong>Mutators</strong>.<br />
- Create <strong>tables</strong> using Doctrine.<br />
- <strong>Remove index.php</strong> from CodeIgniter urls<br />
- <strong>Build</strong> and <strong>Style</strong> the Signup Form.<br />
- Learn about <strong>Helpers</strong>, <strong>Libraries</strong> and how to <strong>extend</strong> them.<br />
- <strong>Form Validation</strong> and checking for <strong>duplicates</strong>.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_3.png" alt="ci_doctrine_day3_3" title="ci_doctrine_day3_3" width="484" height="501" class="aligncenter size-full wp-image-390" /></p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Let&#8217;s build a Doctrine Model</h3>
<p>Since we are building a user signup form today, it is best to start with a &#8220;User&#8221; Model.</p>
<p>Our model will be extending the <strong>Doctrine_Record</strong> class, which will represent records in a table named &#8220;user&#8221;.</p>
<p>So let&#8217;s make one:</p>
<ul>
<li>Create a file named <strong>user.php</strong> under <strong>system/application/models</strong></li>
<li>We name the class <strong>User</strong>, matching the file name.<br />
	The class name is <strong>capitalized</strong>, but the filename is always <strong>lowercase</strong>. (This is a CodeIgniter rule, rather than Doctrine, but we&#8217;re still going go with it for consistency.)</li>
<li>We add a method named <strong>setTableDefinition()</strong>, which will contain column info.</li>
<li>We also add a method named <strong>setUp()</strong>, which will contain additional options.</li>
</ul>
<p><strong>system/application/models/user.php</strong></p>
<pre class="brush: php;">
&lt;?php
class User extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('username', 'string', 255, array('unique' =&gt; 'true'));
		$this-&gt;hasColumn('password', 'string', 255);
		$this-&gt;hasColumn('email', 'string', 255, array('unique' =&gt; 'true'));
	}

	public function setUp() {
		$this-&gt;setTableName('user');
		$this-&gt;actAs('Timestampable');
	}
}
</pre>
<p>Looks simple right? Now let&#8217;s go over the code.</p>
<h4>$this->hasColumn()</h4>
<p>Structure:</p>
<pre class="brush: php;">$this-&gt;hasColumn($name, $type = null, $length = null, $options = array());</pre>
<p>This function call tells Doctrine about the table column structure. Everything except the $name field is optional.</p>
<p>Supported <strong>$type</strong>&#8216;s are: Boolean, Integer, Float, Decimal, String, Array, Object, Blob, Clob, Timestamp, Time, Date, Enum, Gzip.</p>
<p><strong>$options</strong> are passed in an array, as &#8216;name&#8217; => &#8216;value&#8217; pairs. We passed an option named <strong>unique</strong> for 2 columns, which means we will have <strong>unique indexes</strong> on them.</p>
<p>We don&#8217;t need to get into more detail on this, but if you want to read more, <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/defining-models" rel="nofollow">read Doctrine docs</a>.</p>
<h4>$this->setTableName()</h4>
<p>Structure:</p>
<pre class="brush: php;">$this-&gt;setTableName($table_name);</pre>
<p>Simply sets the <strong>table name</strong> the Model will use. This can have a totally different name than the Model.</p>
<h4>$this->actAs()</h4>
<p>Adds a behavior to the model.</p>
<p>The one we used was <strong>Timestampable</strong>. It adds 2 fields to the table and manages them. They are called <strong>created_at</strong> and <strong>updated_at</strong>. And you guessed it, they keep track of the records create and update times.</p>
<p><strong>Note</strong>: When we add this behavior, we don&#8217;t need those 2 columns specified inside the setTableDefinition() function.</p>
<h3>Adding Mutators</h3>
<p>Let&#8217;s say we want our <strong>password</strong> field to be automatically encrypted for security. This is where <strong>Mutators</strong> come in.</p>
<p>So, make the following changes to our model.</p>
<p><strong>system/application/models/user.php</strong> (new code is highlighted)</p>
<pre class="brush: php; highlight: [14,17,18,19,20];">
&lt;?php
class User extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('username', 'string', 255, array('unique' =&gt; 'true'));
		$this-&gt;hasColumn('password', 'string', 255);
		$this-&gt;hasColumn('email', 'string', 255, array('unique' =&gt; 'true'));

	}

	public function setUp() {
		$this-&gt;setTableName('user');
		$this-&gt;actAs('Timestampable');
		$this-&gt;hasMutator('password', '_encrypt_password');
	}

	protected function _encrypt_password($value) {
		$salt = '#*seCrEt!@-*%';
		$this-&gt;_set('password', md5($salt . $value));
	}
}
</pre>
<p>First we added a <strong>Mutator function</strong> named <strong>_encrypt_password</strong> to the <strong>password</strong> column.</p>
<p>Then we implemented it as a method inside our Model class.</p>
<p><strong>Note:</strong> For mutators to work, <strong>auto_accessor_override</strong> option needs to be enabled. We have already done it, in our plugin file doctrine_pi.php.</p>
<h3>Let Doctrine create the tables</h3>
<p>Why create the user table manually ourselves when we can just let Doctrine do it for us. <img src='http://www.phpandstuff.com/wp-includes/images/smilies/icon_smile.gif' alt=':)' class='wp-smiley' /> </p>
<p>We will use the Doctrine <strong>static</strong> class to create our tables like this:</p>
<pre class="brush: php;">
Doctrine::createTablesFromModels();
</pre>
<p>So let&#8217;s create a simple and reusable script that we can rebuild our database with.</p>
<ul>
<li>Create this controller: <strong>system/application/controllers/doctrine_tools.php</strong></li>
</ul>
<pre class="brush: php; highlight: [10];">
&lt;?php
class Doctrine_Tools extends Controller {

	function create_tables() {
		echo 'Reminder: Make sure the tables do not exist already.&lt;br /&gt;
		&lt;form action=&quot;&quot; method=&quot;POST&quot;&gt;
		&lt;input type=&quot;submit&quot; name=&quot;action&quot; value=&quot;Create Tables&quot;&gt;&lt;br /&gt;&lt;br /&gt;';

		if ($this-&gt;input-&gt;post('action')) {
			Doctrine::createTablesFromModels();
			echo &quot;Done!&quot;;
		}
	}

}
</pre>
<p>Only pay attention to the highlighted line for now. It simply reads our Doctrine Model class files, and <strong>creates tables</strong> for them in the database.</p>
<p>I know the code is a bit ugly, but we&#8217;re just going to use this controller temporarily as we write our initial models.</p>
<ul>
<li>First make sure user table <strong>does NOT exist</strong>. If it does, drop it using phpmyadmin.</li>
<li>Go to: <a href="http://localhost/ci_doctrine/index.php/doctrine_tools/create_tables" rel="nofollow">http://localhost/ci_doctrine/index.php/doctrine_tools/create_tables</a> and click the button.</li>
<li>Check out our new table.</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_1.png" alt="ci_doctrine_day3_1" title="ci_doctrine_day3_1" width="567" height="541" class="aligncenter size-full wp-image-379" /></p>
<p><strong>Note:</strong> The <strong>id</strong> column got generated automatically. We already have a setting in our <strong>doctrine_pi.php</strong> plugin file:</p>
<pre class="brush: php;">
// set the default primary key to be named 'id', integer, 4 bytes
Doctrine_Manager::getInstance()-&gt;setAttribute(
	Doctrine::ATTR_DEFAULT_IDENTIFIER_OPTIONS,
	array('name' =&gt; 'id', 'type' =&gt; 'integer', 'length' =&gt; 4));
</pre>
<p>Now let&#8217;s do some more CodeIgniter tweaking.</p>
<h3>Removing &#8220;index.php&#8221; from CodeIgniter urls</h3>
<p>We would like to have url&#8217;s like this:</p>
<pre>

http://localhost/ci_doctrine/welcome
</pre>
<p>instead of this:</p>
<pre>

http://localhost/ci_doctrine/index.php/welcome
</pre>
<p>Shorter, cleaner and nicer.</p>
<h4>follow these steps:</h4>
<ul>
<li>Our web server needs <strong>mod_rewrite</strong> enabled.<br />
	For <strong>WAMP</strong> users: Left-Click the system tray icon -> Apache -> Apache Modules -> rewrite_module</li>
<li>Create a file named <strong>.htaccess</strong> under our project folder &#8220;ci_doctrine&#8221;.</li>
<li>Copy-paste the following:</li>
</ul>
<p><strong>.htaccess:</strong></p>
<pre>
&lt;IfModule mod_rewrite.c>
    RewriteEngine On
    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ /ci_doctrine/index.php/$1 [L]
&lt;/IfModule>
&lt;IfModule !mod_rewrite.c>
    ErrorDocument 404 /ci_doctrine/index.php
&lt;/IfModule>
</pre>
<p>Now we need to tell CodeIgniter that we&#8217;re removing index.php from our url&#8217;s.</p>
<ul>
<li>Edit: <strong>system/application/config.php</strong></li>
</ul>
<pre class="brush: php;">
/*
|--------------------------------------------------------------------------
| Index File
|--------------------------------------------------------------------------
|
| Typically this will be your index.php file, unless you've renamed it to
| something else. If you are using mod_rewrite to remove the page set this
| variable so that it is blank.
|
*/
$config['index_page'] = &quot;&quot;;
</pre>
<p>That&#8217;s it!</p>
<p>To make sure it&#8217;s working, visit: <a href="http://localhost/ci_doctrine/welcome" ref="nofollow">http://localhost/ci_doctrine/welcome</a>.<br />
You should see the welcome page.</p>
<h3>Building the Signup Form</h3>
<p>Before we start coding, let&#8217;s decide how we&#8217;re going to do this</p>
<h4>The Game plan</h4>
<p>We want a <strong>Controller</strong> named <strong>signup</strong>, so the url for the signup form becomes <strong>http://localhost/ci_doctrine/signup</strong><br />
We would like this signup controller to load a <strong>View</strong> named <strong>signup_form</strong> by default, which will contain the html for the form.<br />
The form will submit to a method named <strong>submit</strong> inside the signup controller i.e. <strong>signup/submit</strong>.<br />
From there we need to <strong>validate the user input</strong>. Display <strong>errors</strong> if needed.<br />
Finally <strong>save</strong> the new user to the database using our new Doctrine Model.</p>
<h4>&#8220;Signup&#8221; Controller</h4>
<ul>
<li>Create this file: <strong>system/application/controllers/signup.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php

class Signup extends Controller {

	public function __construct() {
		parent::Controller();
	}

	public function index() {
		$this-&gt;load-&gt;view('signup_form');
	}

}
</pre>
<p>Now let&#8217;s go over the code.</p>
<ul>
<li>First we created a <strong>constructor</strong> method (line 5). This will get called first every time.<br />
	Constructors are optional, however there is a reason I decided to create one, which we will see in a bit.</li>
<li>In the constructor, we always must call the parent constructor first (line 6).</li>
<li>In the <strong>index()</strong> method, (which acts as the default method for the controller), we load a <strong>View</strong> named <strong>signup_form</strong>.</li>
</ul>
<h4>&#8220;signup_form&#8221; View</h4>
<ul>
<li>Create this file: <strong>system/application/views/signup_form.php</strong></li>
</ul>
<pre class="brush: xml;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;New User Signup&lt;/p&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>For now it&#8217;s just a simple HTML file.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a></li>
</ul>
<p>You should see the output:</p>
<pre>
New User Signup
</pre>
<h4>CodeIgniter Helpers</h4>
<p><strong><a href="http://codeigniter.com/user_guide/general/helpers.html" rel="nofollow">Helpers</a></strong> are located in <strong>system/helpers</strong>. They contain procedural utility functions that make our lives easier.</p>
<p>In this tutorial, we will be using the <strong>url</strong> and <strong>form</strong> Helpers.</p>
<p>They can be loaded like this:</p>
<pre class="brush: php;">
$this-&gt;load-&gt;helper('url');
</pre>
<p>Or load multiple helpers at once:</p>
<pre class="brush: php;">
$this-&gt;load-&gt;helper(array('form','url'));
</pre>
<h4>CodeIgniter Libraries</h4>
<p><strong><a href="http://www.codeignitor.com/user_guide/general/libraries.html" rel="nofollow">Libraries</a></strong> are very similar to <strong>Helpers</strong>, but they tend to be <strong>Object Oriented</strong> instead.</p>
<p>We will be using the <strong>form_validation</strong> library, and load it like this:</p>
<pre class="brush: php;">
$this-&gt;load-&gt;library('form_validation');
</pre>
<p>Once it&#8217;s loaded, we can access it like this:</p>
<pre class="brush: php;">
$this-&gt;form_validation-&gt;//...
</pre>
<h4>Add them to the controller</h4>
<ul>
<li>Edit: <strong>system/application/controllers/signup.php</strong></li>
</ul>
<pre class="brush: php; highlight: [8,9];">
&lt;?php

class Signup extends Controller {

	public function __construct() {
		parent::Controller();

		$this-&gt;load-&gt;helper(array('form','url'));
		$this-&gt;load-&gt;library('form_validation');
	}

	public function index() {
		$this-&gt;load-&gt;view('signup_form');
	}

}
</pre>
<p><strong>Note:</strong> When you load Helpers and Libraries inside the <strong>Constructor</strong>, they become available in all methods of that <strong>Controller</strong>. For example, now index() function can use them.<br />
<strong>Note2:</strong> When <strong>Views</strong> are loaded, they also can use the Helpers and Libraries that the Controller had loaded.</p>
<h4>Form Helper</h4>
<p>Now that we have it loaded, let&#8217;s use our <strong>Form Helper functions</strong>.</p>
<ul>
<li>Edit: <strong>system/application/views/signup_form.php</strong></li>
</ul>
<pre class="brush: php; highlight: [13,17,21,32,35]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;New User Signup&lt;/p&gt;

	&lt;?php echo form_open('signup/submit'); ?&gt;

	&lt;p&gt;
		&lt;label for=&quot;username&quot;&gt;Username: &lt;/label&gt;
		&lt;?php echo form_input('username'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;password&quot;&gt;Password: &lt;/label&gt;
		&lt;?php echo form_password('password'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;passconf&quot;&gt;Confirm Password: &lt;/label&gt;
		&lt;?php echo form_password('passconf'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;email&quot;&gt;E-mail: &lt;/label&gt;
		&lt;?php echo form_input('email'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;?php echo form_submit('submit','Create my account'); ?&gt;
	&lt;/p&gt;

	&lt;?php echo form_close(); ?&gt;
&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>I highlighted all the different kinds of functions we just called. These functions create the html for our form tags and elements.</p>
<ul>
<li>Open <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a></li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_2.png" alt="ci_doctrine_day3_2" title="ci_doctrine_day3_2" width="313" height="272" class="aligncenter size-full wp-image-387" /</p>
<p>And in the source code you can see:</p>
<pre class="brush: xml; highlight: [13,17,20,29,30];">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;New User Signup&lt;/p&gt;

	&lt;form action=&quot;http://localhost/ci_doctrine/signup/submit&quot; method=&quot;post&quot;&gt;

	&lt;p&gt;
		&lt;label for=&quot;username&quot;&gt;Username: &lt;/label&gt;
		&lt;input type=&quot;text&quot; name=&quot;username&quot; value=&quot;&quot;  /&gt;	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;password&quot;&gt;Password: &lt;/label&gt;
		&lt;input type=&quot;password&quot; name=&quot;password&quot; value=&quot;&quot;  /&gt;	&lt;/p&gt;
	&lt;p&gt;

		&lt;label for=&quot;passconf&quot;&gt;Confirm Password: &lt;/label&gt;
		&lt;input type=&quot;password&quot; name=&quot;passconf&quot; value=&quot;&quot;  /&gt;	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;email&quot;&gt;E-mail: &lt;/label&gt;
		&lt;input type=&quot;text&quot; name=&quot;email&quot; value=&quot;&quot;  /&gt;	&lt;/p&gt;
	&lt;p&gt;
		&lt;input type=&quot;submit&quot; name=&quot;submit&quot; value=&quot;Create my account&quot;  /&gt;	&lt;/p&gt;
	&lt;/form&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<h4>Let's give it Style</h4>
<ul>
<li>Create a folder named <strong>css</strong> directly under our project folder <strong>ci_doctrine</strong></li>
<li>Create file: <strong>css/style.css</strong></li>
</ul>
<pre class="brush: css;">
body {
	font-family: &quot;Trebuchet MS&quot;,Arial;
	font-size: 14px;
	background-color: #212426;
	color: #11151E;
}

input, textarea, select {
	font-family:inherit;
	font-size:inherit;
	font-weight:inherit;
}

#signup_form {
	margin-left: auto;
	margin-right: auto;
	width: 360px;

	font-size: 16px;

}

#signup_form .heading {
	text-align: center;
	font-size: 22px;
	font-weight: bold;
	color: #B9AA81;
}

#signup_form form {

	background-color: #B9AA81;
	padding: 10px;

	border-radius: 8px;
	-moz-border-radius: 8px;
	-webkit-border-radius: 8px;

}

#signup_form form label {
	font-weight: bold;
}

#signup_form form input[type=text],input[type=password] {
	width: 316px;
	font-weight: bold;
	padding: 8px;

	border: 1px solid #FFF;
	border-radius: 4px;
	-moz-border-radius: 4px;
	-webkit-border-radius: 4px;
}

#signup_form form input[type=submit] {
	display: block;
	margin: auto;
	width: 200px;
	font-size: 18px;
	background-color: #FFF;
	border: 1px solid #BBB;
}

#signup_form form input[type=submit]:hover {
	border-color: #000;
}

#signup_form .error {
	font-size: 13px;
	color: #690C07;
	font-style: italic;
}
</pre>
<p>This tutorial is not about CSS, so there is not much to explain here.</p>
<ul>
<li>Edit: <strong>system/application/views/signup_form.php</strong> again.</li>
<li>Add the highlighted lines:</li>
</ul>
<pre class="brush: xml; highlight: [6,7];">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;
</pre>
<p>As you can see, we just called the <strong>base_url()</strong> function, which returns http://localhost/ci_doctrine/ in this case. This function is part of the <strong><a href="http://codeigniter.com/user_guide/helpers/url_helper.html" rel="nofollow">URL Helper</a></strong>.</p>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a>, you will see:</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_3.png" alt="ci_doctrine_day3_3" title="ci_doctrine_day3_3" width="484" height="501" class="aligncenter size-full wp-image-390" /></p>
<h4>Form Validation</h4>
<p>If you press the submit button now, you will receive a 404 error:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_4.png" alt="ci_doctrine_day3_4" title="ci_doctrine_day3_4" width="406" height="173" class="aligncenter size-full wp-image-392" /></p>
<p>Because our submit() method does not exist.</p>
<ul>
<li>Edit: <strong>system/application/controllers/signup.php</strong></li>
</ul>
<pre class="brush: php; highlight: [16,27];">
&lt;?php

class Signup extends Controller {

	public function __construct() {
		parent::Controller();

		$this-&gt;load-&gt;helper(array('form','url'));
		$this-&gt;load-&gt;library('form_validation');
	}

	public function index() {
		$this-&gt;load-&gt;view('signup_form');
	}

	public function submit() {

		if ($this-&gt;_submit_validate() === FALSE) {
			$this-&gt;index();
			return;
		}

		$this-&gt;load-&gt;view('submit_success');

	}

	private function _submit_validate() {

		// validation rules
		$this-&gt;form_validation-&gt;set_rules('username', 'Username',
			'required|alpha_numeric|min_length[6]|max_length[12]');

		$this-&gt;form_validation-&gt;set_rules('password', 'Password',
			'required|min_length[6]|max_length[12]');

		$this-&gt;form_validation-&gt;set_rules('passconf', 'Confirm Password',
			'required|matches[password]');

		$this-&gt;form_validation-&gt;set_rules('email', 'E-mail',
			'required|valid_email');

		return $this-&gt;form_validation-&gt;run();

	}
}
</pre>
<p>Let's go over all the code we just added:</p>
<ul>
<li>We add 2 methods: <strong>submit()</strong> and <strong>_submit_validate()</strong>.</li>
<li><strong>submit()</strong> get's called when the form is submitted to <strong>signup/submit</strong>.<br />
	First it validates the input. If it fails, it calls the <strong>index()</strong> method, which display the Signup Form again.</li>
<li>If no errors found, we load a <strong>View</strong> named <strong>submit_success</strong>, which we will create in a bit.</li>
<li><strong>_submit_validate()</strong> is just a private function we created, that contains the <strong>form validation</strong> stuff.<br />
	And it returns the result of the Validation (true or false).</li>
</ul>
<p>Let's look at how the <strong>form validation functions</strong> work:</p>
<p>When we loaded the Form_Validation Library earlier</p>
<p>First we set the rules like this:</p>
<pre class="brush: php;">
$this-&gt;form_validation-&gt;set_rules('username', 'Username',
	'required|alpha_numeric|min_length[6]|max_length[12]');
</pre>
<p>The first parameter is the <strong>name of the form field</strong>.<br />
The second parameter is the literal name for it, for display purposes.<br />
The third parameter is a <strong>list of validation rules</strong>, separated by the pipe character "|".</p>
<p>You can see a list of validation rules <a href="http://codeigniter.com/user_guide/libraries/form_validation.html#rulereference" rel="nofollow">here</a>.</p>
<p>Finally we the run the validation by calling <strong>run()</strong> (line 42), which will return <strong>FALSE</strong> if a user input does not validate.</p>
<h4>Displaying Validation Errors</h4>
<p>Next thing we need to do is display the errors to the user. </p>
<ul>
<li>Edit: <strong>system/application/views/signup_form.php</strong></li>
</ul>
<pre class="brush: php; highlight: [17,21,33]; html-script: true;">
&lt;!DOCTYPE html&gt;
&lt;html lang=&quot;en&quot;&gt;
&lt;head&gt;
	&lt;meta http-equiv=&quot;Content-Type&quot; content=&quot;text/html; charset=utf-8&quot;&gt;
	&lt;title&gt;Signup Form&lt;/title&gt;
	&lt;link rel=&quot;stylesheet&quot; href=&quot;&lt;?php echo base_url(); ?&gt;css/style.css&quot;
		type=&quot;text/css&quot; media=&quot;all&quot;&gt;
&lt;/head&gt;
&lt;body&gt;

&lt;div id=&quot;signup_form&quot;&gt;

	&lt;p class=&quot;heading&quot;&gt;New User Signup&lt;/p&gt;

	&lt;?php echo form_open('signup/submit'); ?&gt;

	&lt;?php echo validation_errors('&lt;p class=&quot;error&quot;&gt;','&lt;/p&gt;'); ?&gt;

	&lt;p&gt;
		&lt;label for=&quot;username&quot;&gt;Username: &lt;/label&gt;
		&lt;?php echo form_input('username',set_value('username')); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;password&quot;&gt;Password: &lt;/label&gt;
		&lt;?php echo form_password('password'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;passconf&quot;&gt;Confirm Password: &lt;/label&gt;
		&lt;?php echo form_password('passconf'); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;label for=&quot;email&quot;&gt;E-mail: &lt;/label&gt;
		&lt;?php echo form_input('email',set_value('email')); ?&gt;
	&lt;/p&gt;
	&lt;p&gt;
		&lt;?php echo form_submit('submit','Create my account'); ?&gt;
	&lt;/p&gt;
	&lt;?php echo form_close(); ?&gt;

&lt;/div&gt;

&lt;/body&gt;
&lt;/html&gt;
</pre>
<p><strong>validation_errors()</strong> displays a list of the errors returned from the form validation (line 17).</p>
<p>The first and second arguments we passed are the html codes to be used to <strong>enclose</strong> each error output.</p>
<p>Also, On <strong>lines 21 and 33</strong> we now pass a second argument to the <strong>form_input()</strong> function call. This way, when the form is re-displayed to the user, it will be populated with the values he entered previously, so he doesn't have to start all over again.</p>
<h4>Submit Success View</h4>
<p>We will keep this one simple for now.</p>
<ul>
<li>Create: <strong>system/application/views/submit_success.php</strong></li>
</ul>
<pre class="brush: xml;">
Success!
</pre>
<h4>Test The Form</h4>
<ul>
<li>Enter some invalid data into the form and submit.</li>
</ul>
<p><a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a></p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_5.png" alt="ci_doctrine_day3_5" title="ci_doctrine_day3_5" width="466" height="620" class="aligncenter size-full wp-image-397" /></p>
<p>And if you enter everything correctly, you should see the <strong>Success!</strong> message.</p>
<h4>Saving the User</h4>
<p>Now that our form works, we're going save the new user to the database using our <strong>Doctrine Model</strong>.</p>
<ul>
<li>Edit the <strong>submit()</strong> function under <strong>system/application/controllers/signup.php</strong>: </li>
</ul>
<pre class="brush: php; highlight: [13,14,15,16,17];">
&lt;?php

class Signup extends Controller {
	// ...

	public function submit() {

		if ($this-&gt;_submit_validate() === FALSE) {
			$this-&gt;index();
			return;
		}

		$u = new User();
		$u-&gt;username = $this-&gt;input-&gt;post('username');
		$u-&gt;password = $this-&gt;input-&gt;post('password');
		$u-&gt;email = $this-&gt;input-&gt;post('email');
		$u-&gt;save();

		$this-&gt;load-&gt;view('submit_success');

	}

	// ...
}
</pre>
<p>As you can see, all we do is create a User object, assign the parameters, and call <strong>save()</strong>, and Doctrine should save the new record to the database. It's that simple.</p>
<p><strong>Note:</strong> We are using <strong>$this->input->post()</strong> to get the submitted form values. When working with CodeIgniter, we do NOT use superglobals such as <strong>$_POST</strong> directly. This provides added security benefits.</p>
<p><strong>Note2:</strong> We do NOT use any <strong>SQL filtering</strong> such as <strong>mysql_real_escape_string()</strong> when assigning the user input to the Doctrine Model, because Doctrine will take care of filtering for us.</p>
<h4>Test the Form</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a>, and submit it with proper values.</li>
<li>Check the contents of the table:</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_6.png" alt="ci_doctrine_day3_6" title="ci_doctrine_day3_6" width="647" height="480" class="aligncenter size-full wp-image-402" /></p>
<p>It's working great. But we're not quite done yet.</p>
<h4>One Little Problem</h4>
<p>Try submitting the form again with the same username and e-mail, and you will see:</p>
<pre class="brush: xml;">
&lt;br /&gt;
&lt;b&gt;Fatal error&lt;/b&gt;:  Uncaught exception 'Doctrine_Connection_Mysql_Exception' with message 'SQLSTATE[23000]: Integrity constraint violation: 1062 Duplicate entry 'testing' for key 'username'' in C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection.php:1084
Stack trace:
#0 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection\Statement.php(253): Doctrine_Connection-&amp;gt;rethrowException(Object(PDOException), Object(Doctrine_Connection_Statement))
#1 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection.php(1049): Doctrine_Connection_Statement-&amp;gt;execute(Array)
#2 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection.php(693): Doctrine_Connection-&amp;gt;exec('INSERT INTO use...', Array)
#3 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection\UnitOfWork.php(595): Doctrine_Connection-&amp;gt;insert(Object(Doctrine_Table), Array)
#4 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine in &lt;b&gt;C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Connection.php&lt;/b&gt; on line &lt;b&gt;1084&lt;/b&gt;&lt;br /&gt;
</pre>
<p>The problem is, we tried to insert a <strong>duplicate value</strong> into a <strong>unique table column</strong>.</p>
<h4>Handling Duplicates</h4>
<p>We could simply check for the existence of a duplicate with something like this:</p>
<pre class="brush: php;">
$user_table = Doctrine::getTable('User');
if ($user_table-&gt;findOneByUsername($username)) {
	// ... username already exists!
}
</pre>
<p>This is the first time we are looking into <strong>fetching records using Doctrine</strong>.</p>
<p>In the first line, we get the <strong>table object</strong> for our User Model. The name we pass is the <strong>name of the Model</strong>, and NOT the name of the table. This is important to know, in case your model and tables are named differently.</p>
<p>Then we call a magic function named <strong>findOneBy*()</strong>. It is <strong>magic</strong>, because it can be called on any other property, like findOneByEmail(). You basically need to append the property name, (which can be in <strong>camelCase format</strong>). </p>
<p>We could just add this code to our <strong>_submit_validate()</strong> function, for both username and email fields, however that's not quite what I want to do.</p>
<h3>Extending CodeIgniter Libraries</h3>
<p>Since we're using Doctrine to <strong>save time</strong> and <strong>avoid code duplication</strong>, it's only fitting that we continue with the same idea here.</p>
<p>We might need to check for duplicate records for other Models or from other Controllers later on. So we're going to build a <strong>reusable</strong> form validation rule, by <strong>extending</strong> the Form Validation class.</p>
<p>This way, other forms will have access to the same functionality later on, without having to duplicate code.</p>
<ul>
<li>Create: <strong>system/application/libraries/MY_Form_validation.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php if (!defined('BASEPATH')) exit('No direct script access allowed');

class MY_Form_validation extends CI_Form_validation {

	function unique($value, $params)
	{
		$CI =&amp; get_instance();

		$CI-&gt;form_validation-&gt;set_message('unique',
			'The %s is already being used.');

		list($model, $field) = explode(&quot;.&quot;, $params, 2);

		$find = &quot;findOneBy&quot;.$field;

		if (Doctrine::getTable($model)-&gt;$find($value)) {
			return false;
		} else {
			return true;
		}

	}
}
</pre>
<p>Let's go over the code:</p>
<ul>
<li>Line 3: The new class needs to have the prefix <strong>MY_</strong>, and extends the core class named <strong>CI_Form_validation</strong>.</li>
<li>Line 5: We are going to create a validation rule named <strong>unique</strong>. With this form_validation class, names of the methods match the names of the rules, due to how the parent class is setup.</li>
<li>Line 5: First argument $value is <strong>value</strong> of the form field input.</li>
<li>Line 5: Second argument $params is the <strong>parameter</strong> passed to the rule. Our rule will have this structure: unique[<strong>model.field</strong>]. You will see it in a bit.</li>
<li>Lines 7-9: We need to get the <strong>CodeIgniter super object</strong>, so that we can access the form_validation instance, and set the error message.</li>
<li>Lines 12+: extract from the model.field values, build the name of the findOneBy function, and check for existing records.</li>
</ul>
<p>You can read more about <a href="http://codeigniter.com/user_guide/general/creating_libraries.html" rel="nofollow">creating libraries in the docs</a>.</p>
<h4>Using the new form validation rule</h4>
<ul>
<li>Edit 2 lines in: <strong>system/application/controllers/signup.php</strong></li>
</ul>
<pre class="brush: php; highlight: [11,16];">
&lt;?php

class Signup extends Controller {

	// ...

	private function _submit_validate() {

		// validation rules
		$this-&gt;form_validation-&gt;set_rules('username', 'Username',
			'required|alpha_numeric|min_length[6]|max_length[12]|unique[User.username]');

		// ...

		$this-&gt;form_validation-&gt;set_rules('email', 'E-mail',
			'required|valid_email|unique[User.email]');

		// ...
	}
	// ...
}
</pre>
<p>As you can see, now we can use our new <strong>form validation rule</strong> named <strong>unique</strong>. We also provide the model name and the field name to this rule, in square brackets.</p>
<h4>Test the form again</h4>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine/signup" rel="nofollow">http://localhost/ci_doctrine/signup</a></li>
<li>Try to signup with the same values twice.</li>
</ul>
<p>You will see 2 errors:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/11/ci_doctrine_day3_7.png" alt="ci_doctrine_day3_7" title="ci_doctrine_day3_7" width="492" height="582" class="aligncenter size-full wp-image-404" /></p>
<h3>Stay Tuned</h3>
<p>This is it for today. We covered quite a few new subjects and I hope you enjoyed it.</p>
<p>In the next episode, we create a <strong>User Login</strong> system.</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/PHakQBN6nSk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form/feed</wfw:commentRss>
		<slash:comments>157</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratch Day 2 – The Basics</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/fKT523aDFsc/codeigniter-and-doctrine-from-scratch-day-2-the-basics</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics#comments</comments>
		<pubDate>Sat, 31 Oct 2009 01:42:44 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[models]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=290</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode:

- We do a quick fresh install of <strong>CodeIgniter</strong> and <strong>Doctrine</strong>, without going into details like last episode.
- Briefly go over some of the <strong>basic concepts</strong> of CodeIgniter and Doctrine.
- First we will review <strong>Controllers</strong> and <strong>Views</strong> in CodeIgniter.
- Then we will move on to <strong>Models</strong> using Doctrine. This is where things are going to get a little different, compared to other CodeIgniter tutorials out there.
- Finally we will preview a sample <strong>Doctrine Model</strong> and talk about what our <strong>main project</strong> is going to be.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-and-doctrine-from-scratch-day-2-the-basics"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this episode:</p>
<p>- We do a quick fresh install of <strong>CodeIgniter</strong> and <strong>Doctrine</strong>, without going into details like last episode.<br />
- Briefly go over some of the <strong>basic concepts</strong> of CodeIgniter and Doctrine.<br />
- First we will review <strong>Controllers</strong> and <strong>Views</strong> in CodeIgniter.<br />
- Then we will move on to <strong>Models</strong> using Doctrine. This is where things are going to get a little different, compared to other CodeIgniter tutorials out there.<br />
- Finally we will preview a sample <strong>Doctrine Model</strong> and talk about what our <strong>main project</strong> is going to be.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p>Let&#8217;s get started and make sure we have a fresh CodeIgniter+Doctrine install ready for some code.</p>
<h3>Fresh Quick CodeIgniter+Doctrine Install</h3>
<h4>Fresh Install Instructions:</h4>
<p>(if you want to use your files from Day 1, skip to the next section instead)</p>
<ul>
<li>Have your PHP+MySQL <strong>web server</strong> ready. Recommended: <a href="http://www.wampserver.com/en/" ref="nofollow">WAMP</a> (for Mac: <a href="http://www.mamp.info" rel="nofollow">MAMP</a>) </li>
<li><a href="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine_bundle_1_0.zip">Download my CodeIgniter+Doctrine bundle (v1.0)</a>.</li>
<li>Extract and put the <strong>ci_doctrine</strong> folder into your web folder.</li>
<li>Create a database named <strong>ci_doctrine</strong> for our project.</li>
<li>Make sure your database info is correct in: <strong>system/application/config/database.php</strong>.</li>
<li>Make sure <strong>base_url</strong> is correct in: <strong>system/application/config/config.php</strong>.</li>
<li>See if its working: <a href="http://localhost/ci_doctrine/">http://localhost/ci_doctrine/</a>.</li>
</ul>
<p>Done!</p>
<h4>If you already have the files from Day 1:</h4>
<p>(if you used the fresh install from the section above, skip this)</p>
<ul>
<li>Rename or Copy your install folder to: <strong>ci_doctrine</strong>. (I decided to do this so we don&#8217;t keep changing our site url on every tutorial)</li>
<li><strong>Delete</strong>: system/application/models/user.php</li>
<li><strong>Delete</strong>: system/application/controllers/hello.php</li>
<li><strong>Drop table</strong>: user</li>
<li><strong>Edit</strong>: system/application/config/config.php</li>
</ul>
<pre class="brush: php;">
// in system/application/config/config.php
$config['base_url']	= &quot;http://localhost/ci_doctrine/&quot;;
</pre>
<h3>CodeIgniter URL structure</h3>
<p>Url&#8217;s in CodeIgniter can look like these:</p>
<p>This url invokes the <strong>controller class</strong> named &#8220;CONTROLLER_NAME&#8221;, and call it&#8217;s <strong>method</strong> (function) named &#8220;METHOD_NAME&#8221;:</p>
<pre>

http://localhost/ci_doctrine/index.php/CONTROLLER_NAME/METHOD_NAME
</pre>
<p>Same as before, except it calls a method named <strong>index()</strong> by default:</p>
<pre>

http://localhost/ci_doctrine/index.php/CONTROLLER_NAME
</pre>
<p>Same as before. This time, it passes a &#8220;VALUE&#8221; as an <strong>argument</strong> to the controller method:</p>
<pre>

http://localhost/ci_doctrine/index.php/CONTROLLER_NAME/METHOD_NAME/VALUE
</pre>
<p>The value can be a number or a string.<br />
You can keep appending more values in the url for passing additional arguments.</p>
<p><strong>For More Info</strong>: <a href="http://codeigniter.com/user_guide/general/controllers.html#passinguri" rel="nofollow">Passing uri segments</a></p>
<h3>CodeIgniter <del>M</del>VC (<del>Model</del> &#8211; View &#8211; Controller)</h3>
<h4>Models</h4>
<p>We are going to be using <strong>Doctrine Model</strong>&#8216;s, instead of CodeIgniter. I will explain it later in the tutorial.</p>
<p>If you still want to learn about CodeIgniter Models, read: <a href="http://codeigniter.com/user_guide/general/models.html" rel="nofollow">CodeIgniter Models</a></p>
<h4>Views</h4>
<ul>
<li>Views are created under <strong>system/application/views</strong>, and are named like my_view.php</li>
<li>They are the <strong>output templates</strong>. They can contain html, javascript and more.</li>
<li>Views also usually contain <strong>inline PHP</strong> code. (to display messages, run loops etc&#8230;)</li>
<li>Controllers typically <strong>load</strong> views for displaying output.</li>
</ul>
<p><strong>Official docs:</strong> <a href="http://codeigniter.com/user_guide/general/views.html" rel="nofollow">CodeIgniter Views</a></p>
<h4>Controllers</h4>
<p>We already covered this in <a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1</a>. Look for the section called <strong>&#8220;CodeIgniter Crash Course: Controllers&#8221;</strong>.</p>
<h4>Controller and View together</h4>
<p>Here is a sample View (system/application/views/my_view.php):</p>
<pre class="brush: php; html-script: true;">
Some plain text.

&lt;div&gt;
	You can use HTML.
&lt;/div&gt;

&lt;div&gt;
	Display variables passed from a controller: &lt;br /&gt;
	&lt;?php echo $message; ?&gt; &lt;br /&gt;
	&lt;?php echo $another_message; ?&gt;
&lt;/div&gt;

You can even do loops: &lt;br /&gt;
&lt;?php for ($i = 0; $i &lt; 3; $i++) {

	echo &quot;Counter shows: $i &lt;br /&gt;&quot;;

} ?&gt;

Or in alternate syntax: &lt;br /&gt;
&lt;?php for ($i = 0; $i &lt; 3; $i++): ?&gt;

	Counter shows: &lt;?php echo $i; ?&gt; &lt;br /&gt;

&lt;?php endfor; ?&gt;
</pre>
<p>Here is a sample Controller (system/application/controllers/sample_controller.php), that loads a view:</p>
<pre class="brush: php;">
class Sample_controller extends Controller {

	function index() {
		$data = array();
		$data['message'] = &quot;index was called&quot;;
		$data['another_message'] = &quot;blah blah&quot;;

		$this-&gt;load-&gt;view('my_view',$data);
	}

}
</pre>
<p>Both of these url&#8217;s will work:</p>
<pre>

http://localhost/ci_doctrine/index.php/sample_controller/index

http://localhost/ci_doctrine/index.php/sample_controller
</pre>
<p>Browser would display:</p>
<pre>
Some plain text.
You can use HTML.
Display variables passed from a controller:
index was called
blah blah
You can even do loops:
Counter shows: 0
Counter shows: 1
Counter shows: 2
Or in alternate syntax:
Counter shows: 0
Counter shows: 1
Counter shows: 2
</pre>
<p><strong>Note:</strong></p>
<ul>
<li>View contains a combination of <strong>raw output</strong> and <strong>simple inline PHP</strong>.</li>
<li>index() is the <strong>default</strong> Controller function, so we don&#8217;t have to put it in the url. </li>
<li>$this->load->view(&#8216;my_view&#8217;,$data) <strong>loads</strong> the view and outputs it to the browser.</li>
<li>First argument &#8216;my_view&#8217; is the <strong>name of the view file</strong>, without the .php part.</li>
<li>Second argument $data is an array, which <strong>passes variables</strong> to the view.</li>
<li><strong>Example</strong>: $data['message'] becomes <strong>$message</strong>, and $data['another_message'] becomes <strong>$another_message</strong>, in our view.</li>
</ul>
<p>(If you created the files above, to test the code, you can delete them now. We&#8217;re not going to use them again in our project.)</p>
<h3>Doctrine Models</h3>
<p>Models are classes that represent data (typically from your database). </p>
<p>For example, you might have a <strong>user</strong> table. So we can build a Model Class named &#8220;User&#8221; to represent the records in that table.</p>
<p>Our Model class should be able to peform <strong>CRUD</strong> (Create, Read, Update and Delete) operations. Luckily, Doctrine will be a great help in accomplishing this with minimal and clean code.</p>
<h4>Differences in Usage (compared to CodeIgniter Models)</h4>
<ul>
<li>They extend the <strong>Doctrine_Record</strong> class (instead of the &#8220;Model&#8221; class).</li>
<li>They can be loaded like this: <strong>$u = new User();</strong> (instead of this: <strong>$u = $this->load->model(&#8216;user&#8217;);</strong>) <br /> thanks to the Doctrine <strong>autoload</strong> we registered in our plugin.</li>
<li>It is not PHP4 compatible.</li>
</ul>
<p>That is all you need to know for now. It should be an easy transition for those of you already working with CodeIgniter.</p>
<h4>What does a Doctrine Model look like?</h4>
<p>Here is a little <strong>PREVIEW</strong> of the kind of Model&#8217;s we are going to be building. We&#8217;ll get into more details in the next tutorials.</p>
<pre class="brush: php;">
&lt;?php
class User extends Doctrine_Record
{
	// define table columns in this function
	public function setTableDefinition() {

		$this-&gt;hasColumn('username', 'string', 255);
		$this-&gt;hasColumn('password', 'string', 255);
		$this-&gt;hasColumn('email', 'string', 255, array(
			'email' =&gt; true // It can validate e-mail input
		));

		// supports many column types, including enum
		$this-&gt;hasColumn('status', 'enum', null,
			array('values' =&gt; array('unverified', 'verified', 'disabled'))
		);

		$this-&gt;hasColumn('referer_id', 'integer', 4);
	}

	// setup some options
	public function setUp() {

		// creates a relationship with a model named Post
		$this-&gt;hasMany('Post as Posts', array(
			'local' =&gt; 'id',
			'foreign' =&gt; 'post_id'
		));

		// can even have a relationship with itself
		$this-&gt;hasOne('User as Referer', array(
			'local' =&gt; 'referer_id',
			'foreign' =&gt; 'id'
		));

		// causes 'created_at' and 'updated_at' fields to be updated automatically
		$this-&gt;actAs('Timestampable');

		// password field gets a mutator assigned, for automatic encryption
		$this-&gt;hasMutator('password', 'md5Password');

	}

	// a mutator function
	public function md5Password($value) {
		$this-&gt;_set('password', md5($value));
	}

}
</pre>
<p>Once we create Doctrine Model&#8217;s like this, we can do all kinds of database operations. Doctrine can even <strong>create the table</strong> based on the model information alone.</p>
<p>Also keep in mind that there are other ways of creating Doctrine Models, such as using schema files. But we will not get into that until later.</p>
<h3>Stay Tuned</h3>
<p>In the next episode, we will start building a project, which will be a <strong>Message Board</strong> and possibly more&#8230; This is a great candidate for a tutorial project with Doctrine because of all the different relationships involved between models such as: users, posts, threads, forums, groups, attachments etc&#8230;</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/fKT523aDFsc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics/feed</wfw:commentRss>
		<slash:comments>39</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics</feedburner:origLink></item>
		<item>
		<title>PHP Method Chaining, plus Magic Setters (similar to jQuery)</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/W4emVPzNN_M/php-method-chaining-plus-magic-setters</link>
		<comments>http://www.phpandstuff.com/articles/php-method-chaining-plus-magic-setters#comments</comments>
		<pubDate>Fri, 30 Oct 2009 15:30:22 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[magic setters]]></category>
		<category><![CDATA[method chaining]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=262</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/php-method-chaining-1.png" alt="php-method-chaining-1" title="php-method-chaining-1" width="128" height="128" class="alignleft size-full wp-image-271" />

<em><strong>Quick Disclaimer</strong>: Even if you know about PHP5 Method Chaining, don't skip this article, because we will explore more than just that.</em>

If you're familiar with jQuery, you might know how it let's you write short and clean code with the help of <strong>method chaining</strong>. 

Not only will I show you how to accomplish this in PHP5, but I will also combine this feature with <strong>magic setter methods</strong> with the help of <strong>method overloading</strong> to make it even nicer.

It's OK if you don't know any of these terms. You should still be able to become familiarized with them by reading this article.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fphp-method-chaining-plus-magic-setters"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/php-method-chaining-1.png" alt="php-method-chaining-1" title="php-method-chaining-1" width="128" height="128" class="alignleft size-full wp-image-271" /></p>
<p><em><strong>Quick Disclaimer</strong>: Even if you know about PHP5 Method Chaining, don&#8217;t skip this article, because we will explore more than just that.</em></p>
<p>If you&#8217;re familiar with jQuery, you might know how it let&#8217;s you write short and clean code with the help of <strong>method chaining</strong>. </p>
<p>Not only will I show you how to accomplish this in PHP5, but I will also combine this feature with <strong>magic setter methods</strong> with the help of <strong>method overloading</strong> to make it even nicer.</p>
<p>It&#8217;s OK if you don&#8217;t know any of these terms. You should still be able to become familiarized with them by reading this article.</p>
<div class="clear"></div>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/10/method_chaining_plus_magic_setters.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Defining Our Goal</h3>
<p><strong>Can you write an Email class that can do this?</strong></p>
<pre class="brush: php;">
&lt;?php
require_once ('Email.php');

$my_email = new Email();
$my_email
	-&gt;set_from('test@email.com')
	-&gt;add_to('programming@gmail.com')
	-&gt;set_subject('Methods Chained')
	-&gt;set_body('Some long message')
	-&gt;send();
</pre>
<p><strong>instead of this:</strong></p>
<pre class="brush: php;">
&lt;?php
require_once ('Email.php');

$my_email = new Email();
$my_email-&gt;from = 'test@email.com';
$my_email-&gt;to []= 'programming@gmail.com';
$my_email-&gt;subject = 'Methods Chained';
$my_email-&gt;body = 'Some long message';
$my_email-&gt;send();
</pre>
<p>Your answer might be &#8220;Yes&#8221; if you&#8217;re already familiar with PHP Method Chaining.</p>
<p>But can you do it <strong>WITHOUT</strong> actually implementing the <strong>setter methods</strong> named &#8220;set_from()&#8221;, &#8220;add_to()&#8221; etc&#8230; in your class?</p>
<h3>PHP Method Chaining in a Nutshell</h3>
<p>For those of you not familiar with this term, here is what you need to know:</p>
<ul>
<li>Method Chaining allows you to call multiple methods in a single line.</li>
</ul>
<pre class="brush: php;">
$my_object-&gt;foo()-&gt;bar()-&gt;taz()-&gt;etc();
</pre>
<ul>
<li>All you need to do is <strong>return $this;</strong> at the end of your class methods.</li>
</ul>
<pre class="brush: php;">
class My_Class {

	public function foo() {
		// ... do something
		return $this;
	}

	public function bar() {
		// ... do something else
		return $this;
	}

}
</pre>
<p>Now your class methods can be called in a <strong>chain</strong>, resulting in a shorter (and hopefully cleaner) code.</p>
<h3>Creating Our Magic Email Class</h3>
<p>Before I explain more, I am just going to paste the entire class code here first:</p>
<h4>Email.php</h4>
<pre class="brush: php;">
&lt;?php

class Email {

	public $from;
	public $to = array();
	public $subject;
	public $body;

	public function send() {

		echo &quot;(not) Sending E-mail &lt;br/&gt;\n&quot;.
			&quot;From: {$this-&gt;from} &lt;br/&gt;\n&quot;.
			&quot;To: &quot;.implode(',',$this-&gt;to).&quot;&lt;br/&gt;\n&quot;.
			&quot;Subject: {$this-&gt;subject} &lt;br/&gt;\n&quot;.
			&quot;Body: {$this-&gt;body} &lt;br/&gt;\n&quot;;

	}

	public function __call($name, $arguments) {

		if (substr($name,0,4) == 'set_') {
			$property = substr($name,4);
			$this-&gt;$property = $arguments[0];

		} else if (substr($name,0,4) == 'add_') {
			$property = substr($name,4);
			array_push($this-&gt;$property, $arguments[0]);
		}

		return $this;
	}
}
</pre>
<p><strong>Please Note:</strong> I did NOT create any methods named <strong>set_from()</strong>, <strong>set_subject()</strong> or <strong>add_to()</strong> etc&#8230;, yet we&#8217;ll be able to call these setter methods with the help of some &#8220;magic&#8221;. Not to metion, we&#8217;ll be able to call them in a chain.</p>
<h4>Now, let&#8217;s analyze the Code</h4>
<p>The first part is simple enough. We&#8217;re just creating a new class:</p>
<pre class="brush: php;">
class Email {

	public $from;
	public $to = array();
	public $subject;
	public $body;
// ...
</pre>
<p>Note that the <strong>$to</strong> property is going to be an array (we can e-mail multiple recipients). We&#8217;ll be adding values to it using &#8220;add_to()&#8221; method call.</p>
<p>Then we write a simple send() method to send our e-mail. (In this case, it&#8217;s just a fake one, for testing purposes)</p>
<pre class="brush: php;">
// ...
	public function send() {

		// not actually sending e-mail
		// we're just testing our stuff

		echo &quot;(not) Sending E-mail &lt;br/&gt;\n&quot;.
			&quot;From: {$this-&gt;from} &lt;br/&gt;\n&quot;.
			&quot;To: &quot;.implode(',',$this-&gt;to).&quot;&lt;br/&gt;\n&quot;.
			&quot;Subject: {$this-&gt;subject} &lt;br/&gt;\n&quot;.
			&quot;Body: {$this-&gt;body} &lt;br/&gt;\n&quot;;

	}
</pre>
<p>Then we create the <strong>magic method</strong> named <strong>__call()</strong>. This method gets invoked when a non-existing function (e.g. set_from() or add_to()) has been called.</p>
<p>First argument <strong>$name</strong> is the name of the method called.<br />
Second argument <strong>$arguments</strong> are the arguments passed to the method.</p>
<p><strong>For more info:</strong>  <a href="http://www.php.net/manual/en/language.oop5.overloading.php#language.oop5.overloading.methods" rel="nofollow">PHP Overloading Methods</a></p>
<pre class="brush: php;">
// ...
	// this magic method gets called
	// when a non-existing method is called
	public function __call($name, $arguments) {

		// setting a property
		if (substr($name,0,4) == 'set_') {

			// get the property name we want to set
			$property = substr($name,4);
			// assign the value that was passed to this method
			// to the class property
			$this-&gt;$property = $arguments[0];

		// adding to an array property
		} else if (substr($name,0,4) == 'add_') {

			// get the property name we want to add to
			$property = substr($name,4);
			// add the value
			array_push($this-&gt;$property, $arguments[0]);

		}

		// for method chaining
		return $this;
	}
// ...
</pre>
<p>In the __call() function above, we do this:</p>
<ul>
<li>If the method call was named <strong>set_*</strong>, we set the corresponding property value.</li>
<li>If the method call was named <strong>add_*</strong>, we add to the corresponding property an array value.</li>
<li>Finally, we return the class instance itself, which allows for method chaining.</li>
</ul>
<h4>Test The Code</h4>
<p>If you test the following code:</p>
<pre class="brush: php;">
&lt;?php
require_once ('Email.php');

$my_email = new Email();
$my_email
	-&gt;set_from('test@email.com')
	-&gt;add_to('programming@gmail.com')
	-&gt;set_subject('Methods Chained')
	-&gt;set_body('Some long message')
	-&gt;send();
</pre>
<p>You should see this output:</p>
<pre>
(not) Sending E-mail
From: test@email.com
To: programming@gmail.com
Subject: Methods Chained
Body: Some long message
</pre>
<h3>Thank you for reading</h3>
<p>I hope you enjoyed this quick tutorial. If there are any other PHP concepts you would like to learn about, just leave a comment.</p>
<p>Thank you!</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/W4emVPzNN_M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/php-method-chaining-plus-magic-setters/feed</wfw:commentRss>
		<slash:comments>21</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/php-method-chaining-plus-magic-setters</feedburner:origLink></item>
		<item>
		<title>CodeIgniter and Doctrine from scratchDay 1 – Install and Setup</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/4S7R2IKTSDI/codeigniter-doctrine-from-scratch-day-1-install-and-setup</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup#comments</comments>
		<pubDate>Wed, 28 Oct 2009 07:17:02 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=161</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />Being inspired by the wonderful series of articles/screencasts on the nettuts website called <a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-1/" rel="nofollow">CodeIgniter From Scratch</a> I decided to write my own series on using <strong>CodeIgniter and Doctrine</strong> together to build a functional website in a series of tutorials.

In this first part of series, I will show you how to create a basic CodeIgniter install and add Doctrine as a <strong>plug-in</strong>.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-from-scratch-day-1-install-and-setup"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />Being inspired by the wonderful series of articles/screencasts on the nettuts website called <a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-day-1/" rel="nofollow">CodeIgniter From Scratch</a> I decided to write my own series on using <strong>CodeIgniter and Doctrine</strong> together to build a functional website in a series of tutorials.</p>
<p>In this first part of series, I will show you how to create a basic CodeIgniter install and add Doctrine as a <strong>plug-in</strong>.</p>
<div class="clear"></div>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<p><a href="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1.zip"><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/download_code.png" alt="download_code" title="download_code" width="240" height="80" class="aligncenter size-full wp-image-249" /></a></p>
<h3>Why add Doctrine to CodeIgniter?</h3>
<p>Before we get started, first let me explain the reason I am doing this. <a href="http://www.doctrine-project.org/" ref="nofollow">Doctrine</a> is an <em>Object Relational Mapper</em> for PHP. It&#8217;s OK if you don&#8217;t know this term. It basically means that you can map your <strong>database tables</strong> to <strong>classes</strong> in your web application. And instances of these classes (i.e. <strong>objects</strong>) represent <strong>records</strong> in the database. </p>
<p>This makes it very easy to <strong>create, read, update and delete</strong> records from the database, while handling them almost like regular objects, so you don&#8217;t even have to write any queries. It will also handle <strong>relationships</strong> between your tables. There are several other benefits that I will not get into until later in these tutorials. See the <a href="http://www.doctrine-project.org/documentation/manual/1_1/en/introduction" rel="nofollow">Doctrine Introduction</a>, if you would like more info right now.</p>
<p>Here is an illustration I put together, that might give you a visual picture.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_41.png" alt="CodeIgniter Doctrine" title="CodeIgniter Doctrine" width="600" height="900" class="aligncenter size-full wp-image-188" /></p>
<h3>First Step: Setup your development environment</h3>
<p>If you already have a <strong>web server with PHP and MySQL</strong> setup, you can skip some of this.</p>
<ul>
<li>Download and install <a href="http://www.wampserver.com/en/" ref="nofollow">WAMP</a> (for Mac: <a href="http://www.mamp.info" rel="nofollow">MAMP</a>)<br />
Warning <strong>Skype</strong> Users: You must shutdown Skype first before you start up WAMP, due to a port conflict. After WAMP starts up, you can open Skype again.</li>
<li>Visit <a href="http://localhost/" rel="nofollow">http://localhost/</a> in your browser to make sure it&#8217;s working</li>
<li>Open the &#8220;www&#8221; folder under the WAMP installation.</li>
<li>Create a folder named &#8220;ci_doctrine_day1&#8243;. We will put our files here.</li>
</ul>
<h3>Install CodeIgniter</h3>
<ul>
<li><a href="http://codeigniter.com/downloads/">Download CodeIgniter</a></li>
<li>Extract and copy the contents into your new &#8220;ci_doctrine_day1&#8243; folder.</li>
<li>You may delete the &#8220;user_guide&#8221; folder.</li>
</ul>
<p>Your new folders should look like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_1.png" alt="ci_doctrine_day1_1" title="ci_doctrine_day1_1" width="350" height="463" class="aligncenter size-full wp-image-177" /></p>
<ul>
<li>Go to <a href="http://localhost/ci_doctrine_day1" rel="nofollow">http://localhost/ci_doctrine_day1</a></li>
</ul>
<p>You should see this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_3.png" alt="ci_doctrine_day1_3" title="ci_doctrine_day1_3" width="500" height="276" class="aligncenter size-full wp-image-184" /></p>
<h3>CodeIgniter Crash Course: Controllers</h3>
<p><strong>Controllers</strong> are called by CodeIgniter on every page load.<br />
They are located under: </p>
<pre>system/application/controllers/</pre>
<p>The <strong>url</strong> structure looks like this: </p>
<pre>http://localhost/ci_doctrine_day1/index.php/CONTROLLER_NAME/FUNCTION_NAME</pre>
<p>For example if you open this url:</p>
<pre>http://localhost/ci_doctrine_day1/index.php/hello/world</pre>
<p>CodeIgniter will look for a controller class named &#8220;Hello&#8221; and call it&#8217;s <strong>method</strong> named &#8220;world()&#8221;.</p>
<p>So let&#8217;s create our first controller.</p>
<h4>Our First Controller</h4>
<ul>
<li>Create this file: system/application/controllers/hello.php</li>
</ul>
<pre class="brush: php;">
&lt;?php
// system/application/controllers/hello.php

class Hello extends Controller {

	function world() {
		echo &quot;Hello CodeIgniter!&quot;;
	}

}
</pre>
<ul>
<li>Go to: <a href="http://localhost/ci_doctrine_day1/index.php/hello/world" rel="nofollow">http://localhost/ci_doctrine_day1/index.php/hello/world</a></li>
</ul>
<p>You should see:</p>
<pre>Hello CodeIgniter!</pre>
<p><strong>Please Note:</strong></p>
<ul>
<li>The class must <strong>extend</strong> Controller.</li>
<li>The class name must be <strong>capitalized</strong>.</li>
<li>The file name must be <strong>lowercase</strong>.</li>
</ul>
<p><strong>Recommended Reading:</strong></p>
<ul>
<li><a href="http://codeigniter.com/user_guide/general/controllers.html" rel="nofollow">http://codeigniter.com/user_guide/general/controllers.html</a></li>
</ul>
<h3>Install Doctrine</h3>
<p>CodeIgniter allows us to add <strong>plug-ins</strong>. That&#8217;s how we will be installing it.</p>
<ul>
<li>Create this folder: system/application/plugins</li>
<li>Create this folder: system/application/plugins/doctrine</li>
<li><a href="http://www.doctrine-project.org/download">Download Doctrine</a></li>
<li>Extract the files. Find the folder named &#8220;lib&#8221; and copy it to <strong>system/application/plugins/doctrine</strong>.</li>
</ul>
<p>Now your folders should look like this:</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_5.png" alt="ci_doctrine_day1_5" title="ci_doctrine_day1_5" width="263" height="290" class="aligncenter size-full wp-image-209" /></p>
<ul>
<li>Create the plug-in file: <strong>system/application/plugins/doctrine_pi.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
// system/application/plugins/doctrine_pi.php

// load Doctrine library
require_once APPPATH.'/plugins/doctrine/lib/Doctrine.php';

// load database configuration from CodeIgniter
require_once APPPATH.'/config/database.php';

// this will allow Doctrine to load Model classes automatically
spl_autoload_register(array('Doctrine', 'autoload'));

// we load our database connections into Doctrine_Manager
// this loop allows us to use multiple connections later on
foreach ($db as $connection_name =&gt; $db_values) {

	// first we must convert to dsn format
	$dsn = $db[$connection_name]['dbdriver'] .
		'://' . $db[$connection_name]['username'] .
		':' . $db[$connection_name]['password'].
		'@' . $db[$connection_name]['hostname'] .
		'/' . $db[$connection_name]['database'];

	Doctrine_Manager::connection($dsn,$connection_name);
}

// CodeIgniter's Model class needs to be loaded
require_once BASEPATH.'/libraries/Model.php';

// telling Doctrine where our models are located
Doctrine::loadModels(APPPATH.'/models');

// (OPTIONAL) CONFIGURATION BELOW

// this will allow us to use &quot;mutators&quot;
Doctrine_Manager::getInstance()-&gt;setAttribute(
	Doctrine::ATTR_AUTO_ACCESSOR_OVERRIDE, true);

// this sets all table columns to notnull and unsigned (for ints) by default
Doctrine_Manager::getInstance()-&gt;setAttribute(
	Doctrine::ATTR_DEFAULT_COLUMN_OPTIONS,
	array('notnull' =&gt; true, 'unsigned' =&gt; true));

// set the default primary key to be named 'id', integer, 4 bytes
Doctrine_Manager::getInstance()-&gt;setAttribute(
	Doctrine::ATTR_DEFAULT_IDENTIFIER_OPTIONS,
	array('name' =&gt; 'id', 'type' =&gt; 'integer', 'length' =&gt; 4));
</pre>
<p>Read the <strong>comments</strong> in the code for explanations. However, don&#8217;t worry if you don&#8217;t understand all of it for now.</p>
<h3>Database Setup and Configuration</h3>
<ul>
<li>Open <strong>phpMyAdmin</strong>: <a href="http://localhost/phpmyadmin/" rel="nofollow">http://localhost/phpmyadmin/</a></li>
<li>Create a <strong>database</strong> named &#8220;ci_doctrine&#8221;</li>
</ul>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_6.png" alt="ci_doctrine_day1_6" title="ci_doctrine_day1_6" width="553" height="400" class="aligncenter size-full wp-image-216" /></p>
<ul>
<li>Edit file: system/application/config/database.php</li>
<li>Find the lines below and input the values.</li>
</ul>
<pre class="brush: php;">
// in system/application/config/database.php
// ... 

$db['default']['hostname'] = &quot;localhost&quot;;
$db['default']['username'] = &quot;root&quot;;
$db['default']['password'] = &quot;&quot;;
$db['default']['database'] = &quot;ci_doctrine&quot;;

// ...
</pre>
<p>We just edited the <strong>database configuration file</strong> of CodeIgniter.</p>
<h3>More Configuration</h3>
<p>Almost done.</p>
<h4>config.php</h4>
<ul>
<li>Edit file: <strong>system/application/config/config.php</strong></li>
</ul>
<pre class="brush: php;">
// in system/application/config/config.php
// ...

$config['base_url']	= &quot;http://localhost/ci_doctrine_day1/&quot;;

// ...
</pre>
<p>Now CodeIgniter knows the <strong>url of our site</strong>.</p>
<h4>autoload.php</h4>
<ul>
<li>Edit file: <strong>system/application/config/autoload.php</strong></li>
</ul>
<pre class="brush: php;">
// in system/application/config/autoload.php
// ...

$autoload['plugin'] = array('doctrine');

// ...
</pre>
<p>This makes sure the Doctrine plug-in is always loaded.</p>
<h4>Finished!</h4>
<p>Now we&#8217;re ready to rock. Let&#8217;s start testing our setup.</p>
<h3>Our First Doctrine Model</h3>
<h4>Create a user Table</h4>
<ul>
<li>Open phpMyAdmin: <a href="http://localhost/phpmyadmin/" rel="nofollow">http://localhost/phpmyadmin/</a></li>
<li>Go to database &#8220;ci_doctrine&#8221;</li>
<li>Create a <strong>table</strong> named &#8220;user&#8221; with columns:<br />
id => int, primary key, auto_increment,<br />
username => varchar(255), unique,<br />
password => varchar(255),<br />
first_name => varchar(255),<br />
last_name => varchar(255)</li>
</ul>
<p>You may use this <strong>query</strong>:</p>
<pre>
CREATE TABLE `ci_doctrine`.`user` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY ,
`username` VARCHAR( 255 ) NOT NULL ,
`password` VARCHAR( 255 ) NOT NULL ,
`first_name` VARCHAR( 255 ) NOT NULL ,
`last_name` VARCHAR( 255 ) NOT NULL ,
UNIQUE (
`username`
)
)
</pre>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_7.png" alt="ci_doctrine_day1_7" title="ci_doctrine_day1_7" width="552" height="481" class="aligncenter size-full wp-image-228" /></p>
<h4>Create the Model</h4>
<ul>
<li>Create file: <strong>system/application/models/user.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
// system/application/models/user.php
class User extends Doctrine_Record {

	public function setTableDefinition() {
		$this-&gt;hasColumn('username', 'string', 255);
		$this-&gt;hasColumn('password', 'string', 255);
		$this-&gt;hasColumn('first_name', 'string', 255);
		$this-&gt;hasColumn('last_name', 'string', 255);
	}

}
</pre>
<p><strong>Note:</strong></p>
<ul>
<li>We extend <strong>Doctrine_Record</strong>, instead of <strong>Model</strong> (which you normally would with CodeIgniter models).</li>
<li>Inside the function setTableDefinition() we need to define the table structure.</li>
<li>By default, Doctrine will look for a table with same name as the class. In this case: &#8220;user&#8221;. (this can be changed)</li>
<li>In our doctrine_pi.php file above in this tutorial, we specified for a default primary key named &#8220;id&#8221;. Therefore we don&#8217;t need to put it again in our User class.</li>
</ul>
<h4>Testing the Model: Add Some Users</h4>
<ul>
<li>Edit our controller we created earlier: <strong>system/application/controllers/hello.php</strong></li>
</ul>
<pre class="brush: php;">
&lt;?php
// system/application/controllers/hello.php

class Hello extends Controller {

	function world() {
		echo &quot;Hello CodeIgniter!&quot;;
	}

	function user_test() {

		$u = new User;
		$u-&gt;username = 'johndoe';
		$u-&gt;password = 'secret';
		$u-&gt;first_name = 'John';
		$u-&gt;last_name = 'Doe';
		$u-&gt;save();

		$u2 = new User;
		$u2-&gt;username = 'phprocks';
		$u2-&gt;password = 'mypass';
		$u2-&gt;first_name = 'Codeigniter';
		$u2-&gt;last_name = 'Doctrine';
		$u2-&gt;save();

		echo &quot;added 2 users&quot;;
	}

}
</pre>
<p>We just generated 2 objects, and populated them with some data. Simply calling <strong>save()</strong> should save them into our database.</p>
<p><strong>Note:</strong></p>
<ul>
<li>We are able to access the fields as <strong>parameters</strong> (e.g. $u->username), even though we did not create these as class parameters. Isn&#8217;t Doctrine nice?</li>
<li>If you are familiar with CodeIgniter, you might remember that you need to call $this->load->model() function to load models. However since we registered the <strong>autoload</strong> function of Doctrine, just saying &#8220;new User;&#8221; is enough.</li>
<li>We didn&#8217;t create the &#8220;save()&#8221; function, because it comes from the Doctrine_Record class we extended. It saves the objects to the database. There are many other functions and goodies that come with Doctrine classes, we will see later in the tutorials.</li>
</ul>
<ul>
<li>Open: <a href="http://localhost/ci_doctrine_day1/index.php/hello/user_test" ref="nofollow">http://localhost/ci_doctrine_day1/index.php/hello/user_test</a></li>
</ul>
<p>You should see output:</p>
<pre>
added 2 users
</pre>
<ul>
<li>Now go back to phpMyAdmin: <a href="http://localhost/phpmyadmin/" rel="nofollow">http://localhost/phpmyadmin/</a></li>
<li>Browse the table &#8216;user&#8217;</li>
</ul>
<p><strong>Voila!</strong> Now you should be able see the 2 new records that just got created.</p>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/ci_doctrine_day1_8.png" alt="ci_doctrine_day1_8" title="ci_doctrine_day1_8" width="530" height="405" class="aligncenter size-full wp-image-240" /></p>
<h3>Stay Tuned</h3>
<p>We just saw how to install and setup CodeIgniter with Doctrine. It took some work, but now we have a powerful MVC framework and ORM combination.</p>
<p>In the next tutorials, I will show you more practical examples and eventually build a functional website. You will see how easy it is to create models with Doctrine and save time from having to write repetitive CRUD (Create, read, update and delete) functions in all of your models. </p>
<p>Doctrine will also help us handle the relationships between our classes, and let us avoid writing complex logic code and queries.</p>
<p>See you next time!</p>
<p>
		<div class="article-series" style="background-color: #FFFFFF; padding: 10px; -moz-border-radius: 4px; border:1px solid #B7A99A; margin-bottom: 20px;">
			<h4 style="margin-top: 0px">"CodeIgniter and Doctrine from Scratch" Series:</h4>
			<ul>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup">Day 1: Install and Setup</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-and-doctrine-from-scratch-day-2-the-basics">Day 2: The Basics</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-3-user-signup-form">Day 3: User Signup Form</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-4-user-login">Day 4: User Login</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-5-database-crud">Day 5: Database CRUD</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-day-6-models-relationships">Day 6: Models with Relationships</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-7-fixtures-forum-list">Day 7: Fixtures & Forum List</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql">Day 8: Hooks, Profiling & DQL</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators">Day 9: Templates & Data Hydrators</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination">Day 10: Pagination</a></li>
				<li><a href="http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks">Day 11: Record Hooks</a></li>
				<li>Day 12: ...coming soon</li>
			</ul>
		</div>
	</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/4S7R2IKTSDI" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup/feed</wfw:commentRss>
		<slash:comments>267</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-from-scratch-day-1-install-and-setup</feedburner:origLink></item>
		<item>
		<title>CodeIgniter with Doctrine sample code [5 min. screencast]</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/zqp9xsgkyRw/codeigniter-with-doctrine-sample-code-screencast</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-with-doctrine-sample-code-screencast#comments</comments>
		<pubDate>Tue, 13 Oct 2009 21:54:49 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>
		<category><![CDATA[CodeIgniter]]></category>
		<category><![CDATA[Doctrine]]></category>
		<category><![CDATA[ORM]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=128</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this video, I show some sample code I wrote in a fresh install of CodeIgniter and Doctrine. It's very easy to use once you get familiar with it. This will allow you to avoid writing repetetive CRUD functionality in all of your CodeIgniter models.
Later I will post an article showing how to install Doctrine into your CodeIgniter setup.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-with-doctrine-sample-code-screencast"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/10/codeigniter_doctrine.png" alt="codeigniter_doctrine" title="codeigniter_doctrine" width="128" height="128" class="alignleft size-full wp-image-140" />In this video, I show some sample code I wrote in a fresh install of CodeIgniter and Doctrine. It&#8217;s very easy to use once you get familiar with it. This will allow you to avoid writing repetetive CRUD functionality in all of your CodeIgniter models.<br />
Later I will post an article showing how to install Doctrine into your CodeIgniter setup.</p>
<div class="clear"></div>
<p>In this video:</p>
<ul>
<li>First I create 2 models.</li>
<li>Then I create the database tables based on these models.</li>
<li>Finally I insert some data into the tables by using very simple code that doesn&#8217;t involve any database queries.</li>
</ul>
<p><object classid='clsid:d27cdb6e-ae6d-11cf-96b8-444553540000' codebase='http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,115,0' width='560' height='345'><param name='movie' value='http://screenr.com/Content/assets/screenr_0817090731.swf' /><param name='flashvars' value='i=15726' /><param name='allowFullScreen' value='true' /><embed src='http://screenr.com/Content/assets/screenr_0817090731.swf' flashvars='i=15726' allowFullScreen='true' width='560' height='345' pluginspage='http://www.macromedia.com/go/getflashplayer'></embed></object></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/zqp9xsgkyRw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-with-doctrine-sample-code-screencast/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-with-doctrine-sample-code-screencast</feedburner:origLink></item>
		<item>
		<title>GeoIP country lookup with PHP</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/rxx82em1CGc/geoip-country-lookup-with-php</link>
		<comments>http://www.phpandstuff.com/articles/geoip-country-lookup-with-php#comments</comments>
		<pubDate>Tue, 08 Sep 2009 23:22:32 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[GeoIP]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=3</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2008/09/geoip_icon.png" alt="geoip_icon" title="geoip_icon" width="128" height="128" class="alignleft size-full wp-image-113" />How to get the surfers country using PHP? Most coders need to tackle this problem sooner or later. There are several options out there. There is even a package called <a href="http://us3.php.net/manual/en/book.geoip.php">GeoIP Location</a>. However, since this does not come with most default installations, it may not be your best choice.

A company called <a href="http://www.maxmind.com/">Maxmind</a> specializes in professional <strong>GeoIP</strong> solutions. However, when you dig through their website, you can find that they also provide some <em>free databases and free code</em>. I will show you how to use this free stuff in a portable way to easily and quickly add an <strong>Ip to Country</strong> lookup feature to your PHP script in 2 easy steps.]]></description>
			<content:encoded><![CDATA[<div class="tweetmeme_button" style="float: right; margin-left: 10px;">
			<a href="http://api.tweetmeme.com/share?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fgeoip-country-lookup-with-php"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly&amp;b=2" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2008/09/geoip_icon.png" alt="geoip_icon" title="geoip_icon" width="128" height="128" class="alignleft size-full wp-image-113" />How to get the surfers country using PHP? Most coders need to tackle this problem sooner or later. There are several options out there. There is even a package called <a href="http://us3.php.net/manual/en/book.geoip.php">GeoIP Location</a>. However, since this does not come with most default installations, it may not be your best choice.</p>
<p>A company called <a href="http://www.maxmind.com/">Maxmind</a> specializes in professional <strong>GeoIP</strong> solutions. However, when you dig through their website, you can find that they also provide some <em>free databases and free code</em>. I will show you how to use this free stuff in a portable way to easily and quickly add an <strong>Ip to Country</strong> lookup feature to your PHP script in 2 easy steps.<br />
<br style="float:clear"/></p>
<h3>Step 1. Download database and PHP file</h3>
<ul>
<li>Download <a href="http://geolite.maxmind.com/download/geoip/database/GeoLiteCountry/GeoIP.dat.gz">GeoLite Country (binary format)</a>, and extract the file GeoIP.dat.</li>
<li>Download <a href="http://www.maxmind.com/download/geoip/api/php/geoip.inc">geoip.inc</a>.</li>
<li>Upload them to your server</li>
</ul>
<h3>Step 2. The Code</h3>
<p>First, include the library and open the geoip database:</p>
<pre class="brush: php;">
// include the php script
include(&quot;geoip.inc&quot;);

// open the geoip database
$gi = geoip_open(&quot;GeoIP.dat&quot;,GEOIP_STANDARD);
</pre>
<p>Getting the country code:</p>
<pre class="brush: php;">
// to get country code
$country_code = geoip_country_code_by_addr($gi, $_SERVER['REMOTE_ADDR']);
echo &quot;Your country code is: $country_code \n&quot;;
</pre>
<p>Getting the country name:</p>
<pre class="brush: php;">
// to get country name
$country_name = geoip_country_name_by_addr($gi, $_SERVER['REMOTE_ADDR']);
echo &quot;Your country name is: $country_name \n&quot;;
</pre>
<p>And finally, close the geoip database:</p>
<pre class="brush: php;">
// close the database
geoip_close($gi);
</pre>
<p>This solution uses a very fast and compact binary file as the database, and it does not add any to load to your MySQL server. You can do thousands of lookups per second on very average hardware with this code.</p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/rxx82em1CGc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/geoip-country-lookup-with-php/feed</wfw:commentRss>
		<slash:comments>26</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/geoip-country-lookup-with-php</feedburner:origLink></item>
	</channel>
</rss><!-- Dynamic page generated in 2.335 seconds. --><!-- Cached page generated by WP-Super-Cache on 2012-05-01 11:42:57 -->

