<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	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/"
	>

<channel>
	<title>Inside DealTakerPHP » Inside DealTaker</title>
	<atom:link href="http://www.dealtaker.com/our-blog/tag/php/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.dealtaker.com/our-blog</link>
	<description>Just another DealTaker.com site</description>
	<lastBuildDate>Fri, 10 Feb 2012 14:56:55 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=</generator>
		<item>
		<title>PHP &amp; MongoDB Sitting in a Tree: Part 2</title>
		<link>http://www.dealtaker.com/our-blog/2010/06/22/php-mongodb-sitting-in-a-tree-part-2/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/06/22/php-mongodb-sitting-in-a-tree-part-2/#comments</comments>
		<pubDate>Tue, 22 Jun 2010 08:41:32 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[Joins]]></category>
		<category><![CDATA[mongo]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[Relational]]></category>
		<category><![CDATA[Relations]]></category>
		<category><![CDATA[Schema-less]]></category>
		<category><![CDATA[schemaless]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2387</guid>
		<description><![CDATA[In part II of this tutorial series, I&#8217;ll cover securing your MongoDB install and go over &#8220;Relations&#8221;. Before we start, if you have not, read part 1 first. Security So to make good on my promise, let&#8217;s get our MongoDB a little be more secure than what it is today. (*Note: At the time of [...]]]></description>
			<content:encoded><![CDATA[<p>In part II of this tutorial series, I&#8217;ll cover securing your MongoDB install and go over &#8220;Relations&#8221;. Before we start, if you have not, <a href="http://www.dealtaker.com/blog/2010/05/12/php-mongodb-sitting-in-a-tree-part-1/">read part 1</a> first.<br />
<span id="more-2387"></span></p>
<p><strong>Security</strong><br />
So to make good on my promise, let&#8217;s get our MongoDB a little be more secure than what it is today. (*Note: At the time of this writting, MongoDB only supports a simplistic security method, username and password. No encryption, no login server integration, ect.)</p>
<p>First open up your shell/command line and bring up the MongoDB Client. In *NIX, execute &#8220;./mongo&#8221; or Windows, &#8220;mongo&#8221;. Of course you might need to navigate to the location where MongoDB was install and execute it from the &#8220;bin&#8221; path. In my setup I have to execute it from &#8220;C:wampbinmongomongodb-win32-x86_64-1.4.1bin&#8221;.</p>
<p>Now that you have the client up enter in the following commands:</p>
<p>[bash]<br />
use admin<br />
db.addUser(&#8220;admin&#8221;, &#8220;admin_password&#8221;)<br />
db.auth(&#8220;admin&#8221;, &#8220;admin_password&#8221;)<br />
[/bash]</p>
<p>What we have done here is created a DB named &#8220;admin&#8221;, added a user to that DB named &#8220;admin&#8221; with the password of &#8220;admin_password&#8221; (I wouldn&#8217;t use &#8220;admin_password&#8221; for my admin password if I were you), then we authenticated our newly created user. If you don&#8217;t authenticate after adding the user, you won&#8217;t be able to perform any actions. OK, now that we have that taken care of, let get on with &#8220;relations&#8221;.</p>
<p><strong>Having relations</strong><br />
<img src="http://yuml.me/diagram/class/%5Buser|PK%20user_id:uint:nn:ai;username:varchar%2824%29:nn;password:char%2832%29:nn;email:varchar%28255%29],[user_profile|PK%20user_id:uint:nn;aim:varchar%2824%29;yahoo:varchar%2824%29;icq:uint;likes:text;dislikes:text;|FK:FK_user_profile_user_user_id],[user]1-1..*[user_profile]" alt="" width="489" height="141" /><br />
In MySQL, you might have laid out some tables using foreign keys to create <abbr title="one to one">1:1</abbr>, <abbr title="one to many">1:N</abbr>&gt; and <abbr title="many to many">N:N</abbr> relationships between them. So lets take simple 1:1 relationship table layout from MySQL, say &#8220;user&#8221; and &#8220;user_profile&#8221;, which the &#8220;user_profile&#8221; table will have primary key of &#8220;user_id&#8221;, which will be used also as a foreign key to create the relationship.</p>
<p><em>MySQL</em></p>
<p>[php]<br />
&lt;?php<br />
// Connect to MySQL<br />
$host = &#8216;localhost&#8217;;<br />
$user = &#8216;root&#8217;;<br />
$pass = &#8220;&#8221;;<br />
$db   = &#8216;testdb&#8217;;<br />
$link = mysql_connect($host, $user, $pass, 1) or die(&#8220;Could not connect to: {$host}. Check your settings and try again.&#8221;);</p>
<p>// Drop DB if exsists first<br />
$sql  = sprintf(&#8216;SET FOREIGN_KEY_CHECKS = 0;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;DROP DATABASE IF EXISTS `&#8217;.$db.&#8217;`;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the DB<br />
$sql  = sprintf(&#8216;CREATE DATABASE `&#8217;.$db.&#8217;`;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Select the DB<br />
mysql_select_db($db, $link);</p>
<p>// Create the &#8220;user&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_id`  INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `username` VARCHAR (24)NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `password` CHAR(32) NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `email`    VARCHAR(255)&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;user_profile&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user_profile`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_id`  INT UNSIGNED NOT NULL PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `aim`      VARCHAR(24),&#8217;.&#8221;n&#8221;.<br />
&#8216;     `yahoo`    VARCHAR(24),&#8217;.&#8221;n&#8221;.<br />
&#8216;     `icq`      INT UNSIGNED,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `likes`    TEXT,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `dislikes` TEXT&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the Foreign Key<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_profile`&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_profile_user_user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`user_id`)&#8217;.&#8221;n&#8221;.<br />
&#8216;REFERENCES `user` (`user_id`);&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
[/php]</p>
<p>So now we have created a relationship between two tables in MySQL, lets insert a user.<br />
<em>MySQL</em></p>
<p>[php]<br />
// Insert a user<br />
$user = &#8216;jsmith&#8217;;<br />
$pass = &#8217;5f4dcc3b5aa765d61d8327deb882cf99&#8242;;<br />
$eml  = &#8216;jsmith@example.com&#8217;;</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `user`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `username` = &#8216;%s&#8217;,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `password` = &#8216;%s&#8217;,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `email`    = &#8216;%s&#8217;;',<br />
mysql_real_escape_string($user),<br />
mysql_real_escape_string($pass),<br />
mysql_real_escape_string($eml));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Get the ID of last insert<br />
$id = mysql_insert_id($link);<br />
[/php]</p>
<p>Now that we have a user, let&#8217;s insert the user&#8217;s profile data.<br />
<em>MySQL</em></p>
<p>[php]<br />
// Add a profile for the last inserted user<br />
$aim  = &#8216;MrGoodGuy&#8217;;<br />
$like = &#8216;Ice cream, Pizza and puppies&#8217;;<br />
$dis  = &#8216;Oil spills&#8217;;<br />
$sql  = sprintf(&#8216;INSERT INTO `user_profile`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id`  = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `aim`      = &#8216;%s&#8217;,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `likes`    = &#8216;%s&#8217;,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `dislikes` = &#8216;%s&#8217;;',<br />
$id,<br />
mysql_real_escape_string($aim),<br />
mysql_real_escape_string($like),<br />
mysql_real_escape_string($dis));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
[/php]</p>
<p>Now that we have some data in the profile table that relates to the first entry of the user, lets query both tables with an &#8220;INNER JOIN&#8221;.<br />
<em>MySQL</em></p>
<p>[php]<br />
// Query both the &#8220;user&#8221; and &#8220;user_profile&#8221; tables with an &#8220;INNER JOIN&#8221;<br />
$sql  = sprintf(&#8216;SELECT *&#8217;.&#8221;n&#8221;.<br />
&#8216;FROM   `user` `u`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `user_profile` `p`&#8217;.&#8221;n&#8221;.<br />
&#8216;        ON `p`.`user_id` = `u`.`user_id`;&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
$cnt  = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}while(&#8211;$cnt &gt; 0);<br />
}<br />
[/php]</p>
<p>Enough of the MySQL example, we will be using document embedding to do the same thing in MongoDB.<br />
<em>MongoDB</em></p>
<p>[php]<br />
&lt;?php<br />
// Connect to MongoDB<br />
$user = &#8216;admin&#8217;;<br />
$pass = &#8216;admin_password&#8217;;</p>
<p>try<br />
{<br />
$link = new Mongo();<br />
$db   = $link-&gt;admin;</p>
<p>$db-&gt;authenticate($user, $pass);<br />
}<br />
catch(MongoConnectionException $e)<br />
{<br />
die(&#8216;Could not connect. Check to make sure MongoDB is running.&#8217;);<br />
}</p>
<p>// Create and use the DB<br />
$db   = $link-&gt;testdb;</p>
<p>// Drop DB if exsists first<br />
$db-&gt;drop();</p>
<p>// Create and use the DB<br />
$db   = $link-&gt;testdb;</p>
<p>// Create the &#8220;user&#8221; colection<br />
$col  = $db-&gt;user;</p>
<p>// Insert a new document<br />
$doc  = array(&#8216;username&#8217; =&gt; &#8216;jsmith&#8217;, &#8216;password&#8217; =&gt; &#8216; 5f4dcc3b5aa765d61d8327deb882cf99&#8242;, &#8216;email&#8217; =&gt; &#8216;jsmith@example.com&#8217;,<br />
&#8216;profile&#8217;  =&gt; array(&#8216;aim&#8217; =&gt; &#8216;MrGoodGuy&#8217;, &#8216;likes&#8217; =&gt; &#8216;Ice cream, Pizza and puppies&#8217;, &#8216;dislikes&#8217; =&gt; &#8216;Oil spills&#8217;));</p>
<p>$col-&gt;insert($doc, true);</p>
<p>// Get the ID of last insert<br />
$id   = $doc['_id'];</p>
<p>// Get all documents<br />
$res = $col-&gt;find();</p>
<p>echo &#8216;All documents:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>&#8220;Wow, pretty simple!&#8221; is what I&#8217;m thinking you are saying to your self. With MongoDB, instead of having to create two tables, the <abbr title="Foreign Key">FK</abbr>,  insert a record, get the id, and do another insert. We create  the collection and just insert our data with a multidimensional associative array.</p>
<p><img src="http://yuml.me/diagram/class/%5Buser|PK%20user_id:uint:nn:ai;username:varchar%2824%29:nn;password:char%2832%29:nn;email:varchar%28255%29],[user_profile|PK%20user_id:uint:nn;aim:varchar%2824%29;yahoo:varchar%2824%29;icq:uint;likes:text;dislikes:text;|FK:FK_user_profile_user_user_id],[user_likes|PK%20user_likes_id:uint:nn:ai;user_id:id:uint:nn;likes:varchar%28255%29%27|FK:FK_user_likes_user_user_id],[user]1-1..*[user_profile],[user]1-.-1..*[user_likes]" alt="" width="456" height="318" /><br />
1:1 relationships are easy, but what about 1:N relationships? Let get back into MySQL mode.<br />
<em>MySQL</em></p>
<p>[php]<br />
// Delete the &#8220;likes&#8221; and &#8220;dislikes&#8221; columns<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_profile`&#8217;.&#8221;n&#8221;.<br />
&#8216;DROP COLUMN `dislikes`,&#8217;.&#8221;n&#8221;.<br />
&#8216;DROP COLUMN `likes`;&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;user_likes&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_likes_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `user_id`       INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `likes`         VARCHAR(255) NOT NULL&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the Foreign Key<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_likes_user_user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`user_id`)&#8217;.&#8221;n&#8221;.<br />
&#8216;REFERENCES `user` (`user_id`);&#8217;);</p>
<p>// Create the &#8220;user_dislikes&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_dislikes_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `user_id`          INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `dislikes`         VARCHAR(255) NOT NULL&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the Foreign Key<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_likes_user_user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`user_id`)&#8217;.&#8221;n&#8221;.<br />
&#8216;REFERENCES `user` (`user_id`);&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Insert some &#8220;likes&#8221; and &#8220;dislikes&#8221;<br />
$like = array(&#8216;Ice cream&#8217;, &#8216;Pizza&#8217;, &#8216;Puppies&#8217;);</p>
<p>foreach($like as $val)<br />
{<br />
$sql = sprintf(&#8216;INSERT INTO `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id` = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `likes`   = &#8216;%s&#8217;;',<br />
$id,<br />
mysql_real_escape_string($val));</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
}</p>
<p>$dis  = array(&#8216;Oil spills&#8217;);</p>
<p>foreach($dis as $val)<br />
{<br />
$sql = sprintf(&#8216;INSERT INTO `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id` = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `dislikes`   = &#8216;%s&#8217;;',<br />
$id,<br />
mysql_real_escape_string($val));</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
}</p>
<p>// Query the &#8220;user&#8221; table and pull in the &#8220;likes&#8221; and &#8220;dislikes&#8221; data.<br />
$sql  = sprintf(&#8216;SELECT `u`.*,&#8217;.&#8221;n&#8221;.<br />
&#8216;       GROUP_CONCAT(DISTINCT `l`.`likes` SEPARATOR &#8216;, &#8216;) AS `likes`,&#8217;.&#8221;n&#8221;.<br />
&#8216;       GROUP_CONCAT(DISTINCT `d`.`dislikes` SEPARATOR &#8216;, &#8216;) AS `dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;FROM  `user` `u`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `user_likes` `l`&#8217;.&#8221;n&#8221;.<br />
&#8216;        ON `l`.`user_id` = `u`.`user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `user_dislikes` `d`&#8217;.&#8221;n&#8221;.<br />
&#8216;        ON `d`.`user_id` = `u`.`user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;WHERE `u`.`user_id` = %u;&#8217;,<br />
$id);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
$cnt  = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}while(&#8211;$cnt &gt; 0);<br />
}<br />
[/php]</p>
<p>Boy is that a lot of work and I cheated with &#8220;group_concat&#8221; function. Let do this with MongoDB.<br />
<em>MongoDB</em></p>
<p>[php]<br />
// Create a &#8220;1:N&#8221; for &#8220;likes&#8221; and &#8220;dislikes&#8221; in the &#8220;profile&#8221; element<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$set&#8217; =&gt; array(&#8216;profiles&#8217; =&gt; array(&#8216;likes&#8217;    =&gt; array(&#8216;Ice cream&#8217;, &#8216;Pizza&#8217;, &#8216;Puppies&#8217;),<br />
&#8216;dislikes&#8217; =&gt; array(&#8216;Oil spills&#8217;)))));</p>
<p>echo &#8216;All documents:&lt;br/&gt;&#8217;;</p>
<p>// Get all documents<br />
$res = $col-&gt;find();</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>Since MongoDB is schema-less, we can update how we store the &#8220;likes&#8221; and &#8220;dislikes&#8221; and it comes back to us as an array that we could iterate through. So what&#8217;s next?</p>
<p><img src="http://yuml.me/diagram/class/%5Buser|PK%20user_id:uint:nn:ai;username:varchar%2824%29:nn;password:char%2832%29:nn;email:varchar%28255%29],[user_profile|PK%20user_id:uint:nn;aim:varchar%2824%29;yahoo:varchar%2824%29;icq:uint;likes:text;dislikes:text;|FK:FK_user_profile_user_user_id],[user_likes|PK%20user_id:uint:nn;PK%20user_likes_id:uint:nn;|FK:FK_user_likes_user_user_id;FK:FK_user_likes_likes_likes_id],[user_dislikes|PK%20user_id:uint:nn;PK%20dislikes_id:uint:nn;|FK:FK_user_dislikes_user_user_id;FK:FK_user_dislikes_dislikes_dislikes_id],[likes|PK%20likes_id:uint:nn:ai;likes:varchar%28255%29;],[dislikes|PK%20dislikes_id:uint:nn:ai;dislikes:varchar%28255%29;],[user]1-1..*[user_profile],[user]1-1..*[user_likes],[user]1-1..*[user_dislikes],[likes]1-1..*[user_likes],[dislikes]1-1..*[user_dislikes]" alt="" width="496" height="212" /><br />
N:N relationships. Oh boy are those the ultimate in a relational model. Once again, I&#8217;ll how we do this in MySQL.<br />
<em>MySQL</em></p>
<p>[php]<br />
// Drop &#8220;user_likes&#8221; table if exsists first<br />
$sql  = sprintf(&#8216;SET FOREIGN_KEY_CHECKS = 0;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;DROP TABLE IF EXISTS `user_likes`;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Drop &#8220;dislikes&#8221; table if exsists first<br />
$sql  = sprintf(&#8216;SET FOREIGN_KEY_CHECKS = 0;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;DROP TABLE IF EXISTS `user_dislikes`;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;likes&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`likes_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `likes`    VARCHAR (255) NOT NULL&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;like&#8221; joins table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_id`  INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `likes_id` INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     PRIMARY KEY (`user_id`, `likes_id`)&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create Foriegn Keys<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_likes_user_user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`),&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_likes_likes_likes_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`likes_id`) REFERENCES `likes` (`likes_id`);&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Insert some &#8220;likes&#8221;<br />
$sql  = sprintf(&#8216;INSERT INTO `likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `likes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;Ice Cream&#8217;));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `%s`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `likes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;likes&#8217;),<br />
mysql_real_escape_string(&#8216;Pizza&#8217;)<br />
);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `%s`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `likes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;likes&#8217;),<br />
mysql_real_escape_string(&#8216;Puppies&#8217;)<br />
);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `likes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;Kittens&#8217;));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create some &#8220;likes&#8221; relations (Cheating &#8211; since I already know the id&#8217;s)<br />
$sql  = sprintf(&#8216;INSERT INTO `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id`  = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `likes_id` = %u;&#8217;,<br />
1,<br />
1);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id`  = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `likes_id` = %u;&#8217;,<br />
1,<br />
2);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `user_likes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id`  = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `likes_id` = %u;&#8217;,<br />
1,<br />
3);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;dislikes&#8221; table<br />
$sql  = sprintf(&#8216;CREATE TABLE `dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`dislikes_id` INT UNSIGNED NOT NULL AUTO_INCREMENT PRIMARY KEY,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `dislikes`    VARCHAR (255) NOT NULL&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create the &#8220;dislike&#8221; joins table<br />
$sql  = sprintf(&#8216;CREATE TABLE `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;    (`user_id`     INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     `dislikes_id` INT UNSIGNED NOT NULL,&#8217;.&#8221;n&#8221;.<br />
&#8216;     PRIMARY KEY (`user_id`, `dislikes_id`)&#8217;.&#8221;n&#8221;.<br />
&#8216;    ) TYPE=innodb;&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create Foriegn Keys<br />
$sql  = sprintf(&#8216;ALTER TABLE `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_dislikes_user_user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`user_id`) REFERENCES `user` (`user_id`),&#8217;.&#8221;n&#8221;.<br />
&#8216;ADD CONSTRAINT `FK_user_dislikes_likes_likes_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;FOREIGN KEY (`dislikes_id`) REFERENCES `dislikes` (`dislikes_id`);&#8217;);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Insert some &#8220;dislikes&#8221;<br />
$sql  = sprintf(&#8216;INSERT INTO `dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `dislikes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;Oil Spills&#8217;));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>$sql  = sprintf(&#8216;INSERT INTO `dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `dislikes` = &#8216;%s&#8217;;',<br />
mysql_real_escape_string(&#8216;Screaming Babies&#8217;));</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Create some &#8220;dislikes&#8221; relations<br />
$sql  = sprintf(&#8216;INSERT INTO `user_dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET    `user_id`  = %u,&#8217;.&#8221;n&#8221;.<br />
&#8216;       `dislikes_id` = %u;&#8217;,<br />
1,<br />
1);</p>
<p>mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);</p>
<p>// Query &#8220;USER&#8221; and join with &#8220;likes&#8221; and &#8220;dislikes&#8221;<br />
$sql  = sprintf(&#8216;SELECT `u`.*,&#8217;.&#8221;n&#8221;.<br />
&#8216;       GROUP_CONCAT(DISTINCT `l`.`likes` SEPARATOR &#8216;, &#8216;) AS `likes`,&#8217;.&#8221;n&#8221;.<br />
&#8216;       GROUP_CONCAT(DISTINCT `d`.`dislikes` SEPARATOR &#8216;, &#8216;) AS `dislikes`&#8217;.&#8221;n&#8221;.<br />
&#8216;FROM  `user` `u`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `user_likes` `ul`&#8217;.&#8221;n&#8221;.<br />
&#8216;        ON `ul`.`user_id` = `u`.`user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `likes` `l`&#8217;.&#8221;n&#8221;.<br />
&#8216;       ON  `l`.`likes_id` = `ul`.`likes_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `user_dislikes` `ud`&#8217;.&#8221;n&#8221;.<br />
&#8216;        ON `ud`.`user_id` = `u`.`user_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;    INNER JOIN `dislikes` `d`&#8217;.&#8221;n&#8221;.<br />
&#8216;       ON  `d`.`dislikes_id` = `ud`.`dislikes_id`&#8217;.&#8221;n&#8221;.<br />
&#8216;WHERE `u`.`user_id` = 1;&#8217;);</p>
<p>$qry  = mysql_query($sql, $link) or die(&#8220;&lt;pre&gt;SQL:n{$sql}nERROR:n&#8221;.mysql_error($link).&#8217;&lt;/pre&gt;&#8217;);<br />
$cnt  = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}while(&#8211;$cnt &gt; 0);<br />
}<br />
[/php]</p>
<p>Wow! Again, MySQL is making us work some more. With MongoDB we have three approaches. The first way is to fake it with a 1:1 or 1:N with an extra collection with the values you want to validate against.  This might seem odd if you want to do a N:N relation, but there is reason why would want to do this in MongoDB . The second way is to create &#8220;manual relations&#8221;. This is kind of like MyISAM, where there isn&#8217;t an automatic relation, you have to specify it in your query. So lets look that one over.</p>
<p><em>MongoDB</em><br />
[php]<br />
// Create the &#8220;likes&#8221; and &#8220;dislikes&#8221; collections (create, drop and recreate).<br />
$likes = $db-&gt;likes;<br />
$likes-&gt;drop();<br />
$likes = $db-&gt;likes;</p>
<p>$dis   = $db-&gt;dislikes;<br />
$dis-&gt;drop();<br />
$dis   = $db-&gt;dislikes;</p>
<p>// Insert some &#8220;likes&#8221; and &#8220;dislikes&#8221;<br />
// &#8220;Likes&#8221;<br />
$doc  = array(&#8216;likes&#8217; =&gt; &#8216;Ice cream&#8217;);<br />
$likes-&gt;insert($doc, true);</p>
<p>$doc  = array(&#8216;likes&#8217; =&gt; &#8216;Pizza&#8217;);<br />
$likes-&gt;insert($doc, true);</p>
<p>$doc  = array(&#8216;likes&#8217; =&gt; &#8216;Puppies&#8217;);<br />
$likes-&gt;insert($doc, true);</p>
<p>$doc  = array(&#8216;likes&#8217; =&gt; &#8216;Kittens&#8217;);<br />
$likes-&gt;insert($doc, true);</p>
<p>$ls   = $likes-&gt;find();</p>
<p>// &#8220;Dislikes&#8221;<br />
$doc  = array(&#8216;dislikes&#8217; =&gt; &#8216;Oil spills&#8217;);<br />
$dis-&gt;insert($doc, true);</p>
<p>$doc  = array(&#8216;dislikes&#8217; =&gt; &#8216;Screeming children&#8217;);<br />
$dis-&gt;insert($doc, true);</p>
<p>// Create a &#8220;N:N&#8221; for &#8220;likes&#8221; and &#8220;dislikes&#8221; in the &#8220;profile&#8221; element<br />
// Find our &#8220;likes&#8221;<br />
$ic   = $likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Ice cream&#8217;));<br />
$pz   = $likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Pizza&#8217;));<br />
$ps   = $likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Puppies&#8217;));</p>
<p>// Find our &#8220;dislikes&#8221;<br />
// Find our &#8220;likes&#8221;<br />
$os   = $dis-&gt;findOne(array(&#8216;dislikes&#8217; =&gt; &#8216;Oil spills&#8217;));</p>
<p>// Create manual reference<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$set&#8217; =&gt; array(&#8216;profile&#8217; =&gt; array(&#8216;likes&#8217;    =&gt; array($ic['_id'], $pz['_id'], $ps['_id']),<br />
&#8216;dislikes&#8217; =&gt; array($os['_id'])))));</p>
<p>// Get all documents<br />
$res = $col-&gt;find();</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);</p>
<p>echo &#8220;nLikes:n&#8221;;</p>
<p>foreach($doc['profile']['likes'] as $key=&gt;$val)<br />
{<br />
$l = $likes-&gt;findOne(array(&#8216;_id&#8217; =&gt; $val));<br />
echo $l['likes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8220;nDislikes:n&#8221;;</p>
<p>foreach($doc['profile']['dislikes'] as $key=&gt;$val)<br />
{<br />
$d = $dis-&gt;findOne(array(&#8216;_id&#8217; =&gt; $val));<br />
echo $d['dislikes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>The thirday way is to create a reference (DBRef) to another document.<br />
<em>MongoDB</em></p>
<p>[php]<br />
// Create an automatic reference<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$set&#8217; =&gt; array(&#8216;profile&#8217; =&gt; array(&#8216;likes&#8217;    =&gt; array(array(&#8216;$ref&#8217; =&gt; &#8216;likes&#8217;, &#8216;$id&#8217; =&gt; $ic['_id']),<br />
array(&#8216;$ref&#8217; =&gt; &#8216;likes&#8217;, &#8216;$id&#8217; =&gt; $pz['_id']),<br />
array(&#8216;$ref&#8217; =&gt; &#8216;likes&#8217;, &#8216;$id&#8217; =&gt; $ps['_id'])<br />
),<br />
&#8216;dislikes&#8217; =&gt; array(array(&#8216;$ref&#8217; =&gt; &#8216;dislikes&#8217;, &#8216;$id&#8217; =&gt; $os['_id']))))));</p>
<p>// Get all documents<br />
$res = $col-&gt;find();</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);</p>
<p>echo &#8220;nLikes:n&#8221;;</p>
<p>foreach($doc['profile']['likes'] as $key=&gt;$val)<br />
{<br />
$l = $likes-&gt;findOne(array(&#8216;_id&#8217; =&gt; $val['$id']));<br />
echo $l['likes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8220;nDislikes:n&#8221;;</p>
<p>foreach($doc['profile']['dislikes'] as $key=&gt;$val)<br />
{<br />
$d = $dis-&gt;findOne(array(&#8216;_id&#8217; =&gt; $val['$id']));<br />
echo $d['dislikes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>So we&#8217;ve created an element that references a document. The key was to query what we needed, then used &#8220;$ref&#8221; identifier (<a href="http://www.mongodb.org/display/DOCS/Database+References" target="_blank">More information</a>) along with the ID return from our query to create the element. There is another way to do this in PHP by using the &#8220;<a href="http://us3.php.net/manual/en/mongocollection.createdbref.php" target="_blank">MongoCollection::createDBRef</a>&#8221; method.<br />
<em>MongoDB</em></p>
<p>[php]<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$set&#8217; =&gt; array(&#8216;profile&#8217; =&gt; array(&#8216;likes&#8217;    =&gt; array($likes-&gt;createDBRef($likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Ice cream&#8217;))),<br />
$likes-&gt;createDBRef($likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Pizza&#8217;))),<br />
$likes-&gt;createDBRef($likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Puppies&#8217;)))<br />
),<br />
&#8216;dislikes&#8217; =&gt; array($dis-&gt;createDBRef($dis-&gt;findOne(array(&#8216;dislikes&#8217; =&gt; &#8216;Oil spills&#8217;))))));<br />
[/php]</p>
<p>And we can also clean up our loop with less code:<br />
<em>MongoDB</em></p>
<p>[php]<br />
foreach($doc['profile']['dislikes'] as $key=&gt;$val)<br />
{<br />
$d = $col-&gt;getDBRef($val);<br />
echo $d['dislikes'].&#8221;n&#8221;;<br />
}<br />
[/php]</p>
<p>Of course there is one problem with doing N:N in MongoDB . You can&#8217;t query it with a single query, since there is no &#8220;JOIN&#8221; support. So it would be better to embed the data you need to search on and return. Sure it might be redundant, but it seems that would be the best solution at this time. For more information about when to use DBRef vs Embedding, check out the <a title="MongoDB Schema Design" href="http://www.mongodb.org/display/DOCS/Schema+Design" target="_blank">Schema Design article</a>.</p>
<p>Before we end this tutorial, let me leave you with a little extra, adding to the &#8220;likes&#8221; and &#8220;dislikes&#8221; in the &#8220;profile&#8221;:<br />
<em>MongoDB</em></p>
<p>[php]<br />
// Add (Not replace) another &#8220;likes&#8221; and &#8220;Dislikes&#8221; to the profile.<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$pushAll&#8217; =&gt; array(&#8216;profile.likes&#8217; =&gt; array($likes-&gt;createDBRef($likes-&gt;findOne(array(&#8216;likes&#8217; =&gt; &#8216;Kittens&#8217;)))),<br />
&#8216;profile.dislikes&#8217; =&gt; array($dis-&gt;createDBRef($dis-&gt;findOne(array(&#8216;dislikes&#8217; =&gt; &#8216;Screeming children&#8217;)))))), array(&#8216;safe&#8217; =&gt; 1));</p>
<p>// Get all documents<br />
$res = $col-&gt;find();</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8220;&lt;pre&gt;Pushed:n&#8221;;<br />
print_r($doc);</p>
<p>echo &#8220;nLikes:n&#8221;;</p>
<p>foreach($doc['profile']['likes'] as $key=&gt;$val)<br />
{<br />
$l = $col-&gt;getDBRef($val);<br />
echo $l['likes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8220;nDislikes:n&#8221;;</p>
<p>foreach($doc['profile']['dislikes'] as $key=&gt;$val)<br />
{<br />
$d = $col-&gt;getDBRef($val);<br />
echo $d['dislikes'].&#8221;n&#8221;;<br />
}</p>
<p>echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>You&#8217;ll notice that use used the &#8220;keyword&#8221; of &#8220;$pushAll&#8221; to push our array into the &#8220;likes&#8221; and &#8220;dislikes&#8221; element. Also note that we also used dot notation (&#8220;profile.likes&#8221;) to indicated that &#8220;likes&#8221; and &#8220;dislikes&#8221; are element of &#8220;profile&#8221;. So if we had something like &#8220;animal&#8221; which was an array element of &#8220;likes&#8221; which is part of &#8220;profile&#8221;, we would have done &#8220;profile.likes.animal&#8221;.</p>
<p>Until next time, when we will go over &#8230; I&#8217;m not sure yet, It&#8217;ll be a surprise &#8230; Happy Coding!</p>
<p>If you want a VPS with that has a &#8220;one-click&#8221; install of MongoDB, check out <a href="http://www.dealtaker.com/store/dream-host/l" target="_blank">DreamHost</a>. Also don&#8217;t forget to check out our <a href="http://www.dealtaker.com/technology/" target="_blank">tech blog</a> and <a href="http://www.dealtaker.com/category/computers-office/computers/" target="_blank">Computer related coupons</a>.</p>
<p><a href="http://www.dealtaker.com/blog/2010/05/12/php-mongodb-sitting-in-a-tree-part-1/">Part 1</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/06/22/php-mongodb-sitting-in-a-tree-part-2/feed/</wfw:commentRss>
		<slash:comments>4</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 9</title>
		<link>http://www.dealtaker.com/our-blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/#comments</comments>
		<pubDate>Wed, 02 Jun 2010 13:23:25 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[library]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[tutorial]]></category>
		<category><![CDATA[Zend]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2340</guid>
		<description><![CDATA[Welcome to the ninth part in this series on how to develop with Kohana PHP V3 (KO3). If you havenâ€™t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over using other frameworks&#8217; libraries. Before we get into loading external libraries, [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the ninth part in this series on how to develop with Kohana PHP V3 (KO3). If you havenâ€™t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over using other frameworks&#8217; libraries.<br />
<span id="more-2340"></span><br />
Before we get into loading external libraries, weâ€™ll want to update the KO3 code base. Go in to &#8220;application&#8221; directory and rename your &#8220;bootstrap.php&#8221; to &#8220;bootstrap.bak.php&#8221;. Now point your browser to http://kohanaframework.org/download and download the latest stable (3.0.5), open it and extract everything inside the &#8220;kohana&#8221; folder to &#8220;mykohana3&#8243;. Once you have done that, delete or rename the &#8220;install.php&#8221; in your &#8220;mykohana3&#8243; folder. Next, delete the &#8220;bootstrap.php&#8221; file in the &#8220;application&#8221; folder and rename the &#8220;bootstrap.bak.php&#8221; to &#8220;bootstrap.php&#8221;.</p>
<p>The first thing we need to do is create a folder named &#8220;vendors&#8221; under &#8220;application&#8221;. In the &#8220;vendors&#8221; folder, create another folder named &#8220;Zend&#8221; (yes, with a capital &#8220;Z&#8221;). Next we&#8217;ll need to download the latest version of Zend Framework, so click here to download 1.10.5. Open the archive up and extract everything from &#8220;ZendFramework-1.10.5-minimal/library/Zend/&#8221; into &#8220;application/vendors/Zend&#8221;.</p>
<p>Open the  &#8220;application/bootstrap.php&#8221; file and add the following above the line which reads &#8220;echo Request::getInstance()&#8221;:</p>
<p>[php]<br />
$path = Kohana::find_file(&#8216;vendors&#8217;, &#8216;Zend/Loader&#8217;);</p>
<p>if($path)<br />
 {<br />
    ini_set(&#8216;include_path&#8217;,<br />
    ini_get(&#8216;include_path&#8217;) . PATH_SEPARATOR . dirname(dirname($path)));</p>
<p>    require_once &#8216;Zend/Loader/Autoloader.php&#8217;;<br />
    Zend_Loader_Autoloader::getInstance();<br />
 }<br />
[/php]</p>
<p>Open &#8220;application/views/pages/ko3.php&#8221; and put the following at the bottom:</p>
<p>[php]<br />
  &lt;?php $validator = new Zend_Validate_Isbn();?&gt;<br />
  &lt;br /&gt;978-3-16-148410-0 &lt;?php echo ($validator-&gt;isValid(&#8217;978-3-16-148410-0&#8242;)) ? &#8216;is&#8217; : &#8216;is not&#8217;;?&gt; valid.<br />
  &lt;br /&gt;9783161484100 &lt;?php echo ($validator-&gt;isValid(&#8217;9783161484100&#8242;)) ? &#8216;is&#8217; : &#8216;is not&#8217;;?&gt; valid.<br />
[/php]</p>
<p>Now if you load &#8220;http://yourserver/mykohana3/ko3&#8243; in your browser, you should see the two tests at the bottom.</p>
<p>Until next time, when I go over forms, happy coding.</p>
<p>If you enjoyed this tutorial, please check out our <a href="http://www.dealtaker.com/technology/" target="_blank">tech blog</a> and <a href="http://www.dealtaker.com/category/computers-office/computers/" target="_blank">computer related coupons</a>.</p>
<p><a href="http://www.dealtaker.com/blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/">Part 8</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>PHP &amp; MongoDB Sitting in a Tree: Part 1</title>
		<link>http://www.dealtaker.com/our-blog/2010/05/12/php-mongodb-sitting-in-a-tree-part-1/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/05/12/php-mongodb-sitting-in-a-tree-part-1/#comments</comments>
		<pubDate>Wed, 12 May 2010 21:08:30 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[database]]></category>
		<category><![CDATA[db]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[mongo]]></category>
		<category><![CDATA[mongodb]]></category>
		<category><![CDATA[mysql]]></category>
		<category><![CDATA[nosql]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[scale]]></category>
		<category><![CDATA[Schema-less]]></category>
		<category><![CDATA[schemaless]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2187</guid>
		<description><![CDATA[Yet another MongoDB and PHP tutorial, say it ain&#8217;t so! Well yes, but this tutorial aims to be more complete than the others out there. OK I&#8217;m going to assume you know what MongoDB is, so I&#8217;m not going to go over &#8220;what mongoDB is&#8221; or &#8220;what NoSQL is&#8221;. I&#8217;m going to do this series [...]]]></description>
			<content:encoded><![CDATA[<p>Yet another MongoDB and PHP tutorial, say it ain&#8217;t so! Well yes, but this tutorial aims to be more complete than the others out there. OK I&#8217;m going to assume you know what MongoDB is, so I&#8217;m not going to go over &#8220;what mongoDB is&#8221; or &#8220;what NoSQL is&#8221;. I&#8217;m going to do this series in a little different styling than my other tutorial series have been, so let just jump right in.<br />
<span id="more-2187"></span></p>
<p>Here&#8217;s a couple links to get you up to speed:<br />
<a href="http://www.mongodb.org/display/DOCS/Quickstart">Installing Mongo</a><br />
<a href="http://www.mongodb.org/display/DOCS/PHP+Language+Center">MongoDB PHP Extension</a></p>
<p>If you have issues with MongoD not starting &#8211; something about &#8220;/data/db&#8221; missing, then you should create the directory. In *Nix: &#8220;mkdir /data/db&#8221;, in Win &#8220;mkdir c:data&#8221; then &#8220;mkdir c:datadb&#8221;.</p>
<p><strong>Connecting</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
&lt;?php<br />
$host = &#8216;localhost&#8217;;<br />
$user = &#8216;root&#8217;;<br />
$pass = &#8220;&#8221;;<br />
$link = mysql_connect($host, $user, $pass, 1) or die(&#8220;Could not connect to: {$host}. Check your settings and try again.&#8221;);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
&lt;?php<br />
try<br />
{<br />
$link = new Mongo();<br />
}<br />
catch(MongoConnectionException $e)<br />
{<br />
die(&#8216;Could not connect. Check to make sure MongoDB is running.&#8217;);<br />
}<br />
[/php]</p>
<p>As you can see, Mongo DB automatically will connect to the local host and default port. Yes, MySQL will do the same if you have the directives in your &#8220;php.ini&#8221; setup to do this. IE. &#8220;mysql.default_host&#8221;, &#8220;mysql.default_user&#8221; and &#8220;mysql.default_password&#8221;. You might notice that by default MongoDB doesn&#8217;t have a user name or password setup. I will go over how to set that up in part 2.</p>
<p><strong>Creating and using a DB</strong><br />
<em>MySQL</em></p>
<p>[php]$db  = &#8216;testdb&#8217;;<br />
$sql = &#8220;CREATE DATABASE `$db`&#8221;;</p>
<p>mysql_query($sql, $link);<br />
mysql_select_db($db, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]$db   = $link-&gt;testdb;<br />
[/php]</p>
<p>In one line of code, MongoDB will create a DB automatically if it doesn&#8217;t already exists and select (use) it.</p>
<p><strong>Create a Table / Collection</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Create the Table<br />
$tbl = &#8216;user&#8217;;<br />
$sql = &#8220;CREATE TABLE `$tbl` (`id` INT NOT NULL AUTO_INCREMENT PRIMARY KEY, `login` VARCHAR (24)NOT NULL, `password` CHAR(32) NOT NULL, `email` VARCHAR(255)) TYPE=innodb;&#8221;;<br />
mysql_query($sql, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Create the collection (AKA Table)<br />
$col  = $db-&gt;user;<br />
[/php]</p>
<p>Once again, MongoDB will automatically create something for us if it doesn&#8217;t exist. In this example, it create our &#8220;user&#8221; table. You might notice we didn&#8217;t define how the table is formatted, this is because MongoDB is schema-less and doesn&#8217;t need column definitions. &#8220;Tables&#8221; in MongoDB are called &#8220;collections&#8221;.</p>
<p><strong>Insert Data</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Insert a row into the table<br />
$sql = &#8220;INSERT INTO `$tbl` SET `login` = &#8216;jsmith&#8217;, `password` = &#8217;5f4dcc3b5aa765d61d8327deb882cf99&#8242;, `email` = &#8216;jsmith@example.com&#8217;&#8221;;<br />
mysql_query($sql);</p>
<p>$sql = &#8220;INSERT INTO `$tbl` SET `login` = &#8216;psmith&#8217;, `password` = &#8217;5f4dcc3b5aa765d61d8327deb882cf99&#8242;, `email` = &#8216;psmith@example.com&#8217;&#8221;;<br />
mysql_query($sql);</p>
<p>// Get the ID of last insert<br />
$id = mysql_insert_id($link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Insert a document (row) into the collection (table)<br />
$doc  = array(&#8216;login&#8217; =&gt; &#8216;jsmith&#8217;, &#8216;password&#8217; =&gt; &#8216; 5f4dcc3b5aa765d61d8327deb882cf99&#8242;, &#8216;email&#8217; =&gt; &#8216;jsmith@example.com&#8217;);<br />
$col-&gt;insert($doc, true);</p>
<p>$doc  = array(&#8216;login&#8217; =&gt; &#8216;psmith&#8217;, &#8216;password&#8217; =&gt; &#8216; 5f4dcc3b5aa765d61d8327deb882cf99&#8242;, &#8216;email&#8217; =&gt; &#8216;psmith@example.com&#8217;);<br />
$col-&gt;insert($doc, true);</p>
<p>// Get the id of last insert<br />
$id   = $doc['_id'];<br />
[/php]</p>
<p>You might have noticed that we used an array to define our &#8220;row&#8221; of data, which are called &#8220;documents&#8221;. On the insert method, the second argument will set the query to do a &#8220;safe insert&#8221;. This will allow us to find out if the query executed properly. If not set, it will not get that information. So I would set it to true if you want to be able to debug your queries. If you are wondering about the password, it&#8217;s the MD5 hash for &#8220;password&#8221;.</p>
<p><strong>Querying Data</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Get all rows<br />
$sql = &#8220;SELECT * FROM `$tbl`&#8221;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;<br />
}<br />
}</p>
<p>// Query for the row matching the last insert ID<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `id` = {$id}&#8221;;<br />
$qry = mysql_query($sql, $link);<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;Single row (id = $id):&amp;lt;br/&amp;gt;&amp;lt;pre&amp;gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Get all documents<br />
$res = $col-&gt;find();</p>
<p>echo &#8216;All documents:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for the document matching the last insert ID<br />
$doc  = $col-&gt;findone(array(&#8216;_id&#8217; =&gt; $id));</p>
<p>echo &#8216;Single document (_id = $id):&lt;br/&gt;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
[/php]</p>
<p>The MongoDB support in PHP has function to pull a single document, or all the documents. Once again, we use arrays to define something, in this example, we define our constraint.</p>
<p><strong>Upading Data</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
$sql = &#8220;UPDATE `$tbl` SET `password` = &#8216;b497dd1a701a33026f7211533620780d&#8217; WHERE `id` = {$id}&#8221;;<br />
$qry = mysql_query($sql, $link);</p>
<p>$sql = &#8220;SELECT * FROM `$tbl` WHERE `id` = {$id}&#8221;;<br />
$qry = mysql_query($sql, $link);<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;Updated row (id = $id):&lt;br/&gt;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;<br />
[/php]</p>
<p><em>MogoDB</em></p>
<p>[php]<br />
// Update a document<br />
$col-&gt;update(array(&#8216;_id&#8217; =&gt; $id), array(&#8216;$set&#8217; =&gt; array(&#8216;password&#8217; =&gt; &#8216;b497dd1a701a33026f7211533620780d&#8217;)));</p>
<p>// Query the updated docuemnt<br />
$doc = $col-&gt;findone(array(&#8216;_id&#8217; =&gt; $id));</p>
<p>echo &#8216;Updated docuement:&lt;br/&gt;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
[/php]</p>
<p>The MongoDB extension has a function to perform updates. The first argument is an array of constraints, IE &#8220;WHERE {expression}&#8221;. The second is the data we want to update and what we want to update it with. Pretty simple, right?</p>
<p><strong>Indexing data</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Create a unique index<br />
$sql = &#8220;ALTER TABLE `$db`.`$tbl` ADD UNIQUE `login` (`login`)&#8221;;<br />
$qry = mysql_query($sql, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Create a unique index<br />
$col-&gt;ensureIndex(array(&#8220;login&#8221; =&gt; 1), array(&#8220;unique&#8221; =&gt; true, &#8220;dropDups&#8221; =&gt; true));<br />
[/php]</p>
<p>MongoDB has method for creating index name &#8220;ensureIndex&#8221;. The first parameter is an array of what we want to index and the value is ether 1 or -1. 1 means that the index will sort the data for this in an ascending manor, while -1 will sort it in a descending manor. The second parameter are extra options. In this example I tell it to make what ever I&#8217;m indexing as a unique index, that way I don&#8217;t end up with multiple &#8220;jsmith&#8221; entries. Also, I&#8217;ve told it to drop any documents that have duplicates of the data in the &#8220;login&#8221; &#8220;column&#8221;. Another note is that &#8220;columns&#8221; in MongoDB should be called &#8220;elements&#8221;, since we are really dealing with arrays.</p>
<p>Lets make sure our index is working shall we?<br />
<em>MongoDb</em></p>
<p>[php]<br />
// Test our unique index<br />
try<br />
{<br />
$doc  = array(&#8216;login&#8217; =&gt; &#8216;jsmith&#8217;, &#8216;password&#8217; =&gt; &#8216; 5f4dcc3b5aa765d61d8327deb882cf99&#8242;, &#8216;email&#8217; =&gt; &#8216;jsmith@example.com&#8217;);<br />
$col-&gt;insert($doc, true);<br />
}<br />
catch(MongoCursorException $e)<br />
{<br />
echo &#8216;Could not insert document. Double check values.&lt;br /&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>If all works, we should get an error message.</p>
<p><strong>Limiting Results</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Limits<br />
$sql = &#8220;SELECT * FROM `$tbl` LIMIT 1&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows &#8211; Limit by 1:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;<br />
}<br />
}<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Limits<br />
$res = $col-&gt;find()-&gt;limit(1);</p>
<p>echo &#8216;All documents &#8211; Limited to 1:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p><strong>Offsetting</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Limits<br />
$sql = &#8220;SELECT * FROM `$tbl` OFFSET 1 LIMIT 1&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows &#8211; Limit by 1 &#8211; Offset by 1:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Offsets<br />
$res = $col-&amp;gt;find()-&amp;gt;skip(1)-&amp;gt;limit(1);</p>
<p>echo &#8216;All documents &#8211; Limited to 1, Offset by 1:&lt;br/ &gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
&lt;/pre&gt;<br />
[/php]</p>
<p>To offset a your query start point, we used the method &#8220;skip&#8221; with an integer value to create the offset.</p>
<p><strong>Sorting</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Sorting<br />
$sql = &#8220;SELECT * FROM `$tbl` ORDERBY `login` DESC&#8221;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All rows &#8211;  Sorted by login descending:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;<br />
}while(&#8211;$cnt &gt; 0);<br />
}<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Sorting<br />
$res = $col-&gt;find()-&gt;sort(array(&#8216;login&#8217; =&gt; -1));</p>
<p>echo &#8216;All documents &#8211; Sorted by login descending:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>Here we used the sort method, told it what element to sort on and which direction, -1 being descending. The record for &#8220;psmith&#8221; should show up first. A word of caution here, there is a 4MB limit if sorting on non-indexed element.</p>
<p><strong>Advanced Queries</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Advanced queries<br />
// Add new column<br />
$sql = &#8220;ALTER `$db`.`$tbl` ADD COLUMN `age` INT UNSIGNED&#8221;;<br />
mysql_query($sql, $link);</p>
<p>// Add values<br />
$sql = &#8220;UPDATE `$tbl` SET `age` = 40 WHERE `login` = &#8216;jsmith&#8217;&#8221;;<br />
mysql_query($sql, $link);</p>
<p>$sql = &#8220;UPDATE `$tbl` SET `age` = 24 WHERE `login` = &#8216;psmith&#8217;&#8221;;<br />
mysql_query($sql, $link);</p>
<p>// Query for anyone under 30<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` &lt; 30&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone under 30:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}</p>
<p>// Query for anyone over 30<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` &gt; 30&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone over 30:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}</p>
<p>// Query from anyone 25 and over<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` &gt;= 25&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone 25 and over:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}<br />
// Query for anyone 25 and under<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` &lt;= 25&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone 25 and under:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}</p>
<p>// Query for anyone not 40<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` != 40&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone not 30:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}</p>
<p>// Query for anyone 20-50<br />
$sql = &#8220;SELECT * FROM `$tbl` WHERE `age` &gt;= 20 AND `age` &lt;= 50&#8243;;<br />
$qry = mysql_query($sql, $link);<br />
$cnt = mysql_num_rows($qry);</p>
<p>echo &#8216;All documents &#8211; Anyone 20-50:&lt;br/&gt;&#8217;;</p>
<p>if($cnt &gt; 0)<br />
{<br />
do<br />
{<br />
$row = mysql_fetch_assoc($qry);</p>
<p>echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($row);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
}<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Advanced queries<br />
// Add a new element and value<br />
$col-&gt;update(array(&#8216;login&#8217; =&gt; &#8216;jsmith&#8217;), array(&#8216;$set&#8217; =&gt; array(&#8216;age&#8217; =&gt; 40)));<br />
$col-&gt;update(array(&#8216;login&#8217; =&gt; &#8216;psmith&#8217;), array(&#8216;$set&#8217; =&gt; array(&#8216;age&#8217; =&gt; 24)));</p>
<p>// Confirm<br />
$res = $col-&gt;find();</p>
<p>echo &#8216;All documents &#8211; Confirming age element:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for anyone under 30<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$lt&#8217; =&gt; 30)));</p>
<p>echo &#8216;All documents &#8211; Anyone under 30:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for anyone over 30<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$gt&#8217; =&gt; 30)));</p>
<p>echo &#8216;All documents &#8211; Anyone over 30:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query from anyone 25 or over<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$gte&#8217; =&gt; 25)));</p>
<p>echo &#8216;All documents &#8211; Anyone 25 or older:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for anyone 25 and under<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$lte&#8217; =&gt; 25)));</p>
<p>echo &#8216;All documents &#8211; Anyone 25 or younger:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for anyone not 40<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$ne&#8217; =&gt; 40)));</p>
<p>echo &#8216;All documents &#8211; Anyone not 40:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}</p>
<p>// Query for anyone 20-50<br />
$res = $col-&gt;find(array(&#8216;age&#8217; =&gt; array(&#8216;$gte&#8217; =&gt; 20, &#8216;$lte&#8217; =&gt; 50)));</p>
<p>echo &#8216;All documents &#8211; Anyone 20-50:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>With MongoDB you can do &#8220;&lt;,&lt;=, &gt;, &gt;=&#8221; conditional operator based queries. Only thing is that you can&#8217;t just use &#8220;&lt;,&lt;=, &gt;, &gt;=&#8221; in your constraints, you have to use MongoDB&#8217;s version. Those are &#8220;$lt&#8221; (less than), &#8220;$lte&#8221; (less than or equal), &#8220;$gt&#8221; (greater than), &#8220;$gte&#8221; (greater than or equal). Yes, you need the dollar sign. Other conditional operators are &#8220;$ne&#8221; (not equal to), &#8220;$in&#8221; (like MySQL&#8217;s IN statement), &#8220;$nin&#8221; (NOT IN), &#8220;$mod&#8221; (Modulo operation), &#8220;$all&#8221; (like in, but all values much be matched to a document),  &#8220;$size&#8221; (Match of number of elements), &#8220;$exists&#8221; (element exists), &#8220;$type&#8221; (matches element type &#8211; int, string, etc) and there are couple more.</p>
<p><strong>Deleting a Row / Docuement</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Delete a row<br />
$sql = &#8220;DELETE FROM `$tbl` WHERE `login` = &#8216;psmith&#8217;&#8221;<br />
mysql_query($sql, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Delete a document<br />
$col-&gt;remove(array(&#8216;age&#8217; =&gt; 24), array(&#8216;justOne&#8217; =&gt; true, &#8216;safe&#8217; =&gt; true));</p>
<p>// Confirm delete<br />
$res = $col-&gt;find();</p>
<p>echo &#8216;All documents:&lt;br/&gt;&#8217;;</p>
<p>foreach($res as $doc)<br />
{<br />
echo &#8216;&lt;pre&gt;&#8217;;<br />
print_r($doc);<br />
echo &#8216;&lt;/pre&gt;&#8217;;<br />
}<br />
[/php]</p>
<p>Here we use the &#8220;remove&#8221; method. First argument has the constraints and the second tell it to only remove one item and also to run a &#8220;safe&#8221; query.</p>
<p><strong>Dropping a Table / Collection</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Drop table<br />
$sql = &#8220;DROP TABLE `$db`.`$tbl`&#8221;;<br />
mysql_query($sql, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Drop collection<br />
$col-&gt;drop();<br />
[/php]</p>
<p><strong>Dropping a database</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Drop DB<br />
$sql = &#8220;DROP DATABASE `$db`&#8221;;<br />
mysql_query($sql, $link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Drop DB<br />
$db-&gt;drop();<br />
[/php]</p>
<p><strong>Disconnect</strong><br />
<em>MySQL</em></p>
<p>[php]<br />
// Disconnect<br />
mysql_close($link);<br />
[/php]</p>
<p><em>MongoDB</em></p>
<p>[php]<br />
// Disconnect<br />
$link-&gt;close();<br />
[/php]</p>
<p>Until next time, when I will go over more stuff, happy coding.</p>
<p>Sources:<br />
<a href="http://www.php.net/manual/en/book.mongo.php" target="_blank">PHP.net</a>, <a href="http://www.mongodb.org/display/DOCS/Home" target="_blank">MongoDB</a></p>
<p><a href="http://www.dealtaker.com/blog/2010/06/22/php-mongodb-sitting-in-a-tree-part-2/">Part 2</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/05/12/php-mongodb-sitting-in-a-tree-part-1/feed/</wfw:commentRss>
		<slash:comments>31</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 8</title>
		<link>http://www.dealtaker.com/our-blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/#comments</comments>
		<pubDate>Fri, 30 Apr 2010 15:55:25 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[Modules]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2169</guid>
		<description><![CDATA[Welcome to the eighth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over modules. Before we get into views, we&#8217;ll want to update the [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the eighth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on</a>. In this tutorial we will be going over modules.</p>
<p><span id="more-2169"></span></p>
<p>Before we get into views, we&#8217;ll want to update the KO3 code base. Go in to &#8220;application&#8221; directory and rename your &#8220;bootstrap.php&#8221; to &#8220;bootstrap.bak.php&#8221;. Now point your browser to </a><a href="http://kohanaframework.org/download">http://kohanaframework.org/download</a> (Yes there is a new site), download the latest stable (3.0.4.2), open it and extract everything inside the &#8220;kohana&#8221; folder to &#8220;mykohana3&#8243;. Once you have done that, delete or rename the &#8220;install.php&#8221; in your &#8220;mykohana3&#8243; folder. Next, delete the  &#8220;bootstrap.php&#8221; file in the &#8220;application&#8221; folder and rename the &#8220;bootstrap.bak.php&#8221; to &#8220;bootstrap.php&#8221;.</p>
<p>So what is a module? A module is pretty much just a plug in. It can extend the core, give you whole new section to your project (IE. blogs and forums), or just give you a set of classes that are available globally. So lets jump right in!</p>
<p>Add a new directory to the &#8220;modules&#8221; directory and name it &#8220;fortune&#8221;. In the &#8220;module/fortune&#8221; directory add the following directories &#8220;classes&#8221; and &#8220;views&#8221;. In &#8220;/module/fortune/classes&#8221; create a folder named &#8220;kohana&#8221;. In &#8220;/module/fortune/views&#8221; create a folder named &#8220;fortune&#8221;. So you should have a directory that looks something like this:<br />
[php]<br />
modules<br />
+&#8211; fortune<br />
     |&#8211; classes<br />
     |    +&#8211; kohana<br />
     +&#8211; views<br />
          +&#8211; fortune<br />
[/php]<br />
Create a new file in &#8220;/module/fortune/classes/&#8221; named &#8220;fortune.php&#8221; and put the following into it:<br />
[php]<br />
&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);<br />
class Fortune extends Kohana_Fortune{}<br />
[/php]<br />
This is pretty simple. Just extends another class. If you&#8217;ve gone through the code base for KO3, this will probably look familiar. Now lets create the main class file, so open a new file and put the following into it:<br />
[php]<br />
&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>/**<br />
 * Fortune Cookie Module<br />
 */<br />
class Kohana_Fortune<br />
 {<br />
    // Merged configuration settings<br />
    protected $config  = array(&#8216;view&#8217; =&gt; &#8216;fortune/default&#8217;);<br />
    protected $fortune = &quot;&quot;;</p>
<p>    /**<br />
     * Creates a new Fortune object.<br />
     *<br />
     * @return Forune<br />
     */<br />
    public static function factory(array $config = array())<br />
     {<br />
        return new Fortune($config);<br />
     }</p>
<p>    public function __construct(array $config = array())<br />
     {<br />
        // Overwrite system defaults with application defaults<br />
        $this-&gt;config = $this-&gt;config_group() + $this-&gt;config;<br />
     }</p>
<p>    /**<br />
     * Retrieves a fortune config group from the config file. One config group can<br />
     * refer to another as its parent, which will be recursively loaded.<br />
     *<br />
     * @param  STRING fortune config group; &quot;default&quot; if none given<br />
     * @return ARRAY  config settings<br />
     */<br />
    public function config_group($group = &#8216;default&#8217;)<br />
     {<br />
        // Load the fortune config file<br />
        $config_file     = Kohana::config(&#8216;fortune&#8217;);</p>
<p>        // Initialize the $config array<br />
        $config          = array(&#8216;group&#8217; =&gt; (string)$group);</p>
<p>        // Recursively load requested config groups<br />
        while(isset($config['group']) &amp;&amp; isset($config_file-&gt;$config['group']))<br />
         {<br />
           // Temporarily store config group name<br />
           $group   = $config['group'];<br />
           unset($config['group']);</p>
<p>           // Add config group values, not overwriting existing keys<br />
           $config += $config_file-&gt;$group;<br />
         }</p>
<p>        // Get rid of possible stray config group names<br />
        unset($config['group']);</p>
<p>        // Return the merged config group settings<br />
        return $config;<br />
     }</p>
<p>    /**<br />
     * Randomly pick a fortune<br />
     *<br />
     * @return STRING fortune text<br />
     */<br />
     public function getFortune()<br />
      {<br />
         // Stolen from: http://fortunes.cat-v.org/plan_9/<br />
         $fortunes      = array(&#8217;2 is always smaller than 3, even for large values of 2.&#8217;,<br />
                                &#8216;A penny saved is a political breakthrough.&#8217;,<br />
                                &#8216;Avoid reality at all costs.&#8217;,<br />
                                &#8216;Bad taste is timeless.&#8217;);</p>
<p>         $this-&gt;fortune = $fortunes[array_rand($fortunes, 1)];<br />
      }</p>
<p>    /**<br />
     * Renders the fortune.<br />
     *<br />
     * @param  MIXED   string of the view to use, or a Kohana_View object<br />
     * @return STRING  fortune output (HTML)<br />
     */<br />
    public function render($view = NULL)<br />
     {<br />
        if($view === NULL)<br />
         {<br />
           // Use the view from config<br />
           $view = $this-&gt;config['view'];<br />
         }</p>
<p>        if(!$view instanceof Kohana_View)<br />
         {<br />
            // Load the view file<br />
            $view = View::factory($view);<br />
         }</p>
<p>        $this-&gt;getFortune();</p>
<p>        // Pass on the whole Fortune object<br />
        return $view-&gt;set(get_object_vars($this))-&gt;set(&#8216;page&#8217;, $this)-&gt;render();<br />
     }</p>
<p>    /**<br />
     * Renders the fortune.<br />
     *<br />
     * @return STRING fortune output (HTML)<br />
     */<br />
    public function __toString()<br />
     {<br />
        return $this-&gt;render();<br />
     }<br />
 }<br />
[/php]<br />
Save this as &#8220;fortune.php&#8221; in &#8220;/modules/fortune/classes/kohana&#8221;. For the most part this looks like a simple Kohana core. We have 2 protected properties, config and fortune. The config property is for, well, a configuration. We only use the view configuration value here. The fortune property is hopefully the land that my house sits on&#8230; er&#8230; It is used to store a single fortune for our output.</p>
<p>Next we have our factory method so we can do the factory pattern. Then we have our constructor which pulls in a configuration from the config variable and recreates the config property with default configurations from a file, set array element and from what has been passed to it with the help of the next method called &#8220;config_group&#8221;.</p>
<p>The heart of this class is the getFortune method. I cheated here and used an array instead of creating a model and pulling stuff from the db. So I pull a random element and place it in our fortune property. Next up is the render method. This just runs the getFortune method and then renders the view. The last one, __toString calls the render method.</p>
<p>Create a new file and put the following into it:<br />
[php]<br />
&lt;div style=&quot;width: 250px; height: 52px; vertical-align: middle; display: table-cell; text-align: center; border: 1px solid #CCCCCC; border-right-color: #666666; border-bottom-color: #666666;&quot;&gt;<br />
  &lt;p&gt;&lt;?php echo $fortune;?&gt;&lt;/p&gt;<br />
&lt;/div&gt;<br />
[/php]<br />
Save this as &#8220;default.php&#8221; under &#8220;/modules/fortune/views/fortune/default.php&#8221;. Pretty simple. You might notice that I&#8217;m echoing out $fortune, which happens to the protected property in our class. In the render method, we pass all the properties to the view. Makes things simple.</p>
<p>Next up is to edit a couple files. Open up the &#8220;/application/bootstrap.php&#8221; file and locate the section with &#8220;Kohana::modules&#8221; in it. Now replace that with:<br />
[php]Kohana::modules(array(// &#8216;auth&#8217;       =&gt; MODPATH.&#8217;auth&#8217;,       // Basic authentication<br />
                      // &#8216;codebench&#8217;  =&gt; MODPATH.&#8217;codebench&#8217;,  // Benchmarking tool<br />
                      &#8216;database&#8217;   =&gt; MODPATH.&#8217;database&#8217;,   // Database access<br />
                      // &#8216;image&#8217;      =&gt; MODPATH.&#8217;image&#8217;,      // Image manipulation<br />
                      // &#8216;orm&#8217;        =&gt; MODPATH.&#8217;orm&#8217;,        // Object Relationship Mapping<br />
                      // &#8216;pagination&#8217; =&gt; MODPATH.&#8217;pagination&#8217;, // Paging of results<br />
                      // &#8216;userguide&#8217;  =&gt; MODPATH.&#8217;userguide&#8217;,  // User guide and API documentation<br />
                      &#8216;fortune&#8217;    =&gt; MODPATH.&#8217;fortune&#8217;,<br />
                     ));[/php]<br />
We&#8217;ve added the new fortune module and enabled it in our system here. Now open the the &#8220;/application/views/pages/ko3.php&#8221; file and add the following to the bottom of it.<br />
[php]<br />
&lt;?php echo Fortune::factory();?&gt;<br />
[/php]</p>
<p>Now if you point your browser to &#8220;http://yourserver/mykohana3/ko3/&#8221; you should see the fortune at the bottom!</p>
<p>Until next time, when I go over including external libraries, happy coding.</p>
<p><a href="http://www.dealtaker.com/blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/">Part 7</a> | <a href="http://www.dealtaker.com/blog/2010/06/02/kohana-php-3-0-ko3-tutorial-part-9/">Part 9</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/feed/</wfw:commentRss>
		<slash:comments>24</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 7</title>
		<link>http://www.dealtaker.com/our-blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/#comments</comments>
		<pubDate>Fri, 26 Mar 2010 09:03:06 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[Helpers]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2082</guid>
		<description><![CDATA[Welcome to the seventh part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, . In this tutorial we will be going over helpers. So what is a helper? The Kohana 2.0 documents defines helpers as: Helpers are simply â€śhandyâ€ť functions that help [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the seventh part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, <a>. In this tutorial we will be going over helpers.<br />
<span id="more-2082"></span><br />
So what is a helper? The Kohana 2.0 documents defines helpers as:</a></p>
<p><a></p>
<blockquote cite="http://docs.kohanaphp.com/general/helpers"><p>Helpers are simply â€śhandyâ€ť functions that help you with development.</p>
<p>Helpers are similar to library methods, but there is a subtle difference. With a library, you have to create an instance of the library&#8217;s class to use its methods. Helpers are declared as static methods of a class, so there is no need to instantiate the class. You can think of them as â€śglobal functionsâ€ť.</p>
<p>As with libraries, the helper classes are automatically loaded by the framework when they are used, so there is no need to load them yourself.</p></blockquote>
<p></a></p>
<p><a>So pretty much they are static methods that &#8220;help&#8221; with doing common things, IE: working with arrays or URLs. Kohana comes with quite a few &#8220;helpers&#8221; prepackaged. </a><a href="http://kohanaframework.org/3.0/guide/api/" target="_blank">See the KO3 API Guide</a>.</p>
<p>So how do we make a &#8220;helper&#8221;? Fire up your IDE and let get coding. The first thing we should is create a new directory called &#8220;helper&#8221; under &#8220;/application/classes&#8221;. Create a new file and put the following into it:<br />
[php]&lt;?php<br />
class Helper_MyUrl<br />
{<br />
public static function SEOIt($str)<br />
{<br />
$str = preg_replace(array(&#8216;/s/&#8217;, &#8216;/[$.+!*'(),"]/&#8217;), array(&#8216;-&#8217;, &#8220;&#8221;), $str);<br />
return $str;<br />
}<br />
}[/php]<br />
Save to this as &#8220;myurl.php&#8221; under &#8220;/application/classes/helper&#8221;. Now open &#8220;/application/views/pages/ko3.php&#8221; and add the following to the bottom and save it.:<br />
[php]  &lt;br /&gt;&lt;?php echo Helper_MyUrl::SEOIt(&#8216;This Is a string!!!&#8217;);?&gt;[/php]<br />
So if you point your browser to &#8220;http://yourserver/mykohana3/ko3/&#8221;, you should see &#8220;ThisIsastring&#8221; at the bottom. Pretty simple!</p>
<p>Until next time, when I go over modules, happy coding.</p>
<p>Sources used: <a href="http://docs.kohanaphp.com/" target="_blank">Kohana PHP 2.x Docs</a>, <a href="http://forum.kohanaframework.org/" target="_blank">Kohana Forums</a></p>
<p><a href="http://www.dealtaker.com/blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/">Part 6</a> | <a href="http://www.dealtaker.com/blog/2010/04/30/kohana-php-3-0-ko3-tutorial-part-8/">Part 8</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/feed/</wfw:commentRss>
		<slash:comments>21</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 6</title>
		<link>http://www.dealtaker.com/our-blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/#comments</comments>
		<pubDate>Wed, 03 Mar 2010 17:02:12 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[routes]]></category>
		<category><![CDATA[routing]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=2037</guid>
		<description><![CDATA[Welcome to the sixth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over Routes and Routing. What is Routing? Well Routing is nothing more [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the sixth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on</a>. In this tutorial we will be going over Routes and Routing.<br />
<span id="more-2037"></span><br />
What is Routing? Well Routing is nothing more than taking a request, looking at it and directing it to the right place. Think of it Kohana&#8217;s version of the .htaccess file. So why would you want to use routing you might ask. Well there are so many reasons why you would want to use routing, so I&#8217;m not going to over all of them, but give you a couple examples of how to setup routes for different scenarios.</p>
<p>So what does a route look like? Open up &#8220;bootstrap.php&#8221; located in &#8220;application/&#8221;, and scroll down to the comment that says:<br />
[php]/**<br />
 * Set the routes. Each route must have a minimum of a name, a URI and a set of<br />
 * defaults for the URI.<br />
 */[/php]<br />
The next thing you should see is something like this:<br />
[php]Route::set(&#8216;default&#8217;, &#8216;(&lt;controller&gt;(/&lt;action&gt;(/&lt;id&gt;)))&#8217;)<br />
     -&gt;defaults(array(&#8216;controller&#8217; =&gt; &#8216;welcome&#8217;,<br />
                      &#8216;action&#8217;     =&gt; &#8216;index&#8217;));[/php]<br />
So we have a route setup initially for us, but what does this tell us. If we break it down we get:<br />
1. Set a route with the name &#8220;default&#8221;<br />
2. &#8216;((/(/)))&#8217;  Tells the route the controller, action and id are optional. The parentheses are containers that denote if an option is opional or not and the less / greater than symbols tell the the router to assign the value to the variable of the value in-between the less / greater than symbols.<br />
3. The default values for the controller is &#8220;welcome&#8221; and the default value for the action is &#8220;index&#8221;</p>
<p>So when we go to &#8220;http://yourserver/mykohana3/&#8221;, the router see that we have not set a controller nor an action in our URL. It will go through the route rules that we have set to find a match. In our case, we have a default route, which is named &#8220;default&#8221;. This default route will replace the missing controller with &#8220;welcome&#8221; and the action with &#8220;index&#8221; and the rest of the system will process it. Simple so far?</p>
<p>If we were to to &#8220;http://yourserver/mykohana3/hmvc/&#8221;, the router would notice that the controller has been set, but not the action. The router then assign the default action value of &#8220;index&#8221; for us.</p>
<p>You might have noticed the optional &#8220;id&#8221; in the route. This I would say is pretty commonly used and we could pass an ID on to our action. Example:<br />
&#8220;http://yourserver/mykohana3/hmvc/index/111&#8243;. Of course this example will not do anything special since we didn&#8217;t set up any logic to handle it. Now what if we browsed to &#8220;http://yourserver/mykohana3/hmvc/index/111/222&#8243;? We get an error. This is because our router rule is strict and says we can only route for upwards of 3 segments (action/controller/id) and the /222 creates a fourth. To over come this we can though in a overflow handler rule into our default route.<br />
[php]Route::set(&#8216;default&#8217;, &#8216;(&lt;controller&gt;(/&lt;action&gt;(/&lt;id&gt;(/&lt;overflow&gt;))))&#8217;, array(&#8216;overflow&#8217; =&gt; &#8216;.*?&#8217;))<br />
     -&gt;defaults(array(&#8216;controller&#8217; =&gt; &#8216;welcome&#8217;,<br />
                      &#8216;action&#8217;     =&gt; &#8216;index&#8217;));[/php]<br />
If you save the &#8216;bootstrap.php&#8217; file and reload, you should not see an error now.</p>
<p>You might notice that we&#8217;ve added in an extra array &#8220;array(&#8216;overflow&#8217; =&gt; &#8216;.*?&#8217;)&#8221;. This basically sets up a REGEX rules for the &#8220;overflow&#8221; option which tell the router to capture everything, including slashes and pass it as our &#8220;overflow&#8221; argument. So if slashes are captured, the router will no longer try to split out the options on slashes.</p>
<p>Lets go back to this &#8220;id&#8221; option we see in our route. Well, anything we put in that area will be passed to our action. If our id&#8217;s are integers, we might want to error out if we pass a non integer. One way we can do this is with the route:<br />
[php]Route::set(&#8216;default&#8217;, &#8216;(&lt;controller&gt;(/&lt;action&gt;(/&lt;id&gt;(/&lt;overflow&gt;))))&#8217;, array(&#8216;id&#8217; =&gt; &#8216;[[:digit:]]{1,}&#8217;, &#8216;overflow&#8217; =&gt; &#8216;.*?&#8217;))<br />
     -&gt;defaults(array(&#8216;controller&#8217; =&gt; &#8216;welcome&#8217;,<br />
                      &#8216;action&#8217;     =&gt; &#8216;index&#8217;));[/php]<br />
So now if you were go to: &#8220;http://yourserver/mykohana3/hmvc/index/xxx&#8221;, you would get an error about not being able to find the route, which should translate to a 404 in a production environment. Of course you could check the id for an integer inside the action action and decide how to handle it.</p>
<p>Now lets create a route that isn&#8217;t our default route. Add the following to the &#8220;bootstrap.php&#8221; before the default route:<br />
[php]Route::set(&#8216;monkeys&#8217;, &#8216;monkeys(/&lt;action&gt;(/&lt;id&gt;))&#8217;)<br />
     -&gt;defaults(array(&#8216;controller&#8217; =&gt; &#8216;ko3&#8242;,<br />
                      &#8216;action&#8217;     =&gt; &#8216;posts&#8217;));[/php]<br />
Now if you were open up &#8220;http://yourserver/mykohana3/monkeys&#8221;, you would end up with the &#8220;posts&#8221; action of the &#8220;ko3&#8243; controller. If you notice, the &#8220;monkeys&#8221; in the controller spot is not enclosed by parentheses, meaning that is not optional. So the router see &#8220;monkeys&#8221; in the controller spot and triggers this rule set.</p>
<p>Here&#8217;s an example you might want to use to serve up some static pages (Totally stole this from the <a href="http://kerkness.ca/wiki/doku.php?id=routing:routing_basics" target="_blank">Unofficial Kohana 3.0 Wiki</a>):<br />
[php]Route::set(&#8216;static&#8217;, &#8216;&lt;page&gt;&#8217;, array(&#8216;page&#8217; =&gt; &#8216;about|faq|locations&#8217;))<br />
	   -&gt;defaults(array(&#8216;controller&#8217; =&gt; &#8216;page&#8217;,<br />
                      &#8216;action&#8217;     =&gt; &#8216;static&#8217;));[/php]<br />
There is a bit more you could do with routes, but the above should cover the majority of things you would want to use route for.</p>
<p>Until next time when we will go over modules and helpers, happy coding.<br />
Sources used: <a href="http://kerkness.ca/wiki/doku.php" target="_blank">Unofficial Kohana 3 Wiki</a></p>
<p>&lt;&lt;<a href="http://www.dealtaker.com/blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/">Part 5</a> | <a href="http://www.dealtaker.com/blog/2010/03/26/kohana-php-3-0-ko3-tutorial-part-7/">Part 7</a>&gt;&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/feed/</wfw:commentRss>
		<slash:comments>20</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 5</title>
		<link>http://www.dealtaker.com/our-blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/#comments</comments>
		<pubDate>Thu, 25 Feb 2010 17:44:23 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[HMVC]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=1991</guid>
		<description><![CDATA[Welcome to the fifth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over the &#8220;H&#8221; in HMVC. So most of you know what MVC [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the fifth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over the &#8220;H&#8221; in HMVC.<br />
<span id="more-1991"></span><br />
So most of you know what MVC is, but might not know about HMVC. HMVC extends MVC by allowing a controller to call on other controllers on do stuff, or doing stuff in an Hierarchical manor. Think modules that can work by themselves or in a groups. If that didn&#8217;t help, <a href="http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/">check out this article about the Hierarchical-Model-View-Controller pattern</a>.</p>
<p>So we&#8217;ve been design pages with a single controller as a page, with some actions that pulls data in from a model and populates a parts of a view to give us a complete browser page. Well, that can get messy with all the model calls and extra snippets we bring into with views. Using HMVC, we can organize our code a lot better, make more things reusable and with the way Kohana PHP 3 does HMVC, we can even make our application scale by calling out to other servers to give us our content for a section.</p>
<p>Lets go ahead and make a new controller:<br />
[php]&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>class Controller_Hmvc extends Controller_DefaultTemplate<br />
{<br />
public function action_index()<br />
{<br />
// Set meta data<br />
$this-&gt;template-&gt;title            = &#8216;Kohana 3.0 HMVC Test&#8217;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8216;PHP, Kohana, KO3, Framework, HMVC&#8217;;<br />
$this-&gt;template-&gt;meta_description = &#8216;A test of of the KO3 framework HMVC pattern&#8217;;</p>
<p>// Fill in content<br />
$ko3                              = array();<br />
$ko3['posts']                     = Request::factory(&#8216;posts/getposts&#8217;)-&gt;execute()-&gt;response;</p>
<p>$this-&gt;template-&gt;content          = View::factory(&#8216;pages/hmvc&#8217;, $ko3);<br />
}</p>
<p>}[/php]<br />
Save this as &#8220;hmvc.php&#8221; in &#8220;application/classes/controller&#8221;. The above should look pretty familiar. One line should stand out:<br />
[php]$ko3['posts'] = Request::factory(&#8216;posts/getposts&#8217;)-&gt;execute()-&gt;response;[/php]<br />
This line is where the HMVC magic happen. This will call the controller &#8220;posts&#8221; an invoke the action &#8220;getposts&#8221;, execute the code and get the response. We take the response and save it to the array which we fill the view with.</p>
<p>Talking about views, let make our view for this controller:<br />
[php]&lt;?php echo $posts;?&gt;[/php]<br />
Save this as &#8220;hmvc.php&#8221; in &#8220;application/views/pages/&#8221;</p>
<p>Now for the &#8220;posts&#8221; controller:<br />
[php]&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>class Controller_Posts extends Controller<br />
{<br />
public function action_index()<br />
{<br />
}</p>
<p>public function action_getposts()<br />
{<br />
// Load model<br />
$posts           = new Model_Post();</p>
<p>// Fill content array for view with last 10 posts.<br />
$content          = array();<br />
$content['posts'] = $posts-&gt;getLastTenPosts();</p>
<p>// Render and output.<br />
$this-&gt;request-&gt;response   = View::factory(&#8216;pages/hmvc_posts&#8217;, $content);<br />
}<br />
}[/php]<br />
Save this as &#8220;posts.php&#8221; in &#8220;application/classes/controller&#8221;. Once again, pretty straight forward. This controller extends the basic controller, so nifty template or anything and is pretty much what we did in the last tutorial.</p>
<p>Now for the view.<br />
[php]&lt;?php foreach($posts as $post):?&gt;<br />
&lt;h1&gt;&lt;?php echo $post['title'];?&gt;&lt;/h1&gt;<br />
&lt;?php echo $post['post'];?&gt;<br />
&lt;hr /&gt;<br />
&lt;?php endforeach;?&gt;[/php]<br />
Save this as &#8220;hmvc_posts.php&#8221; under &#8220;applications/views/pages&#8221;.</p>
<p>Now if you point your browser to: &#8220;http://yourserver/mykohana3/hmvc&#8221;, you should see a couple posts up on the screen.</p>
<p>We can achieve the same result by calling the controller from the view instead of the controller. This is helpful for keeping it simple. So one template used all over the place, you wouldn&#8217;t have to worry about having to putting in all the HMVC stuff into the controllers that used that template.</p>
<p>Change the &#8220;hmvc&#8221; controller to look like this:<br />
[php]&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>class Controller_Hmvc extends Controller_DefaultTemplate<br />
{<br />
public function action_index()<br />
{<br />
// Set meta data<br />
$this-&gt;template-&gt;title            = &#8216;Kohana 3.0 HMVC Test&#8217;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8216;PHP, Kohana, KO3, Framework, HMVC&#8217;;<br />
$this-&gt;template-&gt;meta_description = &#8216;A test of of the KO3 framework HMVC pattern&#8217;;</p>
<p>// Fill in content<br />
$ko3                              = array();<br />
$ko3['content']                   = &#8216;Hello there!&#8217;;<br />
$this-&gt;template-&gt;content          = View::factory(&#8216;pages/hmvc&#8217;, $ko3);<br />
}<br />
}[/php]<br />
Now edit the &#8220;hmvc&#8221; view to look like this:<br />
[php]&lt;?php echo $content;?&gt;&lt;br/&gt;<br />
&lt;?php echo Request::factory(&#8216;posts/getposts&#8217;)-&gt;execute()-&gt;response;?&gt;[/php]<br />
This is example is pretty simple and we could expand this to use parameters to deliver the data in different ways, say, simple html, full html, xml, json, etc..</p>
<p>Sources used: <a href="http://kerkness.ca/wiki/doku.php" target="_blank">Unofficial Kohana 3 Wiki</a>, <a href="http://techportal.ibuildings.com/2010/02/22/scaling-web-applications-with-hmvc/" target="_blank">iBuildings: Scaling Web Applications with HMVC</a></p>
<p>&lt;&lt;<a href="http://www.dealtaker.com/our-blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/">Part 4</a> | <a href="http://www.dealtaker.com/our-blog/2010/03/03/kohana-php-3-0-ko3-tutorial-part-6/">Part 6</a>&gt;&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/feed/</wfw:commentRss>
		<slash:comments>29</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 4</title>
		<link>http://www.dealtaker.com/our-blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/</link>
		<comments>http://www.dealtaker.com/our-blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/#comments</comments>
		<pubDate>Mon, 01 Feb 2010 13:20:40 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[models]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=1921</guid>
		<description><![CDATA[Welcome to the fourth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over how work with models. So you might be asking your self, [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the fourth part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read any of previous parts yet, I would search for and read them before going on. In this tutorial we will be going over how work with models.<br />
<span id="more-1921"></span><br />
So you might be asking your self, what is a model. From <a href="http://docs.kohanaphp.com/">Kohana&#8217;s 2.x documents</a>:</p>
<blockquote cite="http://docs.kohanaphp.com/general/models"><p>Models are classes designed to work with information given by or asked for by the controller. For example, you have a guestbook, the controller will ask the model to retrieve the last ten entries, the model returns those entries to the controller who passes them on to a view. The controller might also send new entries to the model, update existing ones or even delete some.</p></blockquote>
<p>Simply a model is a data handler and manipulator.</p>
<p>The first thing we want to do is identify where and what the data is. Is it an XML feed, CSV, JSON, DB or something else? Well I&#8217;m going to make it easy. We are going to deal with our friend MySQL for this. The next step is to setup a MySQL DB connection.</p>
<p>Lets open up your bootstrap file (&#8220;application/bootstrap.php&#8221;) and find the like that reads &#8220;// &#8216;database&#8217;   =&gt; MODPATH.&#8217;database&#8217;,   // Database access&#8221; and uncomment it. The whole block of code should look like the following:<br />
[php]Kohana::modules(array(<br />
// &#8216;auth&#8217;       =&gt; MODPATH.&#8217;auth&#8217;,       // Basic authentication<br />
// &#8216;codebench&#8217;  =&gt; MODPATH.&#8217;codebench&#8217;,  // Benchmarking tool<br />
&#8216;database&#8217;   =&gt; MODPATH.&#8217;database&#8217;,   // Database access<br />
// &#8216;image&#8217;      =&gt; MODPATH.&#8217;image&#8217;,      // Image manipulation<br />
// &#8216;orm&#8217;        =&gt; MODPATH.&#8217;orm&#8217;,        // Object Relationship Mapping<br />
// &#8216;pagination&#8217; =&gt; MODPATH.&#8217;pagination&#8217;, // Paging of results<br />
// &#8216;userguide&#8217;  =&gt; MODPATH.&#8217;userguide&#8217;,  // User guide and API documentation<br />
));[/php]<br />
Now save this. We&#8217;ve basically told the bootstrap to load the database module, but we need to configure it. Copy the &#8220;database.php&#8221; from &#8220;modules/database/config/&#8221; to &#8220;application/config/&#8221;. Open up the &#8220;application/config/database.php&#8221; file and edit accordingly to your settings. Mine looks like this:<br />
[php]&lt;?php defined(&#8216;SYSPATH&#8217;) OR die(&#8216;No direct access allowed.&#8217;);</p>
<p>return array<br />
(<br />
&#8216;default&#8217; =&gt; array<br />
(<br />
&#8216;type&#8217;       =&gt; &#8216;mysql&#8217;,<br />
&#8216;connection&#8217; =&gt; array(<br />
/**<br />
* The following options are available for MySQL:<br />
*<br />
* string   hostname<br />
* integer  port<br />
* string   socket<br />
* string   username<br />
* string   password<br />
* boolean  persistent<br />
* string   database<br />
*/<br />
&#8216;hostname&#8217;   =&gt; &#8216;localhost&#8217;,<br />
&#8216;username&#8217;   =&gt; &#8216;root&#8217;,<br />
&#8216;password&#8217;   =&gt; FALSE,<br />
&#8216;persistent&#8217; =&gt; FALSE,<br />
&#8216;database&#8217;   =&gt; &#8216;mykohana3&#8242;,<br />
),<br />
&#8216;table_prefix&#8217; =&gt; &#8221;,<br />
&#8216;charset&#8217;      =&gt; &#8216;utf8&#8242;,<br />
&#8216;caching&#8217;      =&gt; FALSE,<br />
&#8216;profiling&#8217;    =&gt; TRUE,<br />
),<br />
&#8216;alternate&#8217; =&gt; array(<br />
&#8216;type&#8217;       =&gt; &#8216;pdo&#8217;,<br />
&#8216;connection&#8217; =&gt; array(<br />
/**<br />
* The following options are available for PDO:<br />
*<br />
* string   dsn<br />
* string   username<br />
* string   password<br />
* boolean  persistent<br />
* string   identifier<br />
*/<br />
&#8216;dsn&#8217;        =&gt; &#8216;mysql:host=localhost;dbname=mykohana3&#8242;,<br />
&#8216;username&#8217;   =&gt; &#8216;root&#8217;,<br />
&#8216;password&#8217;   =&gt; FALSE,<br />
&#8216;persistent&#8217; =&gt; FALSE,<br />
),<br />
&#8216;table_prefix&#8217; =&gt; &#8221;,<br />
&#8216;charset&#8217;      =&gt; &#8216;utf8&#8242;,<br />
&#8216;caching&#8217;      =&gt; FALSE,<br />
&#8216;profiling&#8217;    =&gt; TRUE,<br />
),<br />
);[/php]<br />
Save this. You&#8217;ll notice I have a database setup just this tutorial series named &#8220;mykohana3&#8243;, you might want to do the same if you can. Now that we have saved, let get a table set up. Here&#8217;s the SQL:<br />
[php]CREATE TABLE `posts` (<br />
`id` MEDIUMINT(8) UNSIGNED NOT NULL AUTO_INCREMENT,<br />
`title` VARCHAR(255) DEFAULT NULL,<br />
`post` TEXT,<br />
PRIMARY KEY  (`id`)<br />
) ENGINE=INNODB DEFAULT CHARSET=utf8 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=DYNAMIC;[/php]<br />
Go run that in your favorite MySQL client, I personally like <a href="http://code.google.com/p/sqlyog/">SQLYog</a>. You might have noticed the &#8220;charset&#8221; is set to &#8220;utf8&#8243; in both the config and create table statement. This will allow us to deal with i18n (Internationalization) stuff later on.</p>
<p>So let create a new folder under &#8220;application/classes&#8221; named &#8220;model&#8221;. Now lets create a new file and make it look like this:<br />
[php]&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>class Model_Post extends Kohana_Model<br />
{<br />
/**<br />
* Get the last 10 posts<br />
* @return ARRAY<br />
*/<br />
public function getLastTenPosts()<br />
{<br />
$sql = &#8216;SELECT *&#8217;.&#8221;n&#8221;.<br />
&#8216;FROM   `posts`&#8217;.&#8221;n&#8221;.<br />
&#8216;ORDER BY `id` DESC&#8217;.&#8221;n&#8221;.<br />
&#8216;LIMIT  0, 10&#8242;;</p>
<p>return $this-&gt;_db-&gt;query(Database::SELECT, $sql, FALSE)<br />
-&gt;as_array();<br />
}<br />
}[/php]<br />
Save this as &#8220;post.php&#8221; under &#8220;application/classes/model/&#8221;. Here&#8217;s an line by line explaination of the code.<br />
[php]        $sql = &#8216;SELECT *&#8217;.&#8221;n&#8221;.<br />
&#8216;FROM   `posts`&#8217;.&#8221;n&#8221;.<br />
&#8216;ORDER BY `id` DESC&#8217;.&#8221;n&#8221;.<br />
&#8216;LIMIT  0, 10&#8242;;[/php]<br />
This is a basic MySQL statement that selects up to ten rows from the DB which are sorted by the &#8216;id&#8217; in a descending direction.<br />
[php]        return $this-&gt;_db-&gt;query(Database::SELECT, $sql, FALSE)<br />
-&gt;as_array();[/php]<br />
This return array of the result from a query. The &#8220;query&#8221; method in this example take 3 parameters. 1st being what type of query, our being select, we use the constant &#8220;Database::SELECT&#8221;. There are 3 others,  &#8220;Database::INSERT&#8221;,  &#8220;Database::UPDATE&#8221; and &#8220;Database::DELETE&#8221;. The &#8220;as_array()&#8221; will return an array of the results, no having to do &#8220;while($row = mysql_fetch_array())&#8221;.</p>
<p>Now that we have a model method, I&#8217;m sure we would want to put it use. Open up &#8220;ko3.php&#8221; in &#8220;/application/classes/controller&#8221; and lets add this into the class:<br />
[php]    public function action_posts()<br />
{<br />
$posts                            = new Model_Post();<br />
$ko3                              = array();<br />
$this-&gt;template-&gt;title            = &#8216;Kohana 3.0 Model Test&#8217;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8216;PHP, Kohana, KO3, Framework, Model&#8217;;<br />
$this-&gt;template-&gt;meta_description = &#8216;A test of of the KO3 framework Model&#8217;;<br />
$this-&gt;template-&gt;styles           = array();<br />
$this-&gt;template-&gt;scripts          = array();</p>
<p>// Get the last 10 posts<br />
$ko3['posts']                     = $posts-&gt;getLastTenPosts();<br />
$this-&gt;template-&gt;content          = View::factory(&#8216;pages/posts&#8217;, $ko3);</p>
<p>}[/php]<br />
Basically we&#8217;ve called our model&#8217;s &#8220;getLastTenPosts()&#8221; method and assigned it to an array which we pass to our view. Talking about views, open up a new file and put the following into it:<br />
[php]&lt;?php foreach($posts as $post):?&gt;<br />
&lt;h1&gt;&lt;?php echo $post['title'];?&gt;&lt;/h1&gt;<br />
&lt;?php echo $post['post'];?&gt;<br />
&lt;hr /&gt;<br />
&lt;?php endforeach;?&gt;[/php]<br />
Save to as &#8220;posts.php&#8221; under &#8220;application/views/pages/&#8221;. This view loops through the array we pass to it from the the controller and displays our posts from the DB. Wait, what? There&#8217;s no posts in our DB! Here&#8217;s some SQL you can run to populate your table:<br />
[php]insert  into `posts`(`id`,`title`,`post`) values (1,&#8217;Test Post&#8217;,'This is some sample text.&#8217;);<br />
insert  into `posts`(`id`,`title`,`post`) values (2,&#8217;Another post&#8217;,'Some more text&#8217;);[/php]<br />
Now if you point your browser to &#8220;http://yourserver/mykohana3/ko3/posts&#8221; you should see the two entries on the screen.</p>
<p>Now lets add something to put data into our DB. Open the the post model (&#8220;application/classes/model/post.php&#8221;) and add this to the class:<br />
[php]    public function addPost($title, $post)<br />
{<br />
$sql = sprintf(&#8216;INSERT INTO `posts`&#8217;.&#8221;n&#8221;.<br />
&#8216;SET         `title` = %s,&#8217;.&#8221;n&#8221;.<br />
&#8216;            `post`  = %s&#8217;,<br />
$this-&gt;_db-&gt;escape($title),<br />
$this-&gt;_db-&gt;escape($post));</p>
<p>$this-&gt;_db-&gt;query(Database::INSERT, $sql, FALSE);<br />
}[/php]<br />
The above is a pretty simple insert, but you may notice we are using &#8220;$this-&gt;_db&gt;escape()&#8221;. This will wrap your strings in quotes and escape it content for you. Save it and now go back to the &#8220;posts.php&#8221; from &#8220;application/views/pages&#8221; and replace the contents with:<br />
[php]&lt;?php if(!empty($msg)):?&gt;<br />
&lt;?php echo $msg.&#8217;&lt;br /&gt;&#8217;;?&gt;<br />
&lt;?php endif;?&gt;<br />
&lt;?php foreach($posts as $post):?&gt;<br />
&lt;h1&gt;&lt;?php echo $post['title'];?&gt;&lt;/h1&gt;<br />
&lt;?php echo $post['post'];?&gt;<br />
&lt;hr /&gt;<br />
&lt;?php endforeach;?&gt;<br />
&lt;form method=&#8221;POST&#8221; action=&#8221;&lt;?php echo url::base();?&gt;ko3/posts/&#8221;&gt;<br />
&lt;table&gt;<br />
&lt;tr&gt;<br />
&lt;td&gt;<br />
Title<br />
&lt;/td&gt;<br />
&lt;td&gt;<br />
&lt;input type=&#8221;text&#8221; name=&#8221;title&#8221; style=&#8221;border: 1px solid #000000;&#8221;/&gt;<br />
&lt;/td&gt;<br />
&lt;/tr&gt;<br />
&lt;tr&gt;<br />
&lt;td&gt;<br />
Post<br />
&lt;/td&gt;<br />
&lt;td&gt;<br />
&lt;textarea cols=&#8221;20&#8243; rows=&#8221;5&#8243; name=&#8221;post&#8221;&gt;&lt;/textarea&gt;<br />
&lt;input type=&#8221;submit&#8221; name=&#8221;submit&#8221; value=&#8221;Submit&#8221;/&gt;<br />
&lt;/td&gt;<br />
&lt;/table&gt;<br />
&lt;/form&gt;[/php]<br />
Save that and open the ko3 controller back up (&#8220;application/classes/controller/ko3.php&#8221;) and lets add a new method to it.<br />
[php]    private function _addPost($title, $post_content)<br />
{<br />
// Load model<br />
$post = new Model_Post();</p>
<p>// Check required fields<br />
if(empty($title))<br />
{<br />
return(array(&#8216;error&#8217; =&gt; &#8216;Please enter a title.&#8217;));<br />
}<br />
elseif(empty($post_content))<br />
{<br />
return(array(&#8216;error&#8217; =&gt; &#8216;Please enter a post.&#8217;));<br />
}</p>
<p>// Add to DB<br />
$post-&gt;addPost($title, $post_content);<br />
return TRUE;<br />
}[/php]<br />
The above code is pretty much a middle man between the &#8220;action_posts&#8221; and the model that saves the post it self. Lets go back to the &#8220;action_posts&#8221; method and make it look like this:<br />
[php]   public function action_posts()<br />
{<br />
// Load model<br />
$posts                            = new Model_Post();</p>
<p>// Setup view stuff<br />
$ko3                              = array();<br />
$this-&gt;template-&gt;title            = &#8216;Kohana 3.0 Model Test&#8217;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8216;PHP, Kohana, KO3, Framework, Model&#8217;;<br />
$this-&gt;template-&gt;meta_description = &#8216;A test of of the KO3 framework Model&#8217;;<br />
$this-&gt;template-&gt;styles           = array();<br />
$this-&gt;template-&gt;scripts          = array();<br />
$ko3['msg']                       = &#8220;&#8221;;</p>
<p>// Handle POST<br />
if($_POST)<br />
{<br />
$ret = $this-&gt;_addPost((isset($_POST['title']) ? $_POST['title'] : &#8220;&#8221;),<br />
(isset($_POST['post']) ? $_POST['post']  : &#8220;&#8221;));</p>
<p>if(isset($ret['error']))<br />
{<br />
$ko3['msg'] = $ret['error'];<br />
}<br />
else<br />
{<br />
$ko3['msg'] = &#8216;Saved.&#8217;;<br />
}<br />
}</p>
<p>// Get the last 10 posts<br />
$ko3['posts']                     = $posts-&gt;getLastTenPosts();</p>
<p>// Display it.<br />
$this-&gt;template-&gt;content          = View::factory(&#8216;pages/posts&#8217;, $ko3);<br />
}[/php]<br />
Save this and reload your browser. Now you should see a pretty ugly form at bottom. Enter some stuff in and click the &#8220;submit&#8221; button. Your post should appear at the top along with the word &#8220;Saved&#8221;, this is if you entered stuff in both fields, if not you should see an error.</p>
<p>Before I end this tutorial, I want to go back to our little model for saving our posts. There are several ways to do queries in KO3, but want to quickly show you how you can use the query builder to do the same thing.<br />
[php]    public function addPost($title, $post)<br />
{<br />
DB::insert(&#8216;posts&#8217;, array(&#8216;title&#8217;,'post&#8217;))<br />
-&gt;values(array($title, $post))<br />
-&gt;execute();<br />
}[/php]<br />
That&#8217;s pretty simple! It does the same thing as the previous one, with less &#8220;hassle&#8221; There are advantages using the query builder method, like being able to convert between different DB types (MySQL to Oracle to what ever).</p>
<p>While I might not have gone over doing updates with your model, I thought I would give you a homework assignment to see if you can come up with you own update model for this. Until next time when we go over &#8220;H&#8221; in &#8220;HMVC&#8221;, happy coding.</p>
<p>Sources used: <a href="http://kerkness.ca/wiki/doku.php" target="_blank">Unofficial Kohana 3 Wiki</a>, <a href="http://docs.kohanaphp.com/" target="_blank">Kohana PHP 2.x Docs</a>, <a href="http://v3.kohanaphp.com/guide/api" target="_blank">KO3 API Guide</a></p>
<p>&lt;&lt;<a href="http://www.dealtaker.com/our-blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/">Part 3</a> | <a href="http://www.dealtaker.com/our-blog/2010/02/25/kohana-php-3-0-ko3-tutorial-part-5/">Part 5</a>&gt;&gt;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/feed/</wfw:commentRss>
		<slash:comments>57</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 3</title>
		<link>http://www.dealtaker.com/our-blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/</link>
		<comments>http://www.dealtaker.com/our-blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/#comments</comments>
		<pubDate>Wed, 30 Dec 2009 10:08:30 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[how-to]]></category>
		<category><![CDATA[howto]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[tutorial]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=1873</guid>
		<description><![CDATA[Welcome to the third part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read the first and/or second parts yet, I would click here and read them before going on. In this tutorial we will be going over how to create a template. In the last tutorial, we [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the third part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read the <a href="http://www.dealtaker.com/our-blog/2009/11/20/kohana-php-3-0-ko3-tutorial-part-1/" target="_blank">first</a> and/or <a href="http://www.dealtaker.com/our-blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/" target="_blank">second parts</a> yet, I would click here and read them before going on. In this tutorial we will be going over how to create a template.<br />
<span id="more-1873"></span><br />
In the last tutorial, we went over views and in this one we are going to extend the Controller classes which will allow us to create a template. A template, you might ask, is nothing more than a view that is more or less your base (X)HTML code. This will allow to keep things &#8220;DRY&#8221; in the view world. Before we get to putting code into a file, lets create a new directory under &#8220;/application/views/&#8221; named &#8220;templates&#8221;.  Now open up your favorite IDE and make a new file and put the following into it:<br />
[php]<br />
&lt;!DOCTYPE html PUBLIC &#8220;-//W3C//DTD XHTML 1.0 Transitional//EN&#8221;<br />
&#8220;http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd&#8221;&gt;<br />
&lt;html xmlns=&#8221;http://www.w3.org/1999/xhtml&#8221; xml:lang=&#8221;en&#8221; lang=&#8221;en&#8221;&gt;<br />
&lt;head&gt;<br />
&lt;meta http-equiv=&#8221;Content-type&#8221; content=&#8221;text/html; charset=UTF-8&#8243; /&gt;<br />
&lt;meta http-equiv=&#8221;Content-Language&#8221; content=&#8221;en-us&#8221; /&gt;<br />
&lt;title&gt;&lt;?php echo $title;?&gt;&lt;/title&gt;<br />
&lt;meta name=&#8221;keywords&#8221; content=&#8221;&lt;?php echo $meta_keywords;?&gt;&#8221; /&gt;<br />
&lt;meta name=&#8221;description&#8221; content=&#8221;&lt;?php echo $meta_description;?&gt;&#8221; /&gt;<br />
&lt;meta name=&#8221;copyright&#8221; content=&#8221;&lt;?php echo $meta_copywrite;?&gt;&#8221; /&gt;<br />
&lt;?php foreach($styles as $file =&gt; $type) { echo HTML::style($file, array(&#8216;media&#8217; =&gt; $type)), &#8220;n&#8221;; }?&gt;<br />
&lt;?php foreach($scripts as $file) { echo HTML::script($file, NULL, TRUE), &#8220;n&#8221;; }?&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;div id=&#8221;container&#8221;&gt;<br />
&lt;?php echo $header;?&gt;<br />
&lt;?php echo $content;?&gt;<br />
&lt;?php echo $footer;?&gt;<br />
&lt;/div&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;<br />
[/php]<br />
Save the above as &#8220;default.php&#8221; in your &#8220;/application/views/templates/&#8221; folder.</p>
<p>As you can see the above pretty much looks like a view we have done before, a bit more expanded. I will go over the &#8220;foreach&#8221; a little bit later. Unlike a view, this will most likely be used by all of your project. Since we will point to this file for our template, or shell, this will reduce the amount of code you have to put in each view, keeping thing separated, easier to maintain, or basically &#8220;DRY&#8221;.</p>
<p>Now that we have a template, our system isn&#8217;t going to do anything with it until well tell it to use it. So lets go back to our IDE and create a new file and put the following into it:<br />
[php]<br />
&lt;?php<br />
defined(&#8216;SYSPATH&#8217;) or die(&#8216;No direct script access.&#8217;);</p>
<p>class Controller_DefaultTemplate extends Controller_Template<br />
{<br />
public $template = &#8216;templates/default&#8217;;</p>
<p>/**<br />
* Initialize properties before running the controller methods (actions),<br />
* so they are available to our action.<br />
*/<br />
public function before()<br />
{<br />
// Run anything that need ot run before this.<br />
parent::before();</p>
<p>if($this-&gt;auto_render)<br />
{<br />
// Initialize empty values<br />
$this-&gt;template-&gt;title            = &#8221;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8221;;<br />
$this-&gt;template-&gt;meta_description = &#8221;;<br />
$this-&gt;template-&gt;meta_copywrite   = &#8221;;<br />
$this-&gt;template-&gt;header           = &#8221;;<br />
$this-&gt;template-&gt;content          = &#8221;;<br />
$this-&gt;template-&gt;footer           = &#8221;;<br />
$this-&gt;template-&gt;styles           = array();<br />
$this-&gt;template-&gt;scripts          = array();<br />
}<br />
}</p>
<p>/**<br />
* Fill in default values for our properties before rendering the output.<br />
*/<br />
public function after()<br />
{<br />
if($this-&gt;auto_render)<br />
{<br />
// Define defaults<br />
$styles                  = array(&#8216;assets/css/reset.css&#8217; =&gt; &#8216;screen&#8217;);<br />
$scripts                 = array(&#8216;http://ajax.googleapis.com/ajax/libs/jquery/1.3.2/jquery.min.js&#8217;);</p>
<p>// Add defaults to template variables.<br />
$this-&gt;template-&gt;styles  = array_reverse(array_merge($this-&gt;template-&gt;styles, $styles));<br />
$this-&gt;template-&gt;scripts = array_reverse(array_merge($this-&gt;template-&gt;scripts, $scripts));<br />
}</p>
<p>// Run anything that needs to run after this.<br />
parent::after();<br />
}<br />
}<br />
[/php]<br />
And save this as &#8220;defaulttemplate.php&#8221; under your &#8220;/application/classes/controller/&#8221; folder.</p>
<p>The above code extends the &#8220;Controller_Template&#8221; class and does three main things, initialize some properties (variables) to be accessable by our methods (actions) and appends default values to them and then gets associates them to our template variables before we render the final output to the screen. This is where the foreach() loop in the template comes into play. The foreach() loop uses a static method for the helper class &#8220;HTML&#8221; to <a href="http://v3.kohanaphp.com/guide/api/HTML#style" target="_blank">load CSS style sheets</a> and load JS files</a>. Both of these helper methods will iterate through an array and properly wrap it in the appropriate tag. They can take a path or a URL.</p>
<p>You might be wondering what a &#8220;Helper&#8221; is, so here is a quick definition from the Kohana PHP 2.x documents:</p>
<blockquote cite="http://docs.kohanaphp.com/general/helpers"><p>Helpers are simply &#8220;handy&#8221; functions that help you with development.</p>
<p>Helpers are similar to library methods, but there is a subtle difference. With a library, you have to create an instance of the library&#8217;s class to use its methods. Helpers are declared as static methods of a class, so there is no need to instantiate the class. You can think of them as &#8220;global functions&#8221;.</p>
<p>As with libraries, the helper classes are automatically loaded by the framework when they are used, so there is no need to load them yourself.</p></blockquote>
<p>OK, back on course. You might have noticed there is a reference to &#8220;assets/css/reset.css&#8221;, so lets go ahead and get that in place. In your root create a folder named &#8220;assets&#8221; and in that folder create one named &#8220;css&#8221;. For the actual &#8220;reset.css&#8221; file, I went to Serene Destiny and copied the code from the article titled &#8220;Create The Perfect CSS Reset&#8221; into a file and saved it as &#8220;reset.css&#8221; in the &#8220;assets/css/&#8221; folder. You might want to also set up some other folders within &#8220;/assets/&#8221;, maybe &#8220;images&#8221;, &#8220;js&#8221; and &#8220;files&#8221;. Basically the assets folder should be used to store and organize static files and such.</p>
<p>At this point, our application still doesn&#8217;t know what to do what we have done, so we need to modify our controller. So open &#8220;/application/classes/controller/ko3.php&#8221;.<br />
We want to change what class we are extending, so change the line:<br />
[php]class Controller_Ko3 extends Controller[/php]<br />
to:<br />
[php]lass Controller_Ko3 extends Controller_DefaultTemplate[/php]</p>
<p>We also need to change up our &#8220;index&#8221; action (action_index() method) to look like the following:<br />
[php]<br />
public function action_index()<br />
{<br />
$ko3_inner               = array();<br />
$ko3                     = array();<br />
$this-&gt;template-&gt;title   = &#8216;Kohana 3.0&#8242;;</p>
<p>View::set_global(&#8216;x&#8217;, &#8216;This is a global variable&#8217;);</p>
<p>$ko3_inner['content']    = &#8216;We have more data&#8217;;<br />
$ko3['content']          = &#8216;We have data&#8217;;<br />
$ko3['ko3_inner']        = View::factory(&#8216;blocks/ko3_inner&#8217;, $ko3_inner)<br />
-&gt;render();<br />
$this-&gt;template-&gt;content = View::factory(&#8216;pages/ko3&#8242;, $ko3);<br />
}<br />
[/php]<br />
Save it. Now you might noticed that we now have &#8220;$this-&gt;template-&gt;title   = &#8216;Kohana 3.0&#8242;;&#8221;, this will assign a value to our templates &#8220;title&#8221; variable. The next thing you might notice is the absence of the last &#8220;render()&#8221; method. The &#8220;factory()&#8221; method actually will &#8220;auto render&#8221; it to our template&#8217;s &#8220;content&#8221; variable. Pretty simple, yes?</p>
<p>There is something we should probably do before loading up the page, so load up the &#8220;ko3.php&#8221; view file located in &#8220;application/views/pages/&#8221;. You might noticed that we have all the &#8220;shell&#8221; code in our view, so lets remove it. What you should only have in the view file is this:<br />
[php]<br />
&lt;h1&gt;This is my first view&lt;/h1&gt;<br />
&lt;?php echo $content;?&gt;<br />
&lt;?php echo $ko3_inner; ?&gt;<br />
&lt;br/&gt;&lt;?php echo $x;?&gt;<br />
[/php]</p>
<p>Now if you load it up, you should see that page has a title of &#8220;Kohana 3.0&#8243; and the page should pretty much look the same as it did from the last tutorial. If you view the source thou, it would look much different. But you might be wondering about the other variables in the template and what to do with them. OK, let go back and edit our &#8220;index&#8221; action again. Make it look like:<br />
[php]<br />
public function action_index()<br />
{<br />
$ko3_inner                        = array();<br />
$ko3                              = array();<br />
$this-&gt;template-&gt;title            = &#8216;Kohana 3.0&#8242;;<br />
$this-&gt;template-&gt;meta_keywords    = &#8216;PHP, Kohana, KO3, Framework&#8217;;<br />
$this-&gt;template-&gt;meta_description = &#8216;A test of of the KO3 framework&#8217;;<br />
$this-&gt;template-&gt;styles           = array(&#8216;assets/css/red.css&#8217; =&gt; &#8216;screen&#8217;);<br />
$this-&gt;template-&gt;scripts          = array(&#8216;assets/js/jqtest.js&#8217;);</p>
<p>View::set_global(&#8216;x&#8217;, &#8216;This is a global variable&#8217;);</p>
<p>$ko3_inner['content']             = &#8216;We have more data&#8217;;<br />
$ko3['content']                   = &#8216;We have data&#8217;;<br />
$ko3['ko3_inner']                 = View::factory(&#8216;blocks/ko3_inner&#8217;, $ko3_inner)<br />
-&gt;render();<br />
$this-&gt;template-&gt;content          = View::factory(&#8216;pages/ko3&#8242;, $ko3);<br />
}<br />
[/php]<br />
Pretty simple. You will notice I didn&#8217;t fill in the header or footer. I&#8217;m sure you know what to do there. Hint: Render a view to that variable =). Another thing you might notice is that I have put in &#8220;assets/css/red.css&#8221; and &#8220;assets/css/jqtest.js&#8221;. Lets make those two files starting with &#8220;/assets/css/red.css&#8221;:<br />
[php]<br />
h1<br />
{<br />
color: #FF0000;<br />
}<br />
[/php]</p>
<p>Next &#8220;/assets/js/jqtest.js&#8221;:<br />
[php]<br />
$(&#8220;document&#8221;).ready(function()<br />
{<br />
alert(&#8216;Hello Kohana!&#8217;);<br />
});<br />
[/php]</p>
<p>Save them and refresh the site. You should see an alert pop up and the first line of text in red.</p>
<p>Today we have created a template file, extended a template controller and our controller use that template file. There is a lot of potential with what you could do with this already. So until next time when I will go over models, happy coding!<br />
Sources used: <a href="http://kerkness.ca/wiki/doku.php" target="_blank">Unofficial Kohana 3 Wiki</a>, <a href="http://docs.kohanaphp.com/" target="_blank">Kohana PHP 2.x Docs</a></p>
<p><a href="http://www.dealtaker.com/our-blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/">Part 2</a> | <a href="http://www.dealtaker.com/our-blog/2010/02/01/kohana-php-3-0-ko3-tutorial-part-4/">Part 4</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/feed/</wfw:commentRss>
		<slash:comments>48</slash:comments>
		</item>
		<item>
		<title>Kohana PHP 3.0 (KO3) Tutorial Part 2</title>
		<link>http://www.dealtaker.com/our-blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/</link>
		<comments>http://www.dealtaker.com/our-blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/#comments</comments>
		<pubDate>Mon, 07 Dec 2009 10:47:54 +0000</pubDate>
		<dc:creator>ellisgl</dc:creator>
				<category><![CDATA[DealTaker.com Updates]]></category>
		<category><![CDATA[framework]]></category>
		<category><![CDATA[KO3]]></category>
		<category><![CDATA[kohana]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[views]]></category>

		<guid isPermaLink="false">http://www.dealtaker.com/blog/?p=1835</guid>
		<description><![CDATA[Welcome to the second part in this series on how to develop with Kohana PHP V3 (KO3). If you haven&#8217;t read the first part, I would read it before going on. In this tutorial we will be going over how to develop views. Before we get into views, we&#8217;ll want to update the KO3 code [...]]]></description>
			<content:encoded><![CDATA[<p>Welcome to the second part in this series on how to develop with Kohana PHP V3 (<acronym title="Kohana PHP 3">KO3</acronym>). If you haven&#8217;t read the first part, I would <a href="http://www.dealtaker.com/our-blog/2009/11/20/kohana-php-3-0-ko3-tutorial-part-1/"> read it before going on</a>. In this tutorial we will be going over how to develop views.<br />
<span id="more-1835"></span><br />
Before we get into views, we&#8217;ll want to update the KO3 code base, So point your browser to <a href="http://dev.kohanaphp.com/projects/kohana3/files">http://dev.kohanaphp.com/projects/kohana3/files</a>, download it, open it and extract everything inside the &#8220;kohana&#8221; folder to &#8220;mykohana3&#8243;. Once you have done that, delete or rename the &#8220;install.php&#8221; in your &#8220;mykohana3&#8243; folder. Next, open up the &#8220;bootstrap.php&#8221; file in the &#8220;application&#8221; folder and change the following line:<br />
[php]Kohana::init(array(&#8216;base_url&#8217; =&gt; &#8216;/kohana/&#8217;));[/php]<br />
to<br />
[php]Kohana::init(array(&#8216;base_url&#8217;   =&gt; &#8216;/mykohana3/&#8217;,<br />
&#8216;index_file&#8217; =&gt; &#8221;));[/php]<br />
Now that we are updated to the latest and greatest, lets get right in to developing a view. Create a new folder within the &#8220;application&#8221; folder named &#8220;views&#8221; and inside the &#8220;views&#8221; folder, create another folder named &#8220;pages&#8221;. Now open up a new document in your editor and put the following in it:<br />
[php]&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Hello!&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;h1&gt;This is my first view&lt;/h1&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;[/php]<br />
Now save that in your &#8220;application/views/pages&#8221; as &#8220;ko3.php&#8221;. As you can tell, it&#8217;s a pretty simple HTML page with some PHP mixed in. Lets open the &#8220;ko3&#8243; controller (&#8220;application/classes/controller/ko3.php&#8221;). Replace the &#8220;action_index&#8221; class with the following:<br />
[php]    public function action_index()<br />
{<br />
$this-&gt;request-&gt;response = View::factory(&#8216;pages/ko3&#8242;);<br />
}[/php]<br />
Save it, and load up &#8220;http://yourserver/myfirstkohana3/&#8221; in your browser. You should see &#8220;This is my first view&#8221;. The code above is pretty simple, we use the &#8220;Facotry&#8221; method of the view class to load the file &#8220;application/views/pages/ko3.php&#8221;, renders it and outputs it. Not very exciting, so let go back to the view (&#8220;application/views/pages/ko3.php&#8221;) and add:<br />
[php]  &lt;?php echo $content;?&gt;[/php]<br />
After the &#8220;h1&#8243; tags. Your view should look like this:<br />
[php]&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Hello!&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;h1&gt;This is my first view&lt;/h1&gt;<br />
&lt;?php echo $content;?&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;[/php]<br />
If we were to refresh the browser, we would seen an exception error about an undefined variable. So let&#8217;s go ahead and fix that, by relating data to the view variable in our controller. So, change up &#8220;Action_Index&#8221; controller to look like this:<br />
[php]    public function action_index()<br />
{<br />
$view                       = View::factory(&#8216;pages/ko3&#8242;);<br />
$view-&gt;content              = &#8216;We have data!&#8217;;<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
Now if we refresh the browser, we should see &#8220;This is my first view&#8221; and under that &#8220;We have data!&#8221;. Lets explain the the code line by line.<br />
[php]$view = View::factory(&#8216;pages/ko3&#8242;);[/php]<br />
This load our view file (&#8220;application/views/pages/ko3.php&#8221;) into the view controller.<br />
[php]$view-&gt;content = &#8216;We have data!&#8217;;[/php]<br />
This assigns a variable for use by the view called &#8220;content&#8221; and we also assign data to that, in this case it&#8217;s &#8220;We have data!&#8221;<br />
[php]$this-&gt;request-&gt;response = $view-&gt;render();[/php]<br />
This renders the view and outputs it.</p>
<p>Simple enough, but there is another way of doing the above. We could have also done the following:<br />
[php]    public function action_index()<br />
{<br />
$data['content']         = &#8216;We have data!&#8217;;<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;, $data);<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
Basically the above use an array with element keys as the template variable names to assign the data. We are not done yet! There&#8217;s 2 more ways we can do the above.<br />
[php]    public function action_index()<br />
{<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;)<br />
-&gt;set(&#8216;content&#8217;, &#8216;We have data!&#8217;);</p>
<p>$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
The above used the set method of the view class, which you can use method chaining to set all your template variables. And now for forth way:<br />
[php]    public function action_index()<br />
{<br />
$content                 = &#8216;We have data!&#8217;;<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;)<br />
-&gt;bind(&#8216;content&#8217;, $content);<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
Now the above is using the bind method of the view class. Once again, this you can do method chaining here. This is a little bit different from the set method, since it will create a reference to a variable. So $content might equal &#8216;We have data!&#8217; when we bound the variable to the template variable, but could change later on, since we are referencing the variable $content in our controller, instead of assigning data to the template variable.</p>
<p>If we were to do the following:<br />
[php]    public function action_index()<br />
{<br />
$content                 = &#8216;We have data!&#8217;;<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;)<br />
-&gt;bind(&#8216;content&#8217;, $content);<br />
$content                 = &#8216;Our data changed&#8217;;<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
Instead of &#8220;We have data!&#8221; showing on our screen, we would have &#8220;Our data changed&#8221;.</p>
<p>Now lets do a view with in a view! Create a new folder in your &#8220;application/views/&#8221; named &#8220;blocks&#8221;. Lets create another view file named &#8220;ko3_inner.php&#8221; and put this in it:<br />
[php]  &lt;h3&gt;This is an inner view&lt;/h3&gt;[/php]<br />
Save that in your &#8220;application/views/blocks/&#8221; directory. Now lets edit the &#8220;ko3&#8243; view (&#8220;application/views/pages/ko3.php&#8221;) and add the following:<br />
[php]  &lt;?php echo View::factory(&#8216;blocks/ko3_inner&#8217;)-&gt;render(); ?&gt;[/php]<br />
You view should like this:<br />
[php]&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Hello!&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;h1&gt;This is my first view&lt;/h1&gt;<br />
&lt;?php echo $content;?&gt;<br />
&lt;?php echo View::factory(&#8216;blocks/ko3_inner&#8217;)-&gt;render(); ?&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;[/php]<br />
So if we run it we should see what we had before, then &#8220;This is an inner view&#8221;. This would be useful for static content, but we won&#8217;t be able to use variables directly to that view. So let fix this. Lets go back to our controller (&#8220;application/classes/controllers/ko3.php&#8221;) and edit the &#8220;Action_Index&#8221; method to look like this:<br />
[php]    public function action_index()<br />
{<br />
$ko3_inner['content']    = &#8216;We have more data&#8217;;<br />
$ko3['content']          = &#8216;We have data&#8217;;<br />
$ko3['ko3_inner']        = View::factory(&#8216;blocks/ko3_inner&#8217;, $ko3_inner)<br />
-&gt;render();<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;, $ko3);<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
This will render the view to a array that then is rendered by the main view. If you noticed I did the inner stuff first and went back to using array template variable setting style. Next we will need to edit the main view (&#8220;application/views/pages/ko3.php&#8221;). The line we put in before, we will change it to:<br />
[php]  &lt;?php echo $ko3_inner; ?&gt;[/php]<br />
The view should look like this:<br />
[php]&lt;html&gt;<br />
&lt;head&gt;<br />
&lt;title&gt;Hello!&lt;/title&gt;<br />
&lt;/head&gt;<br />
&lt;body&gt;<br />
&lt;h1&gt;This is my first view&lt;/h1&gt;<br />
&lt;?php echo $content;?&gt;<br />
&lt;?php echo $ko3_inner; ?&gt;<br />
&lt;/body&gt;<br />
&lt;/html&gt;[/php]<br />
And the last change we need to make is to the inner view (&#8220;application/views/blocks/ko3_inner.php&#8221;). Make it look like this:<br />
[php]  &lt;h3&gt;This is an inner view&lt;/h3&gt;<br />
&lt;?php echo $content;?&gt;[/php]<br />
If you refresh the browser after saving, you should now see the following:<br />
[php]This is my first view</p>
<p>We have data</p>
<p>This is an inner view</p>
<p>We have more data[/php]<br />
Pretty cool, now you can make your views more modular and reusable. Now lets get into making variables globally available to your views. Back to your controller (&#8220;applications/classes/controllers/ko3.php&#8221;) and edit the &#8220;Action_Index&#8221; method so the following is at the top of the method:<br />
[php]       View::set_global(&#8216;x&#8217;, &#8216;This is a global variable&#8217;);[/php]<br />
So now the method should look like this:<br />
[php]    public function action_index()<br />
{<br />
View::set_global(&#8216;x&#8217;, &#8216;This is a global variable&#8217;);</p>
<p>$ko3_inner['content']    = &#8216;We have more data&#8217;;<br />
$ko3['content']          = &#8216;We have data&#8217;;<br />
$ko3['ko3_inner']        = View::factory(&#8216;blocks/ko3_inner&#8217;, $ko3_inner)<br />
-&gt;render();<br />
$view                    = View::factory(&#8216;pages/ko3&#8242;, $ko3);<br />
$this-&gt;request-&gt;response = $view-&gt;render();<br />
}[/php]<br />
Now if you were to edit your views and add in:<br />
[php]  &lt;br/&gt;&lt;?php echo $x;?&gt;[/php]<br />
You should now see &#8220;This is a global variable&#8221; two times on the page. As you can see this could be very handy. Basically, we are using the static method of &#8220;set&#8221; from the view class, so it ends up being available to all view object instances. You can also use the static method of &#8220;bind&#8221; to reference variables. This could be handy for dry things &#8220;<acronym title="Don't Repeat Yourself">DRY</acronym>&#8221; and could be used in other place, like a contruct.</p>
<p>Untill next time, when I go over &#8220;templates&#8221; (advanced views and controller stuff), happy coding!<br />
Sources used: <a href="http://kerkness.ca/wiki/doku.php?id=template-site:create_the_template" target="_blank">Unofficial Kohana 3 Wiki</a></p>
<p><a href="http://www.dealtaker.com/our-blog/2009/11/20/kohana-php-3-0-ko3-tutorial-part-1/">Part 1</a> | <a href="http://www.dealtaker.com/our-blog/2009/12/30/kohana-php-3-0-ko3-tutorial-part-3/">Part 3</a></p>
]]></content:encoded>
			<wfw:commentRss>http://www.dealtaker.com/our-blog/2009/12/07/kohana-php-3-0-ko3-tutorial-part-2/feed/</wfw:commentRss>
		<slash:comments>37</slash:comments>
		</item>
	</channel>
</rss>

