In this article we are going to create Templates (with CodeIgniter) to keep our Views organized, and avoid repeating the same HTML code. Also we are going to learn about Doctrine Data Hydrators to see alternative ways to structure the data returned from the database.
"CodeIgniter and Doctrine from Scratch" Series:
Templates
What and Why?
The term Template might be a little ambiguous right now. Maybe you are already thinking of Views as Templates. Which is mostly true. However, there is a problem with using separate Views for every single page in our application. There will be headers, footers and other content that will be repeated everywhere. That’s why there is a need for actual Templates for our Views.
For example, we will be creating a new View for the Forum pages. It will look mostly the same as the home page, using the same css stylesheet, same header, same user control panel, etc… There will be other Views later that will be the same way. If we ever make a change to any of these common parts, we don’t want to go through every single View. There should be Views that have the common html output that we can quickly edit. Using Templates will enable us to do just that, and maybe more.
Creating a Template
Let’s create our first Template, which is actually going to be a View itself. The idea is to keep all the common elements in one file, and take out the variable stuff.
For example, take a look at this:

The content section is definitely going to change from page to page. Also, I would like to take out the user controls section, so it can have its own View. We’re going to replace these with some code instead.
- Create: system/application/views/template.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title><?php echo $title; ?> | CI+Doctrine Message Board</title>
<link rel="stylesheet" href="<?php echo base_url(); ?>css/style.css"
type="text/css" media="all">
</head>
<body>
<div class="<?php echo $container_css; ?> container">
<div class="user_controls">
<?php $this->load->view('user_controls'); ?>
</div>
<h1>CI+Doctrine Message Board</h1>
<?php $this->load->view($content_view); ?>
</div>
</body>
</html>
I have copied the contents of the Home View we created before, and replaced a few things.
Line 14: The code for the user_controls div will now be found in a View named user_controls.php.
Line 19: $content_view is the name of the View that will be loaded to fill up the content area. For example, we will use a View named forum_list for the home page. The controller will have to pass this variable.
Line 5: Now the page title can be passed as a $title variable.
Line 11: We can apply a different css class for the container div on every page.
As you can see, a View can load other Views. That’s a big help in creating Templates. Now, all Controllers can just load this Template View, and they can pass the name for a content View that will be loaded in the middle of the page.
Now let’s create the user_controls View.
- Create: system/application/views/user_controls.php
<?php if ($user = Current_User::user()): ?>
Hello, <em><?php echo $user->username; ?></em> <br/>
<?php echo anchor('logout', 'Logout'); ?>
<?php else: ?>
<?php echo anchor('login','Login'); ?> |
<?php echo anchor('signup', 'Register'); ?>
<?php endif; ?>
Basically it’s the same code as before, but now it is in its own View file.
Now let’s create the forum_list View.
- Create: system/application/views/forum_list.php
<?php foreach($categories as $category): ?>
<div class="category">
<h2><?php echo $category->title; ?></h2>
<?php foreach($category->Forums as $forum): ?>
<div class="forum">
<h3>
<?php echo anchor('forums/display/'.$forum->id, $forum->title) ?>
(<?php echo $forum->Threads[0]->num_threads; ?> threads)
</h3>
<div class="description">
<?php echo $forum->description; ?>
</div>
</div>
<?php endforeach; ?>
</div>
<?php endforeach; ?>
This code is also taken from the middle section of the old Home View. (I only made a small change to the link at line 10.)
Now we can get rid of the Home View file.
- Delete: system/application/views/home.php
Updating the Home Controller
This new Template needs to know what content to load, what the title of the page is, etc… So we need to update the Home Controller.
- Edit: system/application/controllers/home.php
<?php
class Home extends Controller {
public function index() {
$vars['categories'] = Doctrine_Query::create()
->select('c.title, f.title, f.description')
->addSelect('t.id, COUNT(t.id) as num_threads')
->from('Category c, c.Forums f')
->leftJoin('f.Threads t')
->groupBy('f.id')
->execute();
$vars['title'] = 'Home';
$vars['content_view'] = 'forum_list';
$vars['container_css'] = 'forums';
$this->load->view('template', $vars);
}
}
The changes are only the highlighted lines. We are now passing the page title, name of the content View, and a CSS class name for styling purposes. Then we load the View named ‘template’ instead of ‘home’ (since we deleted that one).
See the Results
The page should look exactly the same as before:

