<?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, 06 May 2010 06:02:33 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.8.6</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<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>9 Useful PHP Functions and Features You Need to Know</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/JvMcTa-Zz0M/9-useful-php-functions-and-features-you-need-to-know</link>
		<comments>http://www.phpandstuff.com/articles/9-useful-php-functions-and-features-you-need-to-know#comments</comments>
		<pubDate>Thu, 06 May 2010 06:02:33 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=898</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/05/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-899" />

<em>Even after using PHP for years, we stumble upon functions and features that we did not know about. Some of these can be very useful, yet underused. Not all of us have read the manual and the function reference from cover to cover!</em>

<a href="http://net.tutsplus.com/tutorials/php/9-useful-php-functions-and-features-you-need-to-know/" rel="nofollow">Read the full article</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%2F9-useful-php-functions-and-features-you-need-to-know"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2F9-useful-php-functions-and-features-you-need-to-know&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/05/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-899" /></p>
<p><em>Even after using PHP for years, we stumble upon functions and features that we did not know about. Some of these can be very useful, yet underused. Not all of us have read the manual and the function reference from cover to cover!</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/9-useful-php-functions-and-features-you-need-to-know/" rel="nofollow">Read the full article</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/JvMcTa-Zz0M" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/9-useful-php-functions-and-features-you-need-to-know/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/9-useful-php-functions-and-features-you-need-to-know</feedburner:origLink></item>
		<item>
		<title>Advanced Regular Expression Tips and Techniques</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/PDCe0nUlGPw/advanced-regular-expression-tips-and-techniques</link>
		<comments>http://www.phpandstuff.com/articles/advanced-regular-expression-tips-and-techniques#comments</comments>
		<pubDate>Thu, 06 May 2010 06:01:11 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=895</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/05/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-894" />

<em>Regular Expressions are the Swiss Army knife for searching through information for certain patterns. They have a wide arsenal of tools, some of which often go undiscovered or underutilized. Today I will show you some advanced tips for working with regular expressions.</em>

<a href="http://net.tutsplus.com/tutorials/php/advanced-regular-expression-tips-and-techniques/" rel="nofollow">Read the full article</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%2Fadvanced-regular-expression-tips-and-techniques"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fadvanced-regular-expression-tips-and-techniques&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/05/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-894" /></p>
<p><em>Regular Expressions are the Swiss Army knife for searching through information for certain patterns. They have a wide arsenal of tools, some of which often go undiscovered or underutilized. Today I will show you some advanced tips for working with regular expressions.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/advanced-regular-expression-tips-and-techniques/" rel="nofollow">Read the full article</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/PDCe0nUlGPw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/advanced-regular-expression-tips-and-techniques/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/advanced-regular-expression-tips-and-techniques</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: Day 13 – Extending the Framework</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/5nwLBCpejvs/codeigniter-from-scratch-day-13-extending-the-framework</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-13-extending-the-framework#comments</comments>
		<pubDate>Fri, 30 Apr 2010 10:51:54 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Uncategorized]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=891</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" />

<em>In today’s screencast we are going to learn how to create our own helpers and libraries. We are also going to learn how to extend the existing helpers and libraries that come with CodeIgniter. At the end of the tutorial we will extend the Form Validation library to give it the ability to check for password strength.</em>

<a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-extending-the-framework/" rel="nofollow">Click Here to Watch the Screencast</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%2Fcodeigniter-from-scratch-day-13-extending-the-framework"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-13-extending-the-framework&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /></p>
<p><em>In today’s screencast we are going to learn how to create our own helpers and libraries. We are also going to learn how to extend the existing helpers and libraries that come with CodeIgniter. At the end of the tutorial we will extend the Form Validation library to give it the ability to check for password strength.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-extending-the-framework/" rel="nofollow">Click Here to Watch the Screencast</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/5nwLBCpejvs" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-13-extending-the-framework/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-13-extending-the-framework</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: Day 12 – Shopping Cart</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/d_vMeRil8NM/codeigniter-from-scratch-day-12-shopping-cart</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-12-shopping-cart#comments</comments>
		<pubDate>Fri, 30 Apr 2010 10:50:49 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=889</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" />