Later in this article we are going to use this Template to build the Forum page, that lists Threads in a Forum.
Data Hydrators (Doctrine)
Our Doctrine Models extend the Doctrine_Record class. We have been using instances of this class for representing and persisting the database records. Also, we have been using instances of the Doctrine_Collection class when dealing with multiple records (e.g. fetching multiple rows with DQL).
With Data Hydrators, we can work with the data in other structure formats. For example, with DQL we can have it return the results of a SELECT query as an Array instead of Doctrine_Collection.
HYDRATE_SCALAR
This returns an array similar to what you would get from doing raw SQL queries.
$category = Doctrine_Query::create()
->select('c.*, f.*')
->from('Category c, c.Forums f')
->where('c.id = ?', 1)
->setHydrationMode(Doctrine::HYDRATE_SCALAR)
->execute();
print_r($category);
/* output:
Array
(
[0] => Array
(
[c_id] => 1
[c_title] => The CodeIgniter Lounge
[f_id] => 1
[f_title] => Introduce Yourself!
[f_description] => Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.
[f_category_id] => 1
)
[1] => Array
(
[c_id] => 1
[c_title] => The CodeIgniter Lounge
[f_id] => 2
[f_title] => The Lounge
[f_description] => CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.
[f_category_id] => 1
)
)
*/
We fetched the Category with id 1, and it’s associated Forums. There were 2 Forums under that Category, so the result contains 2 rows of data.
If I run the same raw query from phpMyAdmin, it looks like this:

Note that the Category title is repeated in both rows, because of the nature of JOIN queries. That is also the case in the Array that was returned by DQL.
HYDRATE_ARRAY
This also returns an Array. But this time, it will have a nice multi-tier structure based on the Model relationships.
$category = Doctrine_Query::create()
->select('c.*, f.*')
->from('Category c, c.Forums f')
->where('c.id = ?', 1)
->setHydrationMode(Doctrine::HYDRATE_ARRAY)
->execute();
print_r($category);
/* output:
Array
(
[0] => Array
(
[id] => 1
[title] => The CodeIgniter Lounge
[Forums] => Array
(
[0] => Array
(
[id] => 1
[title] => Introduce Yourself!
[description] => Use this forum to introduce yourself to the CodeIgniter community, or to announce your new CI powered site.
[category_id] => 1
)
[1] => Array
(
[id] => 2
[title] => The Lounge
[description] => CodeIgniter's social forum where you can discuss anything not related to development. No topics off limits... but be civil.
[category_id] => 1
)
)
)
)
*/
Now we have a multidimensional Array. As you can see, this time the Category info is not repeated. And Forums is a sub-array under the Category. Also the keys of the array retain their original names, like ‘title’, instead of ‘c_title’.
Other Hydrators
By default Doctrine is using HYDRATE_RECORD, that causes objects to be returned. And there are a few other Hydrators you can read about here: http://www.doctrine-project.org/documentation/manual/1_2/en/data-hydrators
Why?
Hydrators can have certain performance benefits. Creating an array is faster than creating an object that has lots of overhead. And arrays take less memory too.
Also there are things you can do with arrays that you cannot do with a Doctrine object. If you prefer to handle the data as an array, Hydration is the way to go.
We are going to be using HYDRATE_ARRAY to fetch a list of Threads in the following sections, to demonstrate the usage.
CSS Changes
Before we move on, I want to make some CSS changes, so the new pages we build will be styled.
- Edit: css/style.css
body {
font-family: "Trebuchet MS",Arial;
font-size: 14px;
background-color: #212426;
color: #B9AA81;
}
a {color: #FFF;}
a:hover {color: #B9AA81;}
input, textarea, select {
font-family:inherit; font-size:inherit; font-weight:inherit;
}
.container {width: 720px; margin: auto;}
/* FORUMS -----------------------------------------*/
.forums.container h2 {
font-size: 16px;
color: #000;
padding: 5px 10px 5px 10px;
margin: 0px;
background-color: #BBB;
-moz-border-radius-topleft: 6px;
-moz-border-radius-topright: 6px;
-webkit-border-top-left-radius: 6px;
-webkit-border-top-right-radius: 6px;
}
.forums.container h3 {font-size: 15px; margin: 0px;}
.forums.container .category {margin-bottom: 40px;}
.forums.container .forum {border-bottom: 1px solid #666; padding: 10px;}
.forums.container .forum .description {font-size: 14px;}
/* FORUM -----------------------------------------*/
.forum.container h2 {
font-size: 16px;
color: #000;
padding: 5px 10px 5px 10px;
margin: 0px;
background-color: #BBB;
-moz-border-radius-topleft: 6px;
-moz-border-radius-topright: 6px;
-webkit-border-top-left-radius: 6px;
-webkit-border-top-right-radius: 6px;
}
.forum.container h3 {font-size: 15px; margin: 0px 0px 5px 0px;}
.forum.container .thread {border-bottom: 1px solid #666; padding: 10px;}
/* SIGNUP FORM ------------------------------------*/
#signup_form {margin: auto; width: 360px; font-size: 16px;}
#signup_form .heading {
text-align: center; font-size: 22px; font-weight: bold; color: #B9AA81;
}
#signup_form form {
background-color: #B9AA81;
padding: 10px;
-moz-border-radius: 8px;
-webkit-border-radius: 8px;
}
#signup_form form label {font-weight: bold; color: #11151E;}
#signup_form form input[type=text],input[type=password] {
width: 316px;
font-weight: bold;
padding: 8px;
border: 1px solid #FFF;
-moz-border-radius: 4px;
-webkit-border-radius: 4px;
}
#signup_form form input[type=submit] {
display: block;
margin: auto;
width: 200px;
font-size: 18px;
background-color: #FFF;
border: 1px solid #BBB;
}
#signup_form form input[type=submit]:hover {border-color: #000;}
#signup_form .error {font-size: 13px; color: #690C07; font-style: italic; }
/* USER CONTROL BOX -------------------------------*/
.user_controls {float: right; text-align: right;}
Forum Pages
Now, let’s use what we have, to build the Forum Pages. These pages will list all the Threads, in a given Forum.
Currently, on the Home page we have links like this:

We created these links, because we expect to have a Controller named ‘Forums’ that has a function named ‘Display’.
There is also an ID number at the end of the URL. That is passed to the Controller function as a parameter.
This Controller is supposed to load a page that lists all the Threads in that particular Forum.
Forums Controller
The skeleton structure first:
- Create: system/application/controllers/forums.php
<?php
class Forums extends Controller {
public function display($id) {
}
}
It looks like any other Controller. But this time we are expecting a parameter being passed to the display() method. The string that comes after /forums/display/ in the URL automatically gets passed as the first parameter to that method.
For example:
http://localhost/ci_doctrine/forums/display/1
Will call display(1) in the Forums Class. We are going to use that parameter as the Forum ID. Then we need to display the Forum page.
The Controller needs to obtain the following pieces of data, and pass them on to the View:
- The title of the Forum.
- Each Thread under the Forum.
- For each Thread, we need Thread title, create date, author name and number of replies.
Please note that the create date of the Thread is not part of the Thread Model (or table), because of the way we designed the Models. The first Post inside of the Thread carries a create date already, so we did not want to duplicate that data again. Same thing goes for the author (or user_id) of the Thread.
Now let’s add some code to make this happen:
<?php
class Forums extends Controller {
public function display($id) {
$forum = Doctrine::getTable('Forum')->find($id);
$vars['title'] = $forum['title'];
$vars['threads'] = $forum->getThreadsArray();
$vars['content_view'] = 'forum';
$vars['container_css'] = 'forum';
$this->load->view('template', $vars);
}
}
First we get an instance of the Forum object with the id $id. Then we create the array of variables that will be passed to the template View.
At line 9 you can see that I am attempting to call a method named getThreadsArray(). This does not exist yet, so let’s build it.
The idea is to create a method that can return all associated Threads in an array structure. But we also want each Thread to have information such as: number of replies, date (of first post), author of (first post).
- Edit: system/application/models/forum.php
<?php
class Forum extends Doctrine_Record {
// ...
public function getThreadsArray() {
$threads = Doctrine_Query::create()
->select('t.title')
->addSelect('p.id, (COUNT(p.id) - 1) as num_replies')
->addSelect('MIN(p.id) as first_post_id')
->from('Thread t, t.Posts p')
->where('t.forum_id = ?', $this->id)
->groupBy('t.id')
->setHydrationMode(Doctrine::HYDRATE_ARRAY)
->execute();
foreach ($threads as &$thread) {
$post = Doctrine_Query::create()
->select('p.created_at, u.username')
->from('Post p, p.User u')
->where('p.id = ?', $thread['Posts'][0]['first_post_id'])
->setHydrationMode(Doctrine::HYDRATE_ARRAY)
->fetchOne();
$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
$thread['created_at'] = $post['created_at'];
$thread['username'] = $post['User']['username'];
$thread['user_id'] = $post['User']['id'];
unset($thread['Posts']);
}
return $threads;
}
In the first DQL query:
Look at the from() call first. We are joining 2 Models (Thread, Post) because we need information from both.
Now look at the select() and addSelect() calls to see what we are getting:
- We select the title for every Thread.
- Then we select the number of Posts under each Thread by using COUNT(p.id), and subtract 1 to get number of replies.
- Finally we are also getting the ID for the first Post in that Thread using MIN(p.id). That will be used later in the second DQL query.
where(‘t.forum_id = ?’, $this->id) indicates which Forum id we are looking up.
groupBy(‘t.id’) groups the results by the Thread id, so the Post count works properly.
Then, we loop through the Threads to get some more data into each Thread:
In the first query we fetched the ID of the first post on each Thread and stored it as first_post_id. So this DQL query now gets data for that Post and also the username of its author by joining to the related User Model.
The rest of the code, I just arranged all the values in $thread so it has a nice structure when returned.
Just to give you a better picture, if you were to print_r $threads , it would look this this:
Array
(
[0] => Array
(
[id] => 1
[title] => Hi there!
[num_replies] => 1
[first_post_id] => 1
[created_at] => 2009-12-13 13:00:09
[username] => TestUser
[user_id] => 2
)
[1] => Array
(
[id] => 2
[title] => Greetings to all
[num_replies] => 0
[first_post_id] => 3
[created_at] => 2009-12-13 13:00:09
[username] => Foobar
[user_id] => 3
)
)
I did unset($thread['Posts']) in the code just to keep the resulting array cleaner.
Note that we used HYDRATE_ARRAY, like we talked about earlier. This allowed us to do 2 things that we couldn’t have done with Doctrine_Collection objects:
- When we foreach() the Threads, we are able to get each element by reference (&$thread), and modify them.
- We are able to create new array elements and assign values to them, like this:
$thread['username'] = $post['User']['username'];.
Now, we need to create the View that will be for the content section of this page.
Forum View
In the Controller we passed this: $vars['content_view'] = ‘forum’;
So the Template will look for a View named ‘forum’.
- Create: system/application/views/forum.php
<h2><?php echo $title ?></h2>
<?php foreach($threads as $thread): ?>
<div class="thread">
<h3>
<?php echo anchor('threads/display/'.$thread['id'], $thread['title']) ?>
(<?php echo $thread['num_replies']; ?> replies)
</h3>
<div>
Author: <em><?php echo anchor('profile/display/'.$thread['user_id'],
$thread['username']); ?></em>,
Posted: <em><?php echo $thread['created_at']; ?></em>
</div>
</div>
<?php endforeach; ?>
There is nothing new here. Just putting the data into HTML.
The Result
- Go to the Home Page and click on the first Forum.
You should see this:

Seems to be working!
Stay Tuned
We built another page in our project and explored two more important subjects along the way. Stay tuned for the next article, there is still plenty of work to do
Thank you for reading.

#1 by Aziz Light on December 13th, 2009
| Quote
This series is really getting better and better. Thanks a lot. I wish you will never stop.
Anyway Great Job.
By the way, I have yet to see a bad post by you (I wish I never will :p). Everything you post is plain awesome (even the articles on Nettuts), it’s amazing.
#2 by Burak on December 13th, 2009
| Quote
Thank you
#3 by Anonymous Coward on December 13th, 2009
| Quote
The part I like most about these tutorials is that they show how to develop the website with best practice. Too often have I written sites badly because I simply didn’t know any better. I’d specifically been waiting for todays chapter so I could see how you’re supposed to load views when there was more than 1 URL segment and you explained this perfectly. The concept of creating a forum is quite boring but the way in which you’re doing it is beautiful and this is also one of the only useful Doctrine tutorials out there.
Is there any chance of putting an estimate of when the next chapter will come out? You’re making the web development world a better place
#4 by Burak on December 14th, 2009
| Quote
I am just writing as time permits. It seems to be taking 5-10 days per chapter.
#5 by filip on December 13th, 2009
| Quote
Great tuts. Keep up the good work and positive energy.
I have noticed the way you have solved your layout. Maybe you can use
this http://github.com/sirfilip/codeigniter-goodies (renderer.php) it is a little script that i wrote. Also i found this http://williamsconcepts.com/ci/codeigniter/libraries/template/reference.html it references the same issue.
Anyway this is a great thing you are doing.
With doctrine and ci joined forces nothing can stay in their way.
#6 by Burak on December 13th, 2009
| Quote
I thought about using that Template library but I don’t want to introduce too many third party libraries into these tutorials, because I’m trying to keep them relatively basic.
Thanks for the suggestion though. I might use them another time.
#7 by Fatih on December 14th, 2009
| Quote
Agree with Aziz Light.Thanks again and again
#8 by Kamil Grzegorczyk on December 14th, 2009
| Quote
Great as always.
I’m using very similar idea – I’m just adding “if” conditions in main template file to be able to toggle on/off specific page areas
#9 by Carlos on December 14th, 2009
| Quote
Wow, amazing tut.
Thank you!!
#10 by Zack on December 14th, 2009
| Quote
Thanks again.
There is a really sick Dwoo library for CI too. Maybe later on in life, you could do a Dwoo tutorial. Or not..
#11 by yfi on December 18th, 2009
| Quote
I have a question that might be unrelated to this particular episode, but relevant to the series overall.
Hypothetical scenario: i would like to write a function that retrieves some user hashstring data and emails it to the user->email. So something like $user->emailRegistration()
Say I wanted to keep that function inside the model, because all the vars it needs live inside the model anyway and it could be something that can potentially be called from other controllers.
Can it be done from a doctrine_record model? Can we load CI libraries into doctrine_record models. How?
#12 by Burak on December 18th, 2009
| Quote
You can add functions (i.e. methods) to Doctrine Model classes.
To load a CI library, you would need to do this first:
$CI =& get_instance();
and use $CI instead of $this:
$CI->load->library(‘session’);
#13 by yfi on December 18th, 2009
| Quote
Cool ! Thanks so much. Great series, very addictive.
#14 by Michael Leadley on December 19th, 2009
| Quote
Thanks very much for these tutorials. I can’t believe how much I’ve learnt from 9 blog posts!
Keep up the good work.
#15 by Denes on December 19th, 2009
| Quote
Burak, your work is very cool! Thanks for sharing it with us.
By the way, I’m getting an error message when I click the first forum:
A PHP Error was encountered
Severity: Notice
Message: Undefined index: Posts
Filename: models/forum.php
Line Number: 38 ( ->where(‘p.id = ?’, $thread['Posts'][0]['first_post_id']) )
Did you know what can it be?
#16 by Burak on December 19th, 2009
| Quote
Oh, this is caused because of the new Doctrine version. Thanks for reporting that.
Here is how you fix it:
Change this line in models/forum.php:
->addSelect(‘(COUNT(p.id) – 1) as num_replies’)
to this:
->addSelect(‘p.id, (COUNT(p.id) – 1) as num_replies’)
I will go ahead and update the article too.
#17 by Denes on December 19th, 2009
| Quote
That’s it! Once more, thanks!
#18 by John on December 20th, 2009
| Quote
Like Michael Leadley said: I can’t believe how good these are!
Thank You very much.
#19 by Ansh on December 21st, 2009
| Quote
Burak, Nice tutorial . I have a question . how to load different view inside a div.
for eg
i have a design where i want left sidebar remain unload. but when i click any options there it load view in content area. using jquery or any other ????
#20 by Burak on December 21st, 2009
| Quote
You can load it with AJAX (with jQuery or other javascript tools).
#21 by Ansh on December 21st, 2009
| Quote
Cool, Thanks
#22 by Scott M on December 24th, 2009
| Quote
tip:
instead of
query..->setHydrationMode(Doctrine::HYDRATE_ARRAY)->execute();
you can use the shorter
query..->fetchArray();
also, you can convert a collection to a hydrated array at any time by calling ->toArray(); eg
$hydrated = $collection->toArray(true); #true as a param performs ‘deep’ hydration
#23 by Rob Muadib on December 29th, 2009
| Quote
Just wanted to weigh in with my support. Have found the tutorial series highly effective and useful for getting started with Codeigniter. Helps to see a ‘full-fledged’ page together, particularly the information on nesting views and advanced data handling.
I look forward to the rest of the series.
thank you
#24 by dnyce on December 30th, 2009
| Quote
This has been an extremely enlightening tutorial. I have honestly been checking your site every day in anticipation of Chapter 10.
One question I have, that may be great as an add – on to this series, how does one go about converting some of the current CI auth libraries to work with Doctrine? I am specifically interested in Redux Auth, and will probably attempt to convert it myself, but I thought you may have some basic insight as you seem to have taken a stab at a basic auth library with the “current_user” model.
Thanks again for a truly great tutorial, keep’m coming!
#25 by dnyce on January 3rd, 2010
| Quote
Burak,
Still waiting on Day 10. Can’t wait to see the out come. Disregard the comment about the other auth library integrations. Did some more research and came up with a more viable solution using the info you already provided.
#26 by Zack on December 30th, 2009
| Quote
Hoping for new chapters to start arriving again. Hope you’re having happy holidays.
#27 by Mwafrika on December 31st, 2009
| Quote
Very interesting tutorial article pieces, very well written as well. I have been able to run them “bug-free” – a feat in itself for a newbie
Thanks again and Happy Holidays.
Looking forward to the next piece.
#28 by Ken on January 2nd, 2010
| Quote
Burak, your series will be the first that I will subscribe to via RSS. I’ve been through so many other series, and this one by far is the most useful!
Seriously though, you need to put a “donate” button somewhere…I would drop you some cash in a heart beat as a “thank-you” for what you are teaching.
I know you trying to keep this simple (KISS) with CI + Doctrine…any chance of throwing some AJAX in there? You have the perfect foundation for it.
Thanks and happy holidays!
#29 by Angelo on January 2nd, 2010
| Quote
Burak, I came across your tutorial series on this when I was looking for a PHP ORM and got directed toward Doctrine. You have a great way of writing these tutorials – I already used CI quite extensively, but you helped me get a grip of some of the key features of Doctrine within a matter of hours. Thanks for that, and keep up the good work.
Angelo Hulshout
http://www.hulshout.nl
http://www.delphino-consultancy.nl
#30 by Lechuzo on January 3rd, 2010
| Quote
Thanks a lot Burat. I’ll be waiting for next chapter. Happy holidays!!
#31 by Marcello Romani on January 5th, 2010
| Quote
While I wait for the next article, I must say I’m amazed too that I’ve been able to run the tutorial from day 1 to day 9 without any problem (except those caused by me not understanding everything at first read).
Seems to me you have put a great effort to make sure every little detail is correct and working.
The best thing about this tuts is you’re not only teaching CodeIgniter and Doctrine, but also a sort of “how to build a website”, all in nice steps.
I have written some web apps with Perl, using the Catalyst MVC framework, the DBIx::Class ORM and Template::Toolkit, so while most concepts were familiar to me, I was already used to do things in a certain way. Your clear explanation and the fact that you don’t jump over “simple” things even where you get more advanced have helped me a lot.
Keep up the good work.
#32 by Patrick Fraley on January 8th, 2010
| Quote
Very nice set of articles. Thank you for putting those up. Now I do have a question, is it possible to have like revisions of changes implemented in doctrine? Like when I modify an entry in user, that the old values of an entry would be save in user_history or something like that. This is possible with ignited record by overloading its store method. Is this possible in doctrine? Maybe worth an article?
#33 by Burak on January 10th, 2010
| Quote
You can look into the Versionable behavior:
http://www.doctrine-project.org/documentation/manual/1_2/en/behaviors#core-behaviors:versionable
#34 by Patrick Fraley on January 11th, 2010
| Quote
Perfect, exactly what I was looking for. Thanks
#35 by dnyce on January 8th, 2010
| Quote
Hey Burak,
How would you pull CI’s Session library into Doctrine so that the two can work together seamlessly?
i.e. You could auto create the ci_sessions table when you are creating all the other necessary tables within your application.
This is tricky to me because you already have the CI Session Library that works perfectly well.
#36 by dnyce on January 8th, 2010
| Quote
Disregard,
I managed to figure this out after coding it up myself for a while.
#37 by tomotechi on October 13th, 2010
| Quote
Hi dnyce,
I just came across this issue myself, and solved it like this:
// added to the doctrine_tools controller that creates the tables // from the models, and loads fixtures function create_sessions_table() { $this->load->dbforge(); $fields = array( 'session_id' => array( 'type' => 'VARCHAR', 'constraint' => '32', ), 'user_agent' => array( 'type' => 'VARCHAR', 'constraint' => '255', 'null' => true, ), 'ip_address' => array( 'type' => 'VARCHAR', 'constraint' => '20', 'null' => true, ), 'last_activity' => array( 'type' => 'INT', 'constraint' => '12', 'null' => true, ), 'user_data' => array( 'type' => 'TEXT', ), ); $this->dbforge->add_field($fields); $this->dbforge->add_key('session_id', TRUE); $this->dbforge->create_table('ci_sessions'); } // then just use it in another method from that controller: $this->create_sessions_table();hope this helps!
#38 by Şaban Ulutaş on January 11th, 2010
| Quote
wonderful site.
kardeş eline koluna aklına sağlık
#39 by Jan Antl on January 13th, 2010
| Quote
big up!
Great series of tutorials.
I really enjoyed the reading.
I keep tuned
#40 by krzysko on January 14th, 2010
| Quote
Hi. This is very good tut man. I’ve got a question: when will be next lesson?:)
#41 by Yosy on January 14th, 2010
| Quote
Hey,
Great tutorials !!! Where are the video tutorials?
I saw only video tutorial for the first episode .
Yosy
#42 by Loren on January 16th, 2010
| Quote
I had a question about data hydration…. I keep finding myself with fairly simple models…
class Category extends Doctrine_Record {
public function setTableDefinition(){
$this->hasColumn(‘name’, ‘string’, 255);
}
}
so when I’m working with forms … especially drop downs I need an array thats of the format $myarray[$id] = $category_name. Is there a way I can get this format from my query and HYDRATE SCALAR? It seems like there has to be a way to do this but unfortunatly I’m not that great with php data types….
I find myself doing this a lot with doctrine and codeigniter so a better way than re-hashing all the data with something like
$categories = array();
foreach ($doctrine_categories as $c) {
$categories [$c->id] = $c->name;
}
would be awesome!!!
Thanks in advance!
-Loren
#43 by Burak on January 16th, 2010
| Quote
I found two separate sections in the manual on this subject:
http://www.doctrine-project.org/documentation/manual/1_2/en/dql-doctrine-query-language#indexby-keyword
(i think that works for HYDRATE_ARRAY but not HYDRATE_SCALAR)
and
http://www.doctrine-project.org/documentation/manual/1_2/en/component-overview#collection:key-mapping
#44 by Loren on January 16th, 2010
| Quote
Oh one thing I forgot… AWESOME TUTORIAL SERIES! thanks so much!
#45 by Michael on January 17th, 2010
| Quote
Getting this error since 6/7 any ideas?
Fatal error: Uncaught exception ‘Doctrine_Record_UnknownPropertyException’ with message ‘Unknown record property / related component “num_threads” on “Thread”‘ in C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Record\Filter\Standard.php:55 Stack trace: #0 C:\wamp\www\ci_doctrine\system\application\plugins\doctrine\lib\Doctrine\Record.php(1302)…
#46 by DynamiteN on January 19th, 2010
| Quote
love this series, cant wait for the next chapter to come, but still ahve that duplicate error from the signup chapter :/ , anyway good work , and keep ‘em commming
#47 by piyush on February 3rd, 2010
| Quote
Hi Burak, what would be the dql query for this
select * from table name where city_id=’$cityid ‘ and (status_id=1 or status_id=4 or status_id=7);
even i am not sure that it is correct mysql query.
actually my objective is to get all the records having cityid=’some_id’ and having status_id either 1 , 4 or 7.
Thanks
piyush
#48 by Burak on February 6th, 2010
| Quote
select(‘*’)->
from(‘table_name’)->
where(‘city_id = ?’, $cityid)->
andWhereIn(‘status_id’, array(1,4,7))
#49 by Mohamed Mahmoud on February 7th, 2010
| Quote
Hi Piyush
i think maybe i can help you
$result = Doctrine_Query::create()
->select(‘*’)
->from(‘ Module_Name ‘)
->where(‘cityid = ?’, $cityid)
->wherein(‘status_id’, array(1, 4, 7))
->execute();
and i won’t forget to send many thanks to Burak on this great tuts
Thanks From Sphinx in Egypt
#50 by Mohamed Mahmoud on February 7th, 2010
| Quote
ops .. ididn’t saw burak comment
just saw it after i added mine
Pingback: CodeIgniter and Doctrine from scratch. Day 11 – Record Hooks | PHP and Stuff
#51 by Ricardo on February 11th, 2010
| Quote
Hi Burak! Great tut!!
I’m trying to create a CI form_dropdown, using doctrine to create the options array… is there a way, or a hydrator type, that can return an array with the same format as the form_dropdown needs as parameter?
Thank you very much in advance!
#52 by Burak on February 13th, 2010
| Quote
I looked at the core hydration modes, but I don’t think any of them gives exactly what you are asking.
You can write your own hydration method if you want:
http://www.doctrine-project.org/documentation/manual/1_2/en/data-hydrators#writing-hydration-method
#53 by Elbi on March 28th, 2010
| Quote
->addSelect(‘p.id, (COUNT(p.id) – 1) as num_replies’)
why is it important to select the post id and not just
COUNT(p.id)
?
#54 by Burak on March 28th, 2010
| Quote
If I remember correctly, I encountered some strange behavior in Doctrine where I couldn’t COUNT a column unless I also selected it too.
#55 by Elbi on March 28th, 2010
| Quote
Another question:
If we profile this you can see that theres a query per thread. Doesn’t that mean we access the DB 1 time for each thread?
Since the DQL is executed one at a time.
Aren’t there ways to optimize this, maybe accessing the database just once and executing all the queries at once, or perhaps getting all the data in the first query with a better DQL query ?
Or maybe its worth it to just duplicate the values in the database in terms of performance?
-Thanks
#56 by Burak on March 28th, 2010
| Quote
See Day 11 about this.
#57 by Elbi on March 28th, 2010
| Quote
So the second question got answered by part 11
#58 by Ryan Bosinger on June 17th, 2010
| Quote
Looks like you put a lot of work into this. Good job. I wished I would have used Doctrine (or some form of ORM) when I started by big CI project a year ago. Now it’s going to be a pain to make the switch…
#59 by Richard on June 17th, 2010
| Quote
found if using hydrate_array outside of a model I need to use the following
$q->setHydrationMode(Doctrine_Core::HYDRATE_ARRAY);
doctrine_core not just doctrine otherwise I get an error on the dql. took me a few days to find that tip.
#60 by K. Beau Beauchamp on July 6th, 2010
| Quote
I love your site and it’s been very helpful in getting me started with Doctrine. However, I note that you’re putting SQL (DQL) calls in your controllers. Ouch. In N-tier architecture this is generally a major violation of abstraction. Should you not be placing these SQL (DQL) calls in a CI model?
#61 by James Pakele on July 14th, 2010
| Quote
I don’t know if I’m doing something wrong somewhere, but I had to make the following changes to the getThreadArray() function in the Forum Model for the code to run correctly on my system.
changed line 23:
from: ->where(‘p.id = ?’, $thread['Posts'][0]['first_post_id'])
to: ->where(‘p.id = ?’, $thread['first_post_id'])
changed line 27:
from: $thread['num_replies'] = $thread['Posts'][0]['num_replies'];
to: $thread['num_replies'] = $thread['num_replies'];
BTW: This tutorial has swayed me from using DataMapper OZ edition for my current project. By the looks of this it seems that by doing so I have saved a bunch of time and gained a lot more functionality. Most comprehensive web tutorial I have EVER gone through on ANY subject EVER. You should definitely consider putting out a book.
*Have you considered doing using CI+Doctrine with MondoDB?
Aloha
James
#62 by yoursjazz on July 15th, 2010
| Quote
Hi, I download your day9 source code,then run it ,Iget the error as bellow:
Fatal error: Uncaught exception ‘Doctrine_Record_Exception’ with message ‘Unknown method Forum::getThreadsArray’ in D:\wamp\www\hmvc\system\application\plugins\doctrine\lib\Doctrine\Record.php:2533 Stack trace: #0 [internal function]: Doctrine_Record->__call(‘getThreadsArray’, Array) #1 D:\wamp\www\hmvc\system\application\modules\user\controllers\forums.php(7): Forum->getThreadsArray() #2 [internal function]: Forums->display(’10′) #3 D:\wamp\www\hmvc\system\codeigniter\CodeIgniter.php(236): call_user_func_array(Array, Array) #4 D:\wamp\www\hmvc\index.php(115): require_once(‘D:\wamp\www\hmv…’) #5 {main} thrown in D:\wamp\www\hmvc\system\application\plugins\doctrine\lib\Doctrine\Record.php on line 2533
Help……
#63 by yoursjazz on July 15th, 2010
| Quote
Sorry ,This is my fault~,I copy getThreadsArray function to controller…
#64 by Gareth on August 5th, 2010
| Quote
When you create getThreadsArray, should line 35 (return $threads) not be return $thread?
You create the newly structure $thread array and then return the array first obtained by the first DQL query..
#65 by Gareth on August 5th, 2010
| Quote
Sorry, completely didn’t see the & before the variable name! I didn’t even know what that did, but i do now!
You are correct, afterall
#66 by Patrick Curl on September 17th, 2010
| Quote
Hi.. I keep running into this error.. Can’t seem to shake it.
I’ve got latest CI and doctrine 1.2.3.
A PHP Error was encountered
Severity: Notice
Message: Undefined index: num_replies
Filename: models/forum.php
Line Number: 42
#67 by Geza Szekeres on September 17th, 2010
| Quote
Hi!
I’ve got the same problem.. Any guess?
#68 by Geza Szekeres on September 17th, 2010
| Quote
Yess.. If I comment that line works fine:
//$thread['num_replies'] = $thread['Posts'][0]['num_replies'];
Because $thread itself has the num_replies element.. Its “Post” element dont have..
Does anyone know why?
#69 by kaleonyu on October 19th, 2010
| Quote
Maybe Doctrine bug, i use page top “Download code” zip, it’s no problem.
#70 by Giovanni on November 7th, 2010
| Quote
Hi, I have been following this tuts for the last 3 days. Today I arrived at this point. I got the same problem. After several tries I got to the following solution:
at: system/application/models/forum.php
replace the line-code:
->addSelect(‘p.id, (COUNT(p.id) – 1) as num_replies’)
into this:
->addSelect(‘p.id, COUNT(p.id) – 1 as num_replies’)
note: so, remove the brackets – strange! but that worked for me.
ps: Burak, thanks for the tuts, this is great!!! I am following your tuts from Holland.
#71 by Giovanni on November 7th, 2010
| Quote
I forget to mention: I use Codeigniter 1.7.2 and Doctrine 1.2.3
Pingback: CodeIgniter and Doctrine – Me and My Self
#72 by ha_c on June 7th, 2011
| Quote
Here you have template with “content_view” subview:
11 <div class=" container”>
12
13
14 load->view(‘user_controls’); ?>
15
16
17 CI+Doctrine Message Board
18
19 load->view($content_view); ?>
20
21
And in “content_view” you have $categories variable. How you can get $categories there if you don’t passed it like this:
$this->load->view($content_view, $vars);
Sorry for my English.
#73 by Emmanuel A. Rosani on July 25th, 2011
| Quote
your great man..Thanks for this wonderful tutorials…Waiting for your next episodes..hahaha :p
#74 by b.achyuth on September 21st, 2011
| Quote
i am new to this framework,now i want build dynamic website in this frame work!
please tell me where how can find step by step process of codeigniter frame work!
thank you to all
Trackback: attorney in the philippines,business law attorneys,small business attorney,business law attorney,philippine attorney,lawyers in manila,Legal attorney ,legal aid attorney,legal lawyer,attorney search,legal help,find a lawyer,legal research attorney
Trackback: terms and conditions
Pingback: CodeIgniter and Doctrine from scratch. | 世界是平的
Pingback: CodeIgniter and Doctrine from scratch. | 世界是平的
Pingback: CodeIgniter and Doctrine from scratch. | 世界是平的
#75 by next on January 12th, 2013
| Quote
Hi! I’ve been following your weblog for a while now and finally got the bravery to go ahead and give you a shout out from Atascocita Tx! Just wanted to mention keep up the great job!
#76 by positive approach on January 16th, 2013
| Quote
Quality posts is the crucial to invite the users to pay a quick visit the site, that’s what this web site is providing.
#77 by Shriram Tank on February 4th, 2013
| Quote
awesome website! I’m happy I wandered onto it through google, i’m gonna definitely have to add this one to the morning routine
#78 by http://cooklikeyourgrandmother.com/ on May 15th, 2013
| Quote
If some one wants to be updated with most up-to-date technologies therefore he must be pay a visit this site and be up to date daily.
#79 by smallbusiness.yahoo.com on May 19th, 2013
| Quote
I pay a visit everyday a few web sites and information sites to read
articles or reviews, however this website offers quality based articles.