<em>Today, we are going to take a look at the Shopping Cart library for CodeIgniter. This useful class allows us to add and remove items to a shopping cart, update them, and calculate prices. I will demonstrate how you can build a simple shopping cart system with the help of this library.. </em>


<a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-shopping-cart/" rel="nofollow">Click Here to Watch the Screencast</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%2Fcodeigniter-from-scratch-day-12-shopping-cart"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-12-shopping-cart&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /></p>
<p><em>Today, we are going to take a look at the Shopping Cart library for CodeIgniter. This useful class allows us to add and remove items to a shopping cart, update them, and calculate prices. I will demonstrate how you can build a simple shopping cart system with the help of this library.. </em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-shopping-cart/" rel="nofollow">Click Here to Watch the Screencast</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/d_vMeRil8NM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-12-shopping-cart/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-12-shopping-cart</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: Day 11 – File Operations</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/Ik1yjAz--R4/codeigniter-from-scratch-day-11-file-operations</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-11-file-operations#comments</comments>
		<pubDate>Fri, 30 Apr 2010 10:48:22 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=884</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" />

<em>In today’s episode, we are going to be working with several helper functions, related to files, directories, and downloads. We are going to learn how to read, write, download files, and retrieve information about both files and directories. Also at the end we will build a small file browser that utilizes jQuery as well.</em>

<a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-file-operations/" rel="nofollow">Click Here to Watch the Screencast</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%2Fcodeigniter-from-scratch-day-11-file-operations"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-11-file-operations&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /></p>
<p><em>In today’s episode, we are going to be working with several helper functions, related to files, directories, and downloads. We are going to learn how to read, write, download files, and retrieve information about both files and directories. Also at the end we will build a small file browser that utilizes jQuery as well.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-file-operations/" rel="nofollow">Click Here to Watch the Screencast</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/Ik1yjAz--R4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-11-file-operations/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-11-file-operations</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: (Day 10) The Calendar Library</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/HHY95WXiyuM/codeigniter-from-scratch-day-10-the-calendar-library</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-10-the-calendar-library#comments</comments>
		<pubDate>Fri, 05 Mar 2010 23:15:05 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=880</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" />Here is my next <a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/" rel="nofollow">screencast on CodeIgniter.</a>

<em>In this tenth episode of the CodeIgniter From Scratch screencast series, we will be exploring the Calendar library. We are also going to utilize the database class and jQuery AJAX. I will show you how to build a simple and CSS-styled calendar page, which will have the ability to store and display content for each day. </em>

<a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/" rel="nofollow">Click Here to Watch</a>

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

<img src="http://www.phpandstuff.com/wp-content/uploads/2010/03/ss.png" alt="ss" title="ss" width="641" height="400" class="aligncenter size-full wp-image-881" />]]></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-from-scratch-day-10-the-calendar-library"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-10-the-calendar-library&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" />Here is my next <a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/" rel="nofollow">screencast on CodeIgniter.</a></p>
<p><em>In this tenth episode of the CodeIgniter From Scratch screencast series, we will be exploring the Calendar library. We are also going to utilize the database class and jQuery AJAX. I will show you how to build a simple and CSS-styled calendar page, which will have the ability to store and display content for each day. </em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-the-calendar-library/" rel="nofollow">Click Here to Watch</a></p>
<div class="clear"></div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/03/ss.png" alt="ss" title="ss" width="641" height="400" class="aligncenter size-full wp-image-881" /></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/HHY95WXiyuM" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-10-the-calendar-library/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-10-the-calendar-library</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: Day 9 – File Uploading and Image Manipulation</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/f-MnGLAWsMk/codeigniter-from-scratch-day-9-file-uploading-and-image-manipulation</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-9-file-uploading-and-image-manipulation#comments</comments>
		<pubDate>Sun, 21 Feb 2010 23:52:39 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=872</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /> Nettuts+ published my next <a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/" rel="nofollow">screencast on CodeIgniter.</a>

<em>In lesson nine of our CodeIgniter series, we'll build a small image gallery that allows you to upload files, and automatically create thumbnails.
</em>

<a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/" rel="nofollow">Click Here to Watch</a>

<div class="clear"></div>
<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ss.png" alt="ss" title="ss" width="611" height="516" class="aligncenter size-full wp-image-876" />]]></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-from-scratch-day-9-file-uploading-and-image-manipulation"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-9-file-uploading-and-image-manipulation&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /> Nettuts+ published my next <a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/" rel="nofollow">screencast on CodeIgniter.</a></p>
<p><em>In lesson nine of our CodeIgniter series, we&#8217;ll build a small image gallery that allows you to upload files, and automatically create thumbnails.<br />
</em></p>
<p><a href="http://net.tutsplus.com/videos/screencasts/codeigniter-from-scratch-file-uploading-and-image-manipulation/" rel="nofollow">Click Here to Watch</a></p>
<div class="clear"></div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ss.png" alt="ss" title="ss" width="611" height="516" class="aligncenter size-full wp-image-876" /></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/f-MnGLAWsMk" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-9-file-uploading-and-image-manipulation/feed</wfw:commentRss>
		<slash:comments>8</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-9-file-uploading-and-image-manipulation</feedburner:origLink></item>
		<item>
		<title>CodeIgniter from Scratch: Day 8 – AJAX</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/gnR4G1R1BGw/codeigniter-from-scratch-day-8-ajax</link>
		<comments>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-8-ajax#comments</comments>
		<pubDate>Thu, 11 Feb 2010 17:33:31 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Screencasts]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=863</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /> Today Nettuts+ published my <a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-day-8-ajax/" rel="nofollow">screencast on CodeIgniter.</a>

<em>The CodeIgniter from Scratch series was unexpectedly, and significantly popular. Today, I’m pleased to announce that, with the help of one of my best authors, Burak, we’ll be continuing the series! Additionally, the most often requested topic is the subject for today’s screencast: combining CodeIgniter and jQuery.</em>

<a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-day-8-ajax/" rel="nofollow">Click Here to Watch</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%2Fcodeigniter-from-scratch-day-8-ajax"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-from-scratch-day-8-ajax&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/02/ci_from_scratch.jpg" alt="ci_from_scratch" title="ci_from_scratch" width="200" height="200" class="alignleft size-full wp-image-864" /> Today Nettuts+ published my <a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-day-8-ajax/" rel="nofollow">screencast on CodeIgniter.</a></p>
<p><em>The CodeIgniter from Scratch series was unexpectedly, and significantly popular. Today, I’m pleased to announce that, with the help of one of my best authors, Burak, we’ll be continuing the series! Additionally, the most often requested topic is the subject for today’s screencast: combining CodeIgniter and jQuery.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/codeigniter-from-scratch-day-8-ajax/" rel="nofollow">Click Here to Watch</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/gnR4G1R1BGw" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-8-ajax/feed</wfw:commentRss>
		<slash:comments>6</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-from-scratch-day-8-ajax</feedburner:origLink></item>
		<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?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-11-record-hooks&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" 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>69</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-11-record-hooks</feedburner:origLink></item>
		<item>
		<title>Scheduling Tasks with Cron Jobs</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/mWX4SoG2B88/scheduling-tasks-with-cron-jobs</link>
		<comments>http://www.phpandstuff.com/articles/scheduling-tasks-with-cron-jobs#comments</comments>
		<pubDate>Wed, 27 Jan 2010 22:42:27 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=846</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-847" /><em>Cron Jobs are used for scheduling tasks to run on the server. They're most commonly used for automating system maintenance or administration. However, they are also relevant to web application development. There are many situations when a web application may need certain tasks to run periodically. Today we are going to explore the fundamentals of Cron Jobs.</em>

<a href="http://net.tutsplus.com/tutorials/other/scheduling-tasks-with-cron-jobs/" rel="nofollow">Read the full article at Nettuts</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%2Fscheduling-tasks-with-cron-jobs"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fscheduling-tasks-with-cron-jobs&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-847" /><em>Cron Jobs are used for scheduling tasks to run on the server. They&#8217;re most commonly used for automating system maintenance or administration. However, they are also relevant to web application development. There are many situations when a web application may need certain tasks to run periodically. Today we are going to explore the fundamentals of Cron Jobs.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/other/scheduling-tasks-with-cron-jobs/" rel="nofollow">Read the full article at Nettuts</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/mWX4SoG2B88" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/scheduling-tasks-with-cron-jobs/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/scheduling-tasks-with-cron-jobs</feedburner:origLink></item>
		<item>
		<title>SQL For Beginners: Part 3 – Database Relationships</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/WsM3i3mTNdE/sql-for-beginners-part-3-database-relationships</link>
		<comments>http://www.phpandstuff.com/articles/sql-for-beginners-part-3-database-relationships#comments</comments>
		<pubDate>Thu, 21 Jan 2010 17:00:20 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Tutorials]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=838</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" /> <em>Today, we continue our journey into the world of SQL and relational database systems. In this part three of the series, we’ll learn how to work with multiple tables that have relationships with each other. First, we will go over some core concepts, and then will begin working with JOIN queries in SQL.</em>

<a href="http://net.tutsplus.com/tutorials/databases/sql-for-beginners-part-3-database-relationships/" rel="nofollow">Read More at Nettuts.com</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%2Fsql-for-beginners-part-3-database-relationships"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fsql-for-beginners-part-3-database-relationships&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" /> <em>Today, we continue our journey into the world of SQL and relational database systems. In this part three of the series, we’ll learn how to work with multiple tables that have relationships with each other. First, we will go over some core concepts, and then will begin working with JOIN queries in SQL.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/databases/sql-for-beginners-part-3-database-relationships/" rel="nofollow">Read More at Nettuts.com</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/WsM3i3mTNdE" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/sql-for-beginners-part-3-database-relationships/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/sql-for-beginners-part-3-database-relationships</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?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-10-pagination&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" 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>37</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-10-pagination</feedburner:origLink></item>
		<item>
		<title>Mastering cURL</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/GFZxSDOSqn4/mastering-curl</link>
		<comments>http://www.phpandstuff.com/articles/mastering-curl#comments</comments>
		<pubDate>Sat, 16 Jan 2010 07:27:07 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[curl]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=786</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-789" /> <em><a href="http://curl.haxx.se/" rel="nofollow">cURL</a> is a tool for transferring files and data with URL syntax, supporting many protocols including HTTP, FTP, TELNET and more. Initially, cURL was designed to be a command line tool. Lucky for us, the cURL library is also <a href="http://us3.php.net/manual/en/book.curl.php" rel="nofollow">supported by PHP</a>. In this article, we will look at some of the advanced features of cURL, and how we can use them in our PHP scripts.</em>

<a href="http://net.tutsplus.com/tutorials/php/techniques-and-resources-for-mastering-curl/">Read the rest of the article at Nettuts</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%2Fmastering-curl"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fmastering-curl&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2010/01/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-789" /> <em><a href="http://curl.haxx.se/" rel="nofollow">cURL</a> is a tool for transferring files and data with URL syntax, supporting many protocols including HTTP, FTP, TELNET and more. Initially, cURL was designed to be a command line tool. Lucky for us, the cURL library is also <a href="http://us3.php.net/manual/en/book.curl.php" rel="nofollow">supported by PHP</a>. In this article, we will look at some of the advanced features of cURL, and how we can use them in our PHP scripts.</em></p>
<p><a href="http://net.tutsplus.com/tutorials/php/techniques-and-resources-for-mastering-curl/">Read the rest of the article at Nettuts</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/GFZxSDOSqn4" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/mastering-curl/feed</wfw:commentRss>
		<slash:comments>4</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/mastering-curl</feedburner:origLink></item>
		<item>
		<title>SQL For Beginners Part 2</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/L6LTFqCi5SA/sql-for-beginners-part-2</link>
		<comments>http://www.phpandstuff.com/articles/sql-for-beginners-part-2#comments</comments>
		<pubDate>Tue, 22 Dec 2009 23:32:54 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=779</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" />Another article published on Nettuts

<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/" rel="nofollow">http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/</a>

<em>It is important for every web developer to be familiar with database interactions. In part two of the series, we will continue exploring the SQL language and apply what we’ve learned on a MySQL database. We will learn about Indexes, Data Types and more complex query structures.
</em>
<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/" rel="nofollow">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%2Fsql-for-beginners-part-2"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fsql-for-beginners-part-2&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" />Another article published on Nettuts</p>
<p><a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/" rel="nofollow">http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/</a></p>
<p><em>It is important for every web developer to be familiar with database interactions. In part two of the series, we will continue exploring the SQL language and apply what we’ve learned on a MySQL database. We will learn about Indexes, Data Types and more complex query structures.<br />
</em><br />
<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners-part-2/" rel="nofollow">Read More</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/L6LTFqCi5SA" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/sql-for-beginners-part-2/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/sql-for-beginners-part-2</feedburner:origLink></item>
		<item>
		<title>SQL for Beginners</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/TlTL_yl8RCc/sql-for-beginners</link>
		<comments>http://www.phpandstuff.com/articles/sql-for-beginners#comments</comments>
		<pubDate>Thu, 17 Dec 2009 06:52:31 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[Database]]></category>
		<category><![CDATA[MySQL]]></category>
		<category><![CDATA[SQL]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=767</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" />Another article published on Nettuts

<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners/" rel="nofollow">http://net.tutsplus.com/tutorials/other/sql-for-beginners/</a>

Most modern web applications today interact with databases, usually with a language called SQL. Lucky for us, this language is quite easy to learn. In this article, we are going to start with some basic SQL queries and use them to interact with a MySQL database.

<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners/" rel="nofollow">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%2Fsql-for-beginners"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fsql-for-beginners&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview1.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-768" />Another article published on Nettuts</p>
<p><a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners/" rel="nofollow">http://net.tutsplus.com/tutorials/other/sql-for-beginners/</a></p>
<p><em>Most modern web applications today interact with databases, usually with a language called SQL. Lucky for us, this language is quite easy to learn. In this article, we are going to start with some basic SQL queries and use them to interact with a MySQL database.<br />
</em><br />
<a href="http://net.tutsplus.com/tutorials/other/sql-for-beginners/" rel="nofollow">Read More</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/TlTL_yl8RCc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/sql-for-beginners/feed</wfw:commentRss>
		<slash:comments>10</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/sql-for-beginners</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?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-9-templates-data-hydrators&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" 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(&#8217;t.forum_id = ?&#8217;, $this->id)</strong> indicates which Forum id we are looking up.</p>
<p><strong>groupBy(&#8217;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>65</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-9-templates-data-hydrators</feedburner:origLink></item>
		<item>
		<title>Top 15+ Best Practices for Writing Super Readable Code</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/eE0r5vI6S7g/top-15-best-practices-for-writing-super-readable-code</link>
		<comments>http://www.phpandstuff.com/articles/top-15-best-practices-for-writing-super-readable-code#comments</comments>
		<pubDate>Thu, 10 Dec 2009 03:31:24 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[coding]]></category>
		<category><![CDATA[programming]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=711</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-713" /> My third article for <a href="http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/" rel="nofollow">Nettuts</a> was just published:

<em>"Code readability is a universal subject in the world of computer programming. It's one of the first things we learn as developers. Readable and maintainable code is something to be proud of in a finished product. We can share it with others, contribute to other projects, and reuse code from applications we wrote months or even years ago.

This article will detail the fifteen most important best practices when writing readable code."</em>

Read More: <a href="http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/" rel="nofollow">http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/</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-15-best-practices-for-writing-super-readable-code"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Ftop-15-best-practices-for-writing-super-readable-code&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview.jpg" alt="preview" title="preview" width="200" height="200" class="alignleft size-full wp-image-713" /> My third article for <a href="http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/" rel="nofollow">Nettuts</a> was just published:</p>
<p><em>&#8220;Code readability is a universal subject in the world of computer programming. It&#8217;s one of the first things we learn as developers. Readable and maintainable code is something to be proud of in a finished product. We can share it with others, contribute to other projects, and reuse code from applications we wrote months or even years ago.</p>
<p>This article will detail the fifteen most important best practices when writing readable code.&#8221;</em></p>
<p>Read More: <a href="http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/" rel="nofollow">http://net.tutsplus.com/tutorials/html-css-techniques/top-15-best-practices-for-writing-super-readable-code/</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/eE0r5vI6S7g" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/top-15-best-practices-for-writing-super-readable-code/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/top-15-best-practices-for-writing-super-readable-code</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?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fcodeigniter-doctrine-scratch-day-8-hooks-profiling-dql&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" 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>34</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/codeigniter-doctrine-scratch-day-8-hooks-profiling-dql</feedburner:origLink></item>
		<item>
		<title>HTTP Headers for Dummies</title>
		<link>http://feedproxy.google.com/~r/PhpAndStuff/~3/7Vytb2sRiFc/http-headers-for-dummies</link>
		<comments>http://www.phpandstuff.com/articles/http-headers-for-dummies#comments</comments>
		<pubDate>Wed, 02 Dec 2009 20:16:12 +0000</pubDate>
		<dc:creator>Burak</dc:creator>
				<category><![CDATA[Articles]]></category>
		<category><![CDATA[Tutorials]]></category>
		<category><![CDATA[headers]]></category>
		<category><![CDATA[http]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.phpandstuff.com/?p=641</guid>
		<description><![CDATA[<img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview_http.jpg" alt="preview_http" title="preview_http" width="200" height="200" class="alignleft size-full wp-image-642" />My second article for Nettuts was just published:

<a href="http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/" rel="nofollow">http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/</a>

Whether you're a programmer or not, you have seen it everywhere on the web. At this moment your browsers address bar shows something that starts with "http://". Even your first Hello World script sent HTTP headers without you realizing it. In this article we are going to learn about the basics of HTTP headers and how we can use them in our web applications.

<a href="http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/" rel="nofollow">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%2Fhttp-headers-for-dummies"><br />
				<img src="http://api.tweetmeme.com/imagebutton.gif?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Fhttp-headers-for-dummies&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" height="61" width="50" /><br />
			</a>
		</div>
<p><img src="http://www.phpandstuff.com/wp-content/uploads/2009/12/preview_http.jpg" alt="preview_http" title="preview_http" width="200" height="200" class="alignleft size-full wp-image-642" />My second article for Nettuts was just published:</p>
<p><a href="http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/" rel="nofollow">http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/</a></p>
<p>Whether you&#8217;re a programmer or not, you have seen it everywhere on the web. At this moment your browsers address bar shows something that starts with &#8220;http://&#8221;. Even your first Hello World script sent HTTP headers without you realizing it. In this article we are going to learn about the basics of HTTP headers and how we can use them in our web applications.</p>
<p><a href="http://net.tutsplus.com/tutorials/other/http-headers-for-dummies/" rel="nofollow">Read More</a></p>
<img src="http://feeds.feedburner.com/~r/PhpAndStuff/~4/7Vytb2sRiFc" height="1" width="1"/>]]></content:encoded>
			<wfw:commentRss>http://www.phpandstuff.com/articles/http-headers-for-dummies/feed</wfw:commentRss>
		<slash:comments>1</slash:comments>
		<feedburner:origLink>http://www.phpandstuff.com/articles/http-headers-for-dummies</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?url=http%3A%2F%2Fwww.phpandstuff.com%2Farticles%2Ftop-20-mysql-best-practices&amp;source=phpandstuff&amp;style=normal&amp;service=bit.ly" 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>
	</channel>
</rss><!-- Dynamic page generated in 0.954 seconds. --><!-- Cached page generated by WP-Super-Cache on 2010-09-03 12:03:41 -->
