tag:blogger.com,1999:blog-6112774693059337392024-03-12T18:25:43.023-07:00my-CakePHPA blog tutorial on CakePHP - PHP Rapid Development Framework.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.comBlogger41125tag:blogger.com,1999:blog-611277469305933739.post-29314966278258577922011-04-15T20:51:00.000-07:002011-04-15T20:53:23.359-07:00Two Important CakePHP Plugins You Must Use In Your Next Cake Project - ACL Plugin & Facebook PluginI am glad to get personal emails from a few of our readers. They are mostly Cake Newbies! I am really excited to find that this blog has helped some of them. I promised to share two more plugins, which is a must have in your next Cake Project. The first one will make your life happy (if you use Auth component for authorization) and the second one will make your client happy (if he has strong facebook love!) . These two plugins are:<br />
<br />
1) ACL plugin<br />
2) facebook plugin<br />
<div><br />
</div>As you might know, it is easy to install plugins. Download necessary files, save them under /app/plugins/plugin-name/ folder. If it needs any extra database table, fire your SQL query editor. Usually, necessary table structures are included with the plugin package. Your tables should be ready within a few seconds. Next check for a few configuration files. You can find this file under:<br />
<br />
/app/plugins/your-plugin-name/config/config.php<br />
<div><br />
</div>READ & FOLLOW the installation direction for your new plugin verbatim. Do not skip any single character. Most of the time, I messed things up because I really skipped a few words. The cakeMagic works when you follow the conventions. So, read the instructions and follow it. Make necessary changes to set your settings. If you do everything okay, it should be ready for use within 10- 20 minutes. A single error on your part can lead to lot of frustrating hours.<br />
<br />
Regarding these two plugins here is what I think.<br />
<br />
ACL plugin: Well those using Auth Component might be aware of the fact that CakePHP has a built-in mechanism to set user-level access control to various pages (/controllers/action/) of your website. ACL plugin has a beautiful AJAX based GUI. You can create new ACO on the fly and set permissions.<br />
<br />
For example, say, in your PostsController (posts_controller.php) you have created new action - 'post_by_user' (function post_by_user()). Now you want only registered users to view this section. So, add a new ACO [Access control object, in this case post_by_user() under 'posts' controller.] ACL plugin allows you to create this new node. Now you can set group level or user specific permission using ACL component. I am just giving you a screen shot.<br />
<div><br />
</div><br />
<div class="separator" style="clear: both; text-align: left;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOOc9Pptb8CPqb7pkdwrOBrtfyDREfiDGPYVM7eGgg8-N6_KOsBfvQRVedrunX6_dll-0y3fKpWYEFrtJxG1XEDU-WtQZ5hytLOkcJAYca5YDqPtgLWEXUnidgHqjNAVCXsZNPPrUcRoY/s1600/acl.png" imageanchor="1" style="margin-left: 1em; margin-right: 1em;"><img border="0" height="192" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEgOOc9Pptb8CPqb7pkdwrOBrtfyDREfiDGPYVM7eGgg8-N6_KOsBfvQRVedrunX6_dll-0y3fKpWYEFrtJxG1XEDU-WtQZ5hytLOkcJAYca5YDqPtgLWEXUnidgHqjNAVCXsZNPPrUcRoY/s320/acl.png" width="320" /></a></div><div class="separator" style="clear: both; text-align: left;"><br />
</div><div class="separator" style="clear: both; text-align: left;"></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">The facebook plugin is a cool cakePHP application. It displays facebook like button, facebook login options, facebook fan pages and many more. My simple tips are to wait for a few hours after you have installed this plugin for it to work properly. Remember you need to create your APP ID, API Key & Secret at <a href="http://www.facebook.com/developers/createapp.php">facebook</a> (Create Applications). It takes a few hours (in my case) to propagate. IN the meantime, your facebook login action won't work. So, do not loose your heart.<o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><br />
</div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">Once you have installed those plugins, you can access it using the following urls:<o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><br />
</div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">http://your-good-domain.com/plugin-name (if you are NOT using admin routing)<o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">http://your-good-domain.com/admin/plugin-name (if you are using admin routing)<o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><br />
</div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">Remember installing and using cakePHP plugin is pretty simple. FOLLOW the steps accurately. You must not have any reason to become frustrated anymore. <o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span style="color: black; font-family: 'Times New Roman'; font-size: 13.5pt;">Happy Baking!<o:p></o:p></span></div><div class="separator" style="margin-bottom: .0001pt; margin: 0in;"><span class="Apple-style-span" style="font-size: medium;"><br />
</span></div><div class="separator" style="clear: both; text-align: left;">Links to downloads:</div><div class="separator" style="clear: both; text-align: left;"><a href="http://bakery.cakephp.org/articles/phishy/2008/01/25/acl-management-plugin">CakePHP ACL Plugin</a></div><div class="separator" style="clear: both; text-align: left;"><a href="http://www.webtechnick.com/blogs/view/229/CakePHP_Facebook_Plugin_Auth_Facebook_and_more">CakePHP facebook Plugin</a></div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com2tag:blogger.com,1999:blog-611277469305933739.post-45226027462342062562010-12-05T04:04:00.000-08:002010-12-05T04:04:45.517-08:00CakePHP: Tweak With Search, Managing Form Post DataNowadays, it has rather become a trend to let the visitors sort or filter search results. We let them search by the bestsellers, popular, newest, or, simply by price. We can use a form with a select box having options and let user hit the submit button. You can get the first result page to work pretty well with your default CakePHP setup. But the pagination fails. It is because Cake does not save the form post data. And here is a simple trick I found somewhere in the Internet.<br />
<br />
<b>USE SESSION VARIABLES.</b><br />
<br />
In your controller setup:<br />
<br />
function my_function() {<br />
<br />
if(!empty($this->data)){<br />
$this ->Session->write('search',$this->data['Model']['field']);<br />
$search_string =$this->data['Model']['field'];<br />
} else {<br />
$search_string =$this ->Session->read('search');<br />
}<br />
<br />
$condition = array('Model.field_name'=>$search_string);<br />
$search_data = $this->Model->find('all',array('conditions'=>$condition));<br />
$this->set('search_data',$search_data);<br />
}<br />
<br />
/* in your view file use */<br />
debug($search_data);<br />
/* you can see the recordset, if debug mode is set to 2 or above. */<br />
<br />
Hope this helps someone else as well.<br />
Happy baking.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-75817935035489301892010-08-29T20:53:00.000-07:002010-08-29T20:53:02.799-07:00How to Open a File (xls, doc, pdf etc) through a link in CakePHPWell this question was discussed in <a href="http://groups.google.com/group/cake-php/browse_thread/thread/1e89b9aefa2d2b9b/9d6207c5ba2d83ca?#9d6207c5ba2d83ca">Google Group</a>.<br />
The poster wants to open xls, doc, or pdf files using CakePHP. As such, he wants to create a link, which when clicked, should open the document.<br />
<br />
<b>Solution:</b><br />
1. Save the file under /app/webroot/ folder. You can FTP that file for the sake of simplicity. If you need to upload files frequently, you can consider CAKEPHP <a href="http://bakery.cakephp.org/articles/view/file-upload-component-w-automagic-model-optional">file upload component</a>. This component allows you to upload files from your computer to your server. Tweak it a bit to upload almost any file. But be sure to enforce all reasonable protections to prevent spammy uploads. Check to ensure that the file has been uploaded by pointing your browser to http://your-cake-domain.com/my_file_name.doc. Next we need to do something in the respective view file.<br />
<br />
2. Create a variable name $file_path in the respective view files.<br />
<br />
Say, $file_path='my_file_name.doc';<br />
Now simply create a link to that path.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com3tag:blogger.com,1999:blog-611277469305933739.post-30727441147276505352010-08-21T10:35:00.000-07:002010-08-21T10:35:06.344-07:00Something on CakePHP Notice (8): Undefined IndexI do not know what should be the perfect title for this post - amazing cake or uncanny cake. But unfortunately, CakePHP can literally drive you CRAZY at times. So, we need to develop a methodical debugging algorithm for cake.<br />
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b>Settings:</b></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><b><br />
</b></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">1. You are using proper Model/ Controller/ View setup.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">2. You are firing correct SQL statement to fetch records. And database has at least one matching record.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">3. Everything is just fine to the best of your knowledge and yet you don't really see any output in your view file.</div><div><br />
</div><br />
<b>To debug:</b><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">1. Set <a href="http://my-cakephp.blogspot.com/2009/12/cakephp-debug.html">debug level</a> to '2'.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">As such my localhost is configured in that format by default. So, I do not have to change that setting too often. </div><div><br />
</div><br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">2. Read the output in the debug mode very carefully. Here lies the clue.</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">If you see a message like: </div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Notice (8): Undefined index .. blah blah blah</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">CakePHP points out exactly what went wrong with the filename and line number even. This output is very reliable. "Undefined index" means you have used a variable somewhere but it has not been assigned any value. In production mode, CakePHP will ignore this warning and you will see nothing in your webpage leading to complete confusion.</div><div><br />
</div><br />
3. You are more likely to fix the problem by correcting small typos in that specified file. Anyway, if you can't find anything wrong, follow the next few steps.<br />
<br />
Check the value of the fetched recordset using debug($data) in your controller/action.<br />
If you can see the values as per expectation, move on to your view files.<br />
If you can't see any result, re-frame your find() conditions, examine your controller/action statements very carefully.<br />
<br />
4. Check for typos.<br />
Your variable names must be the same in controller set up and view files. Variable names you might have used in views without setting its value in the controller first. And remember the auto magic cake feature, which automatically converts controller variable names like:<br />
my_funny_vars<br />
to:<br />
myFunnyVars<br />
<br />
So, in your view file, you need to mention myFunnyVars and not my_funny_vars.<br />
I wasted more than few hours to fix that.<br />
<br />
5. Few other tips I have found elsewhere:<br />
When using scaffolding the order your associations must be the same as the order of the keys in your table to avoid getting this error message. Thankfully, I did not face that problem till now.<br />
<br />
6. Have confidence in your cake knowledge. Keep your cool. And move methodically (check for view files, then controller setup, and finally your great models). If you can see desired result using debug($data) in your controller, problem is really trivial. To get into the details, you can use debug($data) in your view file to trace out the contents of the array elements as well.<br />
<br />
Sounds too complicated? That's how CakePHP goes on.<br />
Hope it helps someone, who might have been stumbling with Notice (8): Undefined index!!!Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com9tag:blogger.com,1999:blog-611277469305933739.post-48768236799094646022010-08-07T09:22:00.000-07:002010-08-07T09:24:36.275-07:00How to use SEO urls in CakePHP without the IDCakePHP offers massive support to create SEO friendly URLs on the fly. You can create SEO-friendly-urls without an ID value to refer to specific post id. It works like a charm like many other Cake MAGIC!<br />
<br />
I'll refer to the post table.<br />
<b>1.</b> <b>Create a field called 'slug' (must be UNIQUE and NOT NULL) in the post table.</b><br />
<br />
<b>2. Download and use </b><a href="http://bakery.cakephp.org/articles/view/sluggable-behavior"><b>sluggable behavior</b></a><b> to create post slug! Follow instructions step-by-step. It works perfectly.</b><br />
<br />
<b>3. Define routing rules in config/router.php file to display SEO friendly urls.</b><br />
<br />
Router::connect(<br />
<br />
<br />
'/posts/:slug', <br />
<br />
<br />
array( <br />
<br />
<br />
'controller' => 'posts', <br />
<br />
<br />
'action' => 'view' <br />
<br />
<br />
), <br />
<br />
<br />
array( <br />
<br />
<br />
'slug' => '[-a-z0-9]+', <br />
<br />
<br />
'pass' => array('slug') <br />
<br />
<br />
) <br />
<br />
<br />
); <br />
<br />
<b>4. In posts_controller.php view() function modify query,</b><br />
<br />
function view($slug = null)<br />
{<br />
if (empty($slug))<br />
{<br />
// redirect ...<br />
}<br />
<br />
<b> $data = $this->Post->findBySlug($slug) ; </b><br />
<br />
}<br />
<br />
You you should be able to access urls of the form:<br />
http://example.com/your-seo-friendly-post-url/<br />
<br />
Hope it helps someone.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-5849169040274039212010-06-18T01:06:00.000-07:002010-06-18T01:06:40.514-07:00How to Add Robots Meta Tag to a CakePHP View FileThis is a pirated idea... and hats off to Maquel Collado for his wonder post<br />
<br />
<a href="http://snippetsatwork.blogspot.com/2009/11/adding-robots-meta-tag-to-cakephp-view.html">Adding robots meta-tag to a CakePHP view</a><br />
<br />
You should check the original there. And here is a carbon copy:<br />
<b>Code:</b><br />
<br />
<br />
<span class="Apple-style-span" style="color: orange;"><?php $html->meta('robots', null, array('name' => 'robots', 'content' => 'noindex') ,false); ?></span><br />
<div><br />
</div><div>Add this html helper in its exact form in your view file. </div><div><br />
</div><div><b>Output:</b></div><div><br />
</div><div><span class="Apple-style-span" style="color: #e69138;"><meta name="robots" content="noindex"/> </span></div><div><br />
</div><div>And it will appear within the <head> </head> </div><div><br />
</div><div>And all the well behaved robots (Sure! Google is so) will stop indexing those pages.</div><div><br />
</div><div>Thanks Miquel. You are a genius!</div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-8698316359248331372010-05-06T21:16:00.000-07:002010-05-06T21:18:53.612-07:00How to Create Multiple AJAX Forms on Same Page in CakePHPSettings: Say, your posts/index.ctp page displays the latest ten posts. You want to allow user to rate each post.<br />
<div>Requirement: You MUST have a Post Model and a Comment Model.<br />
<div>In your respective view file: /app/view/posts/view.ctp<br />
<div>Type:</div><div><br />
</div><div>$i = 0; // a counter to create new divs</div><div><br />
</div><div>foreach ($posts as $post) :</div><div><br />
</div><div>// Code to display your post title, body etc.</div><div>// Now our comment form for each post</div><div><br />
</div><div>$i++;</div><div><br />
</div><div>$new_comment = 'new_comment_'.$i ; // for comment div id</div><div>$form_id = 'form_id_'.$i; // for form id</div><div><br />
</div><div>echo '<div id="'. $new_comment .'"</div>';<br />
<br />
<div><div>echo $ajax->form(array('type' => 'post', 'options' => array(</div><div><span class="Apple-tab-span" style="white-space: pre;"> </span> 'model'=>'Post', </div><div><span class="Apple-tab-span" style="white-space: pre;"> </span> 'update'=>$new_comment,</div><div><span class="Apple-tab-span" style="white-space: pre;"> </span> 'url'=>array('controller'=>'comments','action'=>'add'),</div><div><span class="Apple-tab-span" style="white-space: pre;"> </span> 'id'=>$form_id,'class'=>'CommentForm')</div><div> ));</div><div><div><br />
</div><div>echo $form->input('comment',array('label'=>'Write your comment','type'=>'textarea', 'cols'=>'60','rows'=>'4'));</div><div><br />
</div><div>echo $form->end('Submit'); // close the form</div><div><br />
</div><div>// now close div</div><div>echo '</div>';</div></div></div></div><div>endforeach;</div><div><br />
</div><div><span class="Apple-style-span" style="font-family: Arial; font-size: small;"><span class="Apple-style-span" style="font-size: 13px;">- - - - - - - - -</span></span><br />
<span class="Apple-style-span" style="font-family: Arial; font-size: 13px;">The idea is to create unique div to position each form and creating unique id for each form.</span><br />
<span class="Apple-style-span" style="font-family: Arial; font-size: 13px;"><span class="Apple-style-span" style="font-family: 'Times New Roman'; font-size: medium;"></span></span><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span class="Apple-style-span" style="font-family: Arial; font-size: small;"><span class="Apple-style-span" style="font-size: 13px;">I created this post just before leaving for my office on the fly. Let me know if it helps.</span></span></div></div></div></div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-49361440046891528442010-04-30T22:27:00.000-07:002010-04-30T22:27:06.950-07:00Where Should I Upload robots.txt file in CakePHP installation & Why I Thanked Google Webmaster Tool Once AgainFor those rather newbies (ME too!), <a href="http://www.robotstxt.org/robotstxt.html">robots.txt</a> in a text file, which restricts access to specific folders or files in your web page. As such you create some rules using that file. Well behaved robots (like GoogleBOT) will follow these instructions before accessing any location.<br />
<br />
We upload that file usually under /public_html/ folder of our web hosting directory, technically called root of our web servers. CakePHP has its own folder architecture, and, if you follow the default CakePHP installation, you should upload your robots.txt file under:<br />
<br />
<span class="Apple-style-span" style="color: orange;"><b>http://your-lovely-domain-name.com/app/webroot/<span class="Apple-style-span" style="color: red;">robots.txt</span> </b></span><br />
<span class="Apple-style-span" style="color: orange;"><b><br />
</b></span><br />
As such, I have subscribed to free Google Webmaster Tool. I found a notice long ago indicating my robots.txt file was not well formatted. I simply ignored it. Because, I checked that file manually many times and found nothing wrong.<br />
<br />
Recently, Webmaster tool was displaying bunch of urls restricted by robots.txt file. I examined it and found the fault was in upload location itself. Issue was resolved finally.<br />
<br />
Lesson today?<br />
<br />
<b>ALWAYS DOUBLE CHECK EVERYTHING WHEN YOU ARE GOING WITH CAKEPHP</b><br />
<br />
And a big thanks to Google Webmaster Tool for pointing out to the urls restricted by robots.txt and finally, helping me to get into the problem location.<br />
<br />
Thanks.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com5tag:blogger.com,1999:blog-611277469305933739.post-61325536983850066632010-02-18T10:39:00.000-08:002010-02-18T10:39:11.120-08:00CakePHP Pagination & Custom Routes Issue<a href="http://book.cakephp.org/view/46/Routes-Configuration"><span class="Apple-style-span" style="color: #990000;"><b>Custom Routes</b></span></a> are something that make CakePHP very interesting! If you are reading this post you must have experimented with what we call custom routing. The problem might arise when we want to paginate models which use custom routing.<br />
<br />
The problems may be many-folded which all simplifies to one simple issue:<br />
<br />
<b><span class="Apple-style-span" style="background-color: yellow;">UNFORMATTED URL</span></b><br />
Say, you want to display url in the following format using custom routes<br />
<br />
CakePHP default url structure<br />
http://example.com/categories/index/categoryID<br />
<br />
<span class="Apple-style-span" style="background-color: yellow;"><b>Your WELL FORMATTED URL structure:</b></span><br />
http://example.com/category-name-ID<br />
<br />
Obviously, your custom route element points to 'index' action of 'categories' controller with two parameters - category-name and 'categoryID'.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;">Router::connect(</span><br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"> '/:slug-:id/<span class="Apple-style-span" style="color: red;"><b>*</b></span>',</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> array('controller' => 'categories', 'action' => 'index'),</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> array(</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> // order matters</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'pass' => array('slug','id'),</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'id'=> '[0-9]+'</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> )</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> );</span><br />
<div><br />
</div><div>This works perfectly for URLs like</div><div>http://example.com/my-first-category-ID1</div><div>http://example.com/my-second-category-ID2</div><div><br />
</div><div>But it may cause problem when you try to paginate</div><div><br />
</div><div><b><span class="Apple-style-span" style="background-color: yellow;">Cake will not pick your params</span></b> (here 'slug' and 'id') passed through url if you do not force Cake to do so while paginating. </div><div><br />
</div><div>To fix this issue, you MAY use:</div><div><br />
</div><div><span class="Apple-style-span" style="color: #b45f06;"> $paginator->options(array('url' => $this->passedArgs)); </span></div><div>or, as I have told <a href="http://my-cakephp.blogspot.com/2010/01/how-to-pass-all-url-arguments-to.html">here</a> earlier following CakePHP book.</div><div><br />
</div><div>But this will format your paginated urls like</div><div>http://example.com/categories/index/param1/param2/page:xxxx</div><div><br />
</div><div>You can obviously browse pages with the above url. But it does not look decent. So, your entire effort with custom routing might just not work. </div><div><br />
</div><div><b><span class="Apple-style-span" style="background-color: yellow;">You may still get a bad URL.</span></b></div><div><br />
</div><div><b><span class="Apple-style-span" style="background-color: yellow;">DO NOT WORRY!</span></b></div><div><br />
</div><div>While defining <b>paginator</b> options in your view file, follow religiously $html->link() structure. For an example I have put forward the structure of $paginator->options() below in a view file:</div><div><span class="Apple-style-span" style="color: #999999;"><br />
</span></div><div><span class="Apple-style-span" style="color: #999999;">file:// /app/views/categories/index.php</span></div><div><br />
</div><div><div><span class="Apple-style-span" style="color: #b45f06;">$paginator->options(array('url'=> array(</span></div><div><span class="Apple-style-span" style="color: #b45f06;">'controller' => 'categories', </span></div><div><span class="Apple-style-span" style="color: #b45f06;"> 'action' => 'index',</span></div><div><span class="Apple-style-span" style="color: #b45f06;">'slug'=>$this->params['slug']),</span></div><div><span class="Apple-style-span" style="color: #b45f06;">'id'=>$this->params['id'])</span></div><div><span class="Apple-style-span" style="color: #b45f06;"> ));</span></div><div><br />
</div></div><div><b><span class="Apple-style-span" style="background-color: #b6d7a8;">Now Cake will make well formatted URL automatically</span></b>, and your paginated url should look like</div><div><br />
</div><div>http://example.com/category-name-id1/page:2</div><div>http://example.com/category-name-id1/page:3</div><div><br />
</div><div>Done!</div><div>I hope it helps someone.</div><div>Does it?</div><div><br />
</div><div><div><span class="Apple-style-span" style="color: #cc0000;"><b>Please Note</b></span></div><div><span class="Apple-style-span" style="color: #cc0000;"><b></b></span> I have marked asterisk symbol (<span class="Apple-style-span" style="color: red;">*</span>) with RED color while talking about custom route elements. This (<span class="Apple-style-span" style="color: red;">*</span>) MUST be there for pagination to work properly. </div><div>Good night.</div></div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com9tag:blogger.com,1999:blog-611277469305933739.post-4991832314470542732010-02-13T20:55:00.000-08:002010-02-13T20:56:23.908-08:00How to Find Records using MySQL Match Against Query in CakePHPTo use MySQL Match Against Query in CakePHP:<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;">$needle = 'Search String'</span>;<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;">$conditions = array( </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> "MATCH(Post.title) </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> AGAINST('$needle' IN BOOLEAN MODE)" </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> );</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> $matches = $this->Post->find('all', array('conditions' => $conditions));</span><br />
<div><br />
</div><div>It does not need any explanation. I hope.</div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com5tag:blogger.com,1999:blog-611277469305933739.post-38173887730127723022010-02-12T19:16:00.000-08:002010-02-12T19:16:37.930-08:00CakePHP Select EmptySay, you have a select box displaying dropdown options for categories. You want to give the user liberty to select nothing. In CakePHP it is pretty simple. Use 'empty' options in your view file.<br />
<br />
<br />
<?php echo $form->input('category_id', array( 'empty' => '(choose one)')); ?><br />
<br />
Hope this helps someone.<br />
Happy baking.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-47458021574610939582010-02-09T10:15:00.000-08:002010-02-09T10:15:04.240-08:00CakePHP hasAndBelongsToMany (HABTM) JoinComing back to one of the most critical basics of Cake - it is hasAndBelongsToMany (<b>HABTM</b>) relationship. You may know it is a type of relationship between two different database tables (Models) in CakePHP. A case study will explain its importance:<br />
<br />
Say, you have Category model and Post model.<br />
Each category has many posts and each post belongs to more than one categories.<br />
<br />
Had there been only one category per post, it would be enough to use category_id field in posts table. But we are talking about posts each of which may have more than one categories. In this case besides categories and posts table, you need one extra table. By convention - this table should be named as categories_posts (note the alphabetical order of join tables). The table categories_posts will have following fields : id, category_id, post_id.<br />
<br />
In your post model define the relationship.<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><?php</span><br />
<span class="Apple-style-span" style="color: #b45f06;"><br />
</span><br />
<span class="Apple-style-span" style="color: #b45f06;">class Post extends AppModel {</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> var $name = 'Post'; </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> var $hasAndBelongsToMany = array(</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'Category' =></span><br />
<span class="Apple-style-span" style="color: #b45f06;"> array(</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'className' => 'Category',</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'joinTable' => 'categories_posts',</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'foreignKey' => 'post_id',</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> 'associationForeignKey' => 'category_id'</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> )</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> );</span><br />
<span class="Apple-style-span" style="color: #b45f06;"> }</span><br />
<span class="Apple-style-span" style="color: #b45f06;"><br />
</span><br />
<span class="Apple-style-span" style="color: #b45f06;">?></span><br />
<br />
This will show you all categories for a given post when you fire:<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Recipe->find();</span><br />
<br />
Now the biggest question - how to <b>SAVE</b> records for HABTM association.<br />
<br />
The default CakePHP functioning in this regard is not at all adequate. Say you want to add a new category to an existing post which already has a category defined by HABTM association - by default Cake will delete your existing category records for that post from categories_posts table before inserting the new record. That's an absolute mess if you do not really intend to desire existing records. However, there is the savior.<br />
<br />
<b>ExtendAssociations Behavior.</b><br />
This behavior allows you to easily add or delete HABTM associations!<br />
<br />
A full detail of this Behavior can be found in <a href="http://bakery.cakephp.org/articles/view/add-delete-habtm-behavior">Bakery</a>!<br />
<br />
You can <a href="http://bakery.cakephp.org/articles/download_code/362/block/4">download</a> code for this behavior, and save that code as 'extend_associations.php' under '/app/models/behaviors' folder.<br />
<br />
In your Post model, add the following code:<br />
<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"> <?php </span><br />
<span class="Apple-style-span" style="color: #b45f06;">var $actsAs = 'ExtendAssociations'; </span><br />
<span class="Apple-style-span" style="color: #b45f06;">?> </span> <br />
<br />
So, our modified Post model should look like this:<br />
<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><?php </span><br />
<span class="Apple-style-span" style="color: #b45f06;">class Post extends AppModel { </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">var $name = 'Post'; </span><br />
<span class="Apple-style-span" style="color: #b45f06;"><br />
</span><br />
<span class="Apple-style-span" style="color: #b45f06;">var $actsAs = 'ExtendAssociations'; </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">var $hasAndBelongsToMany = array( </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">'Category' => array( </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">'className' => 'Category', </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">'joinTable' => 'categories_posts', </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">'foreignKey' => 'post_id', </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">'associationForeignKey' => 'category_id', </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">), </span><br />
<span class="Apple-style-span" style="color: #b45f06;"> </span><br />
<span class="Apple-style-span" style="color: #b45f06;">); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">} </span><br />
<span class="Apple-style-span" style="color: #b45f06;">?> </span><br />
<br />
<b>Defining ACTION in PostsController</b><br />
file: // app/controllers/posts_controller.php<br />
Now in your PostsController - to <b>ADD</b> categories to a post use:<br />
<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"><?php </span><br />
<span class="Apple-style-span" style="color: #b45f06;">//</span><b><span class="Apple-style-span" style="color: #b45f06;"> </span></b><span class="Apple-style-span" style="color: #b45f06;">to </span><b><span class="Apple-style-span" style="color: #b45f06;">add</span></b><span class="Apple-style-span" style="color: #b45f06;"> only one category for a given post (say, post_id = 1)</span><br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Post->habtmAdd('Category', 1, 1); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">// to add multiple categories </span><br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Post->habtmAdd('Category', 1, array(1, 2, 3)); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">?> </span><br />
<br />
// to <b>DELETE </b>categories for a given post (say, post_id = 1)<br />
<br />
<br />
<span class="Apple-style-span" style="color: #b45f06;"> <?php </span><br />
<span class="Apple-style-span" style="color: #b45f06;">// delete a category </span><br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Post->habtmDelete('Category', 1, 1); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">// to delete multiple categories</span><br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Post->habtmDelete('Category', 1, array(1, 3)); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">// to delete all categories </span><br />
<span class="Apple-style-span" style="color: #b45f06;">$this->Post->habtmDeleteAll('Tag', 1); </span><br />
<span class="Apple-style-span" style="color: #b45f06;">?> </span><br />
<br />
<br />
That's it.<br />
Good night.<br />
Sweet Baking.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com2tag:blogger.com,1999:blog-611277469305933739.post-55894364412555927502010-02-05T23:37:00.000-08:002010-02-05T23:37:52.974-08:00How to Remove Mailed-by Header in CakePHP Email ComponentIt took me quite sometime to fix this issue.<br />
<br />
You can send emails with built-in <a href="http://book.cakephp.org/view/176/Email">CakePHP Email Component</a>. But if you are sending email to any gmail address (like your-name@gmail.com), you can see an annoying 'mailed-by' header. It shows the name of your server, like mailed-by: dreamhost.com. It discloses your webhost. You may not like it. You may want to remove/hide this information. To do so, you need only one line of CakePHP code.<br />
<br />
I have used following sendEmail() function in my /app/app_controller.php<br />
<br />
file:// /app/app_controller.php<br />
<br />
<br />
function sendEmail($subject, $view, $to=null, $from = null, $fromName = null) {<br />
/* This function will be used to send email in my CakePHP application */<br />
$this->Email->to = $to;<br />
$this->Email->subject = env('SERVER_NAME') . ' – ' . $subject;<br />
$this->Email->from = $fromName.' <'. $from.'>';<br />
$this->Email->template = 'default';<br />
<span class="Apple-style-span" style="color: orange;">$this->Email->additionalParams = '-fnoreply@yourdomain.com';</span><br />
<span class="Apple-style-span" style="color: #45818e;"><i>/* the above line is required to remove 'mailed-by' header' */ </i></span><br />
$this->Email->sendAs = 'both'; // you probably want to use both :) <br />
return $this->Email->send($view);<br />
}<br />
<br />
<br />
Done.<br />
<br />
Note again, whenever you use CakePHP Email Component, just add one extra line:<br />
<br />
<b><span class="Apple-style-span" style="color: #cc0000;">$this->Email->additionalParams = '-fnoreply@yourdomain.com';</span></b><br />
<br />
And you can safely remove that annoying 'mailed-by' header.<br />
<br />
That's it.<br />
<br />
Just a guess, <span class="Apple-style-span" style="color: #cc0000;">noreply@yourdomain.com </span>is NOT essential. You may change it to anything you want.<br />
<br />
Take care.<br />
<br />
Responses awaited.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com3tag:blogger.com,1999:blog-611277469305933739.post-29733627833071722472010-01-30T19:24:00.000-08:002010-01-30T19:24:49.173-08:00How to Generate Options for HTML Select Tags in CakePHPHow to generate options for HTML Select Tags in CakePHP?<br />
<br />
As such<br />
<br />
<ol><li>You can retrieve options from a Model (Database Table).</li>
<li>Or, you can specify options for select tag in view files.</li>
</ol><div>Just keep in mind <span class="Apple-style-span" style="background-color: yellow;">CakePHP does not support ENUM type field</span>. So, you may not use 'ENUM' datatype in table fields.</div><div><br />
</div><div><b>To retrieve options from Database Table</b></div><div><b><br />
</b></div><div>Say, you have two Models (tables) - Order and Size; </div><div><br />
</div><div>Fields in 'sizes' table:</div><div>id, size</div><div>And fields in 'orders' table:</div><div>id, quantity, size_id</div><div><br />
</div><div>In your OrdersController file (/app/controllers/orders_controller.php)</div><div><div>$sizes = $this->Order->Size->find('all');</div><div>$this->set('sizes',$sizes);</div><div><br />
</div></div><div>Now in your view file: (/app/views/orders/add.ctp)</div><div><br />
</div><div>echo $form->create('Order');</div><div>echo $form->input('quantity');</div><div><span class="Apple-style-span" style="color: orange;"><span class="Apple-style-span" style="background-color: black;">echo $form->input('size_id');</span></span></div><div>echo $form->end('Submit');</div><div><br />
</div><div>And done.</div><div><br />
</div><div>Note the use of variable names. </div><div>It is important to name the variables as per this convention. It will display all sizes available in database when you are adding a new order. To retrieve size field in table 'sizes', you need to specify variable name 'sizes' (note plural form) in your respective controller/action. Now when you refer to 'size_id' in view file - cake will create a select tag on the fly with options retrieved from database. </div><div><br />
</div><div>OK. It was pretty simple.</div><div><br />
</div><div><b>Now, how to display options for HTML Select Tag without any database table:</b></div><div><br />
</div><div>In this case, we have, say, only 'orders' table with following fields</div><div>id, quantity, size</div><div><br />
</div><div><div>In your view file (/app/views/orders/add.ctp), specify - </div><div><br />
</div><div><div>$form->create('Order');</div><div>$form->input('quantity');</div></div><div><span class="Apple-style-span" style="color: orange;"><span class="Apple-style-span" style="background-color: black;">$sizes = array('s'=>'Small', 'm'=>'Medium', 'l'=>'Large');</span></span></div><div><span class="Apple-style-span" style="color: orange;"><span class="Apple-style-span" style="background-color: black;">echo $form->input('size', array('options'=>$sizes, 'default'=>'m'));</span></span></div><div><div>$form->end('submit');</div><div><br />
</div></div><div>That's it.</div></div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com2tag:blogger.com,1999:blog-611277469305933739.post-86779906500090677242010-01-29T09:03:00.000-08:002010-01-29T09:03:43.318-08:00Managing Plugin URL in CakePHPJust now I noticed my urls are getting deformed when I tried to access a plugin controller/action in my brand new CakePHP app. It took me sometime to understand that the problem was due to plugin call. When you are calling plugin controller/action - the url structure is:<br />
<br />
echo $html->link('Plugin Controller/Action Link', array('plugin' => 'plugin_name', 'controller' => 'controller_name', 'action' => 'action_name'));<br />
<br />
The output will be:<br />
<br />
http://example.com/plugin_name/controller_name/action_name<br />
<br />
Make sure to mention 'plugin' => null in remaining urls, if you do not want to show plugin_name in other displayed links.<br />
<br />
echo $html->link('Non Plugin Link', array('plugin' => null, 'controller' => 'controller_name', 'action' => 'action_name')); <br />
<br />
Output:<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">http://example.com/controller_name/action_name</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">If you do not specify 'plugin' => null, all the displayed links will show:</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">http://example.com/plugin_name/controller_name_1/action_name_1</div><div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">http://example.com/plugin_name/controller_name_2/action_name_2</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"></div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">http://example.com/plugin_name/controller_name_3/action_name_3</div><div><br />
</div><br />
<div>From this what I get is that it is better to specify 'plugin' => null in case of all non-plugin links which are likely to be displayed in tandem with plugin links.</div></div><br />
<br />
<br />
Or, there may be a short route - who knows?<br />
<br />
Cake rocks... still learning each day...Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com1tag:blogger.com,1999:blog-611277469305933739.post-1455332536714673002010-01-27T19:07:00.000-08:002010-01-27T19:07:53.430-08:00How to Pass all URL Arguments to Paginator FunctionsUse the following statement in view file for respective controllers/action:<br />
<br />
$paginator->options(array('url' => $this->passedArgs));<br />
<br />
This will retrieve all passed url arguments.<br />
<br />
<span class="Apple-style-span" style="font-family: 'lucida grande', verdana, helvetica, arial, sans-serif; font-size: 12px; line-height: 18px;">To specify which params to pass, use:</span><br />
<br />
$paginator->options(array('url' => array("0", "1")));<br />
<br />
Simple.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-65230336618693594532010-01-14T18:57:00.000-08:002010-01-14T18:57:03.727-08:00CakePHP Pagination Change LabelHere we can change the displayed label for CakePHP Pagination:<br />
<br />
Say, we want to sort results by user_id.<br />
<br />
This is how it is done by default:<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><?php echo $paginator->sort('<span style="color: orange;">user_id</span>');?> <br />
</div><div><br />
</div><br />
And to change the displayed label:<br />
<?php echo $paginator->sort('<span style="color: red;">User</span>', '<span style="color: orange;">user_id</span>');?> <br />
<br />
Here <span style="color: red;">User</span> is the label which will be displayed.<br />
<span style="color: orange;">user_id</span> is the field to be sorted.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com4tag:blogger.com,1999:blog-611277469305933739.post-55222476838022467412009-12-22T19:03:00.000-08:002009-12-22T19:03:54.920-08:00CakePHP Debug<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;">Set </span></span><br />
<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;"><span style="color: orange;">Configure::write('debug',2);</span> /* file://app/config/core.php</span></span><br />
<span class="Apple-style-span" style="color: #222222; font-family: monospace; font-size: 14px; line-height: 25px;">This will display basic debugging information like SQL dumps etc. If you can see the error message, fix it.</span><br />
<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;"><br />
</span></span><br />
<span class="Apple-style-span" style="color: #222222; font-family: monospace; font-size: 14px; line-height: 25px;">Also you may use this statement in your view file:</span><br />
<span class="Apple-style-span" style="font-family: monospace; font-size: 14px; line-height: 25px;"><span style="color: orange;">pr($this->validationErrors);</span></span><br />
<span class="Apple-style-span" style="color: #222222; font-family: monospace; font-size: 14px; line-height: 25px;">It shows all validation errors. This helps a lot in debugging cake.</span><br />
<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;"><br />
</span></span><br />
<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;">A very helpful article I found:</span></span><br />
<span style="color: #222222; font-family: monospace; font-size: medium;"><span class="Apple-style-span" style="font-size: 14px; line-height: 25px;"><a href="http://teknoid.wordpress.com/2008/06/09/15-essential-cakephp-tips/">CakePHP Tips</a></span></span>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-73170413589312333472009-12-21T19:13:00.000-08:002009-12-21T19:13:39.703-08:00CakePHP Form Textarea Input Size<span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: verdana, geneva, helvetica, arial, sans-serif; font-size: 13px;">Default cake css defines all text inputs as having </span><br />
<span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-family: verdana, geneva, helvetica, arial, sans-serif; font-size: 13px;"><span>width 100%, so if you don't change that then the physical width of the </span><br />
<span><b class="highlight" style="-webkit-background-clip: initial; -webkit-background-origin: initial; background-attachment: initial; background-color: #ffff66; background-image: initial; background-position: initial initial; background-repeat: initial;">textbox</b> will not depend on the <b class="highlight" style="-webkit-background-clip: initial; -webkit-background-origin: initial; background-attachment: initial; background-color: #ffff66; background-image: initial; background-position: initial initial; background-repeat: initial;">size</b> attribute. </span></span><br />
<span style="font-family: verdana, geneva, helvetica, arial, sans-serif; font-size: small;"><span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-size: 13px;"><br />
</span></span><br />
<span style="font-family: verdana, geneva, helvetica, arial, sans-serif; font-size: small;"><span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-size: 13px;">Read more <a href="http://old.nabble.com/FormHelper::input()-has-no-size-option---td15631884.html">here</a>.</span></span><br />
<span style="font-family: verdana, geneva, helvetica, arial, sans-serif; font-size: small;"><span class="Apple-style-span" style="-webkit-border-horizontal-spacing: 2px; -webkit-border-vertical-spacing: 2px; border-collapse: collapse; font-size: 13px;">Thanks.</span></span>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com2tag:blogger.com,1999:blog-611277469305933739.post-63325137854826898032009-11-22T05:10:00.000-08:002009-11-22T05:13:29.756-08:00Field Name Conflicts - Consider using displayField<b>displayField</b><br />
If your table has two fields, i.e., 'name and 'title', you need to specify<br />
<br />
<span style="color: orange;">var $displayField = 'name'; </span><br />
<br />
in the Model.<br />
<br />
<b>Example: </b><br />
In my Category table I used both 'name' and 'title' as names of two different fields. Then in my Category model (file:// 'app/models/category.php), I used the following statement to tell Cake to use 'name' as label.<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">class Category extends AppModel {</span><br />
<span style="color: orange;"> var $name = 'Category';</span><br />
<b><span style="color: orange;"> var $displayField = 'name';</span></b><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;">?></span><br />
<br />
The statement var $displayField = 'name' forces Cake to use 'name' as the label. As such, you can choose any field name to use as a label in this way.<br />
<br />
CakePHP makes a label from either 'name' or 'title' field. When both are present in your table, the system may get confused. I am not sure if this is the general rule, but, this is how I fixed my problem.<br />
<br />
Hope this helps someone.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-69392165767429480002009-11-17T06:36:00.000-08:002009-11-17T06:38:48.543-08:00Creating a Complete User Registration System with CakePHPI was just browsing through my old posts. Hmm. it looks okay. I've started newly with Cake (CakePHP), so, I'm to really learn a lot myself. Anyway, as I'm through my process of learning, I thought it would be great to keep track of what I'm actually reading to get me into the GAME quickly.<br />
<br />
My today's task was to learn about a simple user registration system. Once again, I had to go through the CakePHP book and some other references. Instead of listing every detailed step, I would prefer to refer to those MUST read links, which just work like a CHARM in creating a User Management/Registration System using Cake.<br />
<br />
<b>Step: 1 Set up CakePHP Console</b><br />
The console works like a charm. If you had problem in using this console in windows environment, simply, follow the step-by-step method given <a href="http://www.webdevelopment2.com/cakephp-bake-baking-models-controllers-views-cakephp-12/">here</a>. <br />
<br />
<b>Step: 2 Follow the CakePHP Simple ACL Control Application</b><br />
<a href="http://book.cakephp.org/view/641/Simple-Acl-controlled-Application">This</a> complete tutorial will guide you through the process of creating your user management system. But before going through this tutorial, please, make sure to understand <a href="http://my-cakephp.blogspot.com/2009/11/learn-about-basic-principles-of-cakephp.html">basic working principles</a> of Cake nicely. The tutorial makes full use of different Cake's <a href="http://book.cakephp.org/view/170/Core-Components">core components</a> like Acl Component & Auth Component.<br />
<br />
<b>Step: 3 Set custom routing</b><br />
file: // app/config/routes.php<br />
<br />
Copy paste following codes:<br />
<br />
<span style="color: orange;">Router::connect('/login', array('controller' => 'users', 'action' => 'login'));</span><br />
<span style="color: orange;">Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));</span><br />
<span style="color: orange;">Router::connect('/register', array('controller' => 'users', 'action' => 'register'));</span><br />
<span style="color: orange;"><br />
</span><br />
This will show login form, when someone types http://caketest.local/login and likewise.<br />
<br />
<br />
<b>Step: 3 Create a dynamic login/logout menu</b><br />
The Cakebook tutorial does not include creating a dynamic login/logout menu. So, you need to create one.<br />
1. Create a new file.<br />
2. Copy-paste the following code.<br />
<br />
<span style="color: orange;"><?php </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if(!$session->check('Auth.User')){</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">echo $html->link('Login','/login');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">} else {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$username = $session->read('Auth.User.username');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">echo " Hello ". $username ."&nbsp;";</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">echo $html->link("(logout)", "/logout", array(), null, false);</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span style="color: orange;">?></span><br />
<br />
3. Save this file as '/app/views/elements/login_menu.ctp'<br />
<br />
4. Open '/app/views/layouts/default.ctp'<br />
5. Copy-paste the following code.<br />
<br />
<span style="color: orange;"><?php echo $this-> element('login_menu'); ?></span><br />
<br />
6. Save this file.<br />
<br />
<b>Now you can see the login/logout option.</b><br />
Notice I have used SESSION variables to control login/logout option. To learn more about CakePHP session, please visit <a href="http://justkez.com/understanding-cakephp-sessions/">this</a> page. For a formatted output of contents inside session variables, use pr($_SESSION) - STRICTLY for DEBUG;<br />
<b><br />
</b><br />
<b>Step 4: Ban a user account</b><br />
1.Fire the following SQL query:<br />
<b><br />
</b><br />
<span style="color: orange;">ALTER</span><span style="color: orange;"> </span><span style="color: orange;">TABLE</span><span style="color: orange;"> </span><span style="color: orange;">`users` </span><span style="color: orange;">ADD</span><span style="color: orange;"> </span><span style="color: orange;">`is_banned`</span><span style="color: orange;"> </span><span style="color: orange;">TINYINT</span><span style="color: orange;"> </span><span style="color: orange;">NOT</span><span style="color: orange;"> </span><span style="color: orange;">NULL</span><span style="color: orange;"> </span><span style="color: orange;">DEFAULT</span><span style="color: orange;"> </span><span style="color: orange;">'0'</span><span style="color: orange;">;</span><br />
<br />
This adds a field 'is_banned' in the 'users' table. Set default values to zero.<br />
<br />
2. Now copy-paste following code in UsersController::beforeFilter()<br />
file:// app/controllers/users_controller.php<br />
<br />
<span style="color: orange;">$this->Auth->userScope = array('User.is_banned' => 0);</span><br />
<br />
<b><span style="font-weight: normal;">3. Done. Cake will not allow users to login, when you have set 'is_banned' = 1.</span> </b><br />
<b>Step 5: Email Validation during user registration</b><br />
The code is pretty long and nicely explained <a href="http://www.jonnyreeves.co.uk/2008/06/cakephp-activating-user-account-via-email/">here</a>. To run with my User model (based on CakePHP's default ACL Component), I needed to make some small adjustment. So, I think it is better to give the codes intact here.<br />
<br />
file:// app/controllers/users_controller.php<br />
<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;"> uses('sanitize');</span><br />
<span style="color: orange;">class UsersController extends AppController {</span><br />
<div><br />
</div><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"> var $name = 'Users';<br />
<span style="white-space: pre;"> </span>var $components = array('Email','Auth');<br />
/* "Email' component will handle emailing tasks, 'Auth' component will handle User Management */<br />
<span style="white-space: pre;"> </span>var $helpers = array('Html', 'Form');<br />
<br />
/* ..... member functions will go here ... */<br />
}<br />
<br />
<span style="color: black;"><b>function beforeFilter()</b></span><br />
<span style="color: black;"></span><br />
<span style="color: black;">/* CakePHP CallBack methods */<br />
<span style="color: orange;">function beforeFilter() {</span><br />
<span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">parent::beforeFilter(); </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Email->delivery = 'debug'; /* used to debug email message */</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Auth->autoRedirect = false; /* this allows us to run further checks on login() action.*/</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Auth->allow('register', 'thanks', 'confirm', 'logout'); </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Auth->userScope = array('User.is_banned' => 0); /* admin can ban a user by updating `is_banned` field of users table to '1' */</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<br />
<span style="font-weight: bold;">function register()</span><br />
</span></span><br />
// Allows a user to sign up for a new account<br />
<span style="color: orange;"> function register() {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> if (!empty($this->data)) {</span><br />
<span style="color: orange;"> // Applying Auth Components's Password Hashing Rules</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">/*</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">We have commented the following field as this was double-hashing password.</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Auth->password($this->data['User']['passwrd']); </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">*/</span><span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">// $this->data['User']['passwrd'] = $this->Auth->password($this->data['User']['passwrd']);</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> $this->User->data = Sanitize::clean($this->data);</span><br />
<span style="color: orange;"> </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">// Successfully created account – send activation email </span><br />
<span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> if ($this->User->save()) {</span><br />
<span style="color: orange;"> $this->__sendActivationEmail($this->User->getLastInsertID());</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">// pr($this->Session->read('Message.email')); /*Uncomment this code to view the content of email FOR DEBUG */</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;"> // this view is not show / listed – use your imagination and inform</span><br />
<span style="color: orange;"> // users that an activation email has been sent out to them.</span><br />
<span style="color: orange;"> $this->redirect('/users/thanks');</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> // Failed, clear password field</span><br />
<span style="color: orange;"> else {</span><br />
<span style="color: orange;"> $this->data['User']['passwrd'] = null;</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> }</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$groups = $this->User->Group->find('list');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->set(compact('groups'));</span><br />
<span style="color: orange;"> }</span><br />
<br />
<br />
<b>Function login()</b><br />
<br />
<br />
<span style="color: orange;">function login() {</span><br />
<span style="color: orange;"> // Check for incoming login request.</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">//pr($this->data);</span><br />
<span style="color: orange;"> if ($this->data) {</span><br />
<span style="color: orange;"> // Use the AuthComponent's login action</span><br />
<span style="color: orange;"> if ($this->Auth->login($this->data)) {</span><br />
<span style="color: orange;"> // Retrieve user data</span><br />
<span style="color: orange;"> $results = $this->User->find(array('User.username' => $this->data['User']['username']), array('User.active'), null, false);</span><br />
<span style="color: orange;"> // Check to see if the User's account isn't active</span><br />
<span style="color: orange;"> if ($results['User']['active'] == 0) {</span><br />
<span style="color: orange;"> // Uh Oh!</span><br />
<span style="color: orange;"> $this->Session->setFlash('Your account has not been activated yet!');</span><br />
<span style="color: orange;"> $this->Auth->logout();</span><br />
<span style="color: orange;"> $this->redirect('/users/login');</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> // Cool, user is active, redirect post login</span><br />
<span style="color: orange;"> else {</span><br />
<span style="color: orange;"> $this->redirect('/');</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> }</span><br />
<span style="white-space: pre;"> </span><br />
<span style="white-space: pre;"></span><b>function logout()</b><br />
<span style="color: orange;">function logout() {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Session->setFlash('Good-Bye');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->redirect($this->Auth->logout());</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">/* function to validate activation link</span><br />
<span style="color: orange;">* </span><br />
<span style="color: orange;">* and to set 'active' = 1</span><br />
<span style="color: orange;">*/ </span><br />
<br />
<b>function activate()</b><br />
<br />
<span style="color: orange;">function activate($user_id = null, $in_hash = null) {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> $this->User->id = $user_id;</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if ($this->User->exists() && ($in_hash == $this->User->getActivationHash())) {</span><br />
<span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if (empty($this->data)) {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->data = $this->User->read(null, $user_id);</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> // Update the active flag in the database</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->User->set('active', 1);</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->User->save();</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Session->setFlash('Your account has been activated, please log in below.');</span><br />
<span style="color: orange;"> $this->redirect('login');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> // Activation failed, render '/views/user/activate.ctp' which should tell the user.</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<b><span style="font-weight: normal;"><br />
</span></b><br />
<b>function __sendActivationEmail()</b><br />
<br />
/* function to send activation email */<br />
<span style="color: orange;"> function __sendActivationEmail($user_id) {</span><br />
<span style="color: orange;"> $user = $this->User->find(array('User.id' => $user_id), array('User.email', 'User.username','User.id'), null, false);</span><br />
<span style="color: orange;"> if ($user === false) {</span><br />
<span style="color: orange;"> debug(__METHOD__." failed to retrieve User data for user.id: {$user_id}");</span><br />
<span style="color: orange;"> return false;</span><br />
<span style="color: orange;"> }</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> // Set data for the "view" of the Email</span><br />
<span style="color: orange;"> $this->set('activate_url', 'http://' . env('SERVER_NAME') . '/users/activate/' . $user['User']['id'] . '/' . $this->User->getActivationHash());</span><br />
<span style="color: orange;"> $this->set('username', $this->data['User']['username']);</span><br />
<span style="color: orange;"> </span><br />
<span style="color: orange;"> $this->Email->to = $user['User']['email'];</span><br />
<span style="color: orange;"> $this->Email->subject = env('SERVER_NAME') . ' – Please confirm your email address';</span><br />
<span style="color: orange;"> $this->Email->from = 'noreply@' . env('SERVER_NAME');</span><br />
<span style="color: orange;"> $this->Email->template = 'user_confirm';</span><br />
<span style="color: orange;"> $this->Email->sendAs = 'text'; // you probably want to use both :) </span><br />
<span style="color: orange;"> return $this->Email->send();</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
<span style="color: orange;"> }</span><br />
<br />
Copy paste <b>f</b><span style="font-weight: bold;">unction getActivationHash </span>at file:// app/models/user.php<br />
<br />
<span style="color: orange;">function getActivationHash()</span><br />
<span style="color: orange;"> {</span><br />
<span style="color: orange;"> if (!isset($this->id)) {</span><br />
<span style="color: orange;"> return false;</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> return substr(Security::hash(Configure::read('Security.salt') . $this->field('created') . date('Ymd')), 0, 8);</span><br />
<span style="color: orange;"> }</span><br />
<b>Copy-paste following code in the file:// app/app_controller.php inside the function beforeFilter()</b><br />
function beforeFilter() {<br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Auth->fields = array('username' => 'username', 'password' => 'passwrd');</span><br />
<span style="color: orange;"> /* ... Rest of the function body goes here */</span><br />
}<br />
<br />
<b>Now View Files</b><br />
<b><br />
</b><br />
<b>Registration form</b><br />
file:// app/views/users/register.ctp<br />
<br />
<br />
<br />
<span style="color: orange;"><h2>Create an Account</h2></span><br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">echo $form->create('User', array('action' => 'register'));</span><br />
<span style="color: orange;">echo $form->input('username');</span><br />
<span style="color: orange;">// Force the FormHelper to render a password field, and change the label.</span><br />
<span style="color: orange;">echo $form->input('group_id', array('type' => 'hidden', 'value' => 'Insert-Default-Value'));</span><br />
<span style="color: orange;">echo $form->input('passwrd', array('type' => 'password', 'label' => 'Password'));</span><br />
<span style="color: orange;">echo $form->input('email', array('between' => 'We need to send you a confirmation email to check you are human.'));</span><br />
<span style="color: orange;">echo $form->submit('Create Account');</span><br />
<span style="color: orange;">echo $form->end();</span><br />
<span style="color: orange;">?></span><br />
<br />
<b>Notice replace</b> '<span class="Apple-style-span" style="color: orange;">Insert-Default-Value</span>'<span class="Apple-style-span" style="color: orange;"> </span>with the actual value of your group_id.<br />
<span class="Apple-style-span" style="color: orange;"> </span><br />
<b>Login form</b><br />
file:// app/views/users/login.ctp<br />
<br />
<br />
<span style="color: orange;"></span><br />
<span style="color: orange;"><?php<br />
echo $form->create('User', array('action' => 'login'));<br />
echo $form->input('username');<br />
echo $form->input('passwrd', array('label' => 'Password', 'type' => 'password'));<br />
echo $form->end('Login');<br />
?><br />
</span><br />
<br />
<br />
<b>user_confirm.ctp</b><br />
file:// app/views/elements/email/text/user_confirm.ctp<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;"> # /app/views/elements/email/text/user_confirm.ctp</span><br />
<span style="color: orange;"> ?></span><br />
<span style="color: orange;"> Hey there <?= $username ?>, we will have you up and running in no time, but first we just need you to confirm your user account by clicking the link below:</span><br />
<span style="color: orange;"> <?= $activate_url ?></span><br />
<br />
<div>With all the above scripts, you should be able to get a workable user registration system.<br />
</div><div>Here, you will have groups/ users/ and you can set group level access per controller, even per action following Cake's default mechanism!<br />
</div><div><br />
</div><div><b>[Acknowledgements]</b><br />
</div><div>My sincere regards to Jonny Revees for his wonderful work on <a href="http://www.jonnyreeves.co.uk/2008/06/cakephp-activating-user-account-via-email/">this</a> <a href="http://www.jonnyreeves.co.uk/2008/06/cakephp-activating-user-account-via-email/">CakePHP user registration</a> system. It works like a charm!<br />
</div><div><br />
</div><br />
<span style="font-weight: bold;">Here are some more stuff I found helpful:</span><br />
CakePHP <a href="http://book.cakephp.org/view/248/AuthComponent-Variables">Auth Component</a> variables.<br />
<a href="http://justkez.com/understanding-cakephp-sessions/">Understanding CakePHP Session</a><br />
<a href="http://book.cakephp.org/view/75/Saving-Your-Data">Saving data</a> in CakePHP found in <a href="http://book.cakephp.org/">book.cakephp.org</a><a href="http://justkez.com/understanding-cakephp-sessions/"></a><br />
<a href="http://debuggable.com/posts/make-your-life-easier-with-these-five-cakephp-quicktips:48170ee5-0cc0-4815-af60-7c264834cda3">Debuggable.com</a> - this post explains how to debug CakePHP email.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com9tag:blogger.com,1999:blog-611277469305933739.post-82928412922497550862009-11-15T22:21:00.000-08:002009-11-15T22:23:10.579-08:00How to List Posts by CategoriesThere's a lot to bake with Cake. I'm entering into deeper domains. I hope you are also following me.<br />
Today, I'll show you how to list posts by categories. To do so, we will use '<a href="http://book.cakephp.org/view/474/Containable">containable</a>' behavior.<br />
<br />
<b>Edit Category Model</b><br />
file:// app/models/category.php<br />
Replace:<br />
<span style="color: orange;">var $actsAs = array('Tree');</span><br />
With<br />
<span style="color: orange;">var $actsAs = array('Tree','Containable');</span><br />
Notice I have added the word '<b>Containable</b>' in the $actsAs <a href="http://book.cakephp.org/view/88/Behaviors">behavior</a>.<br />
<br />
<b>Add listposts() 'action' in Category Controller</b><br />
file:// app/controllers/categories_controller.php<br />
<br />
<span style="color: orange;">function listposts() {</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$listPosts = $this->Category->find('all');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->set(compact('listPosts'));</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<b>Create a VIEW file for showing query result.</b><br />
file:// app/views/categories/listposts.ctp<br />
<br />
<br />
<b></b><br />
<b><span style="font-weight: normal;"><span style="color: orange;"><h1>Posts found by category</h1></span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> <?php</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> foreach ($listPosts as $key => $value)</span></span><span style="white-space: pre;"><span style="font-weight: normal;"><span style="color: orange;"> </span></span></span><span style="font-weight: normal;"><span style="color: orange;">{</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> </span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> echo "<h3>" . $value["Category"]["name"] . "</h3>";</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> $posts = $value["Post"];</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> foreach ($posts as $post) {</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> echo "<b>" . $post["title"] . "</b>";</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> echo "<br />";</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> }</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> }</span></span><br />
<span style="font-weight: normal;"><span style="color: orange;"> ?></span></span><br />
</b><br />
<b><div><br />
</div><div>Now point your browser to:<br />
</div><div><span style="font-weight: normal;">http://caketest.local/categories/listposts</span><br />
</div><div><span style="font-weight: normal;"><br />
</span><br />
</div><div><span style="font-weight: normal;">You should see something like this:</span><br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQOoMymNsrSJtRoRZKHjqKkIHNiqlF-knOzIUcf0TBnb8QjixoafWJ34C9Ib1nZ0O83GRN0Srgx950meVqSlH6urfIlhVFizm-Meub9nR_aD7zmMynNykuU8zTAZkgn21YXVaQmEMFebM/s1600/list-2009-11-16+11+48+54.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhQOoMymNsrSJtRoRZKHjqKkIHNiqlF-knOzIUcf0TBnb8QjixoafWJ34C9Ib1nZ0O83GRN0Srgx950meVqSlH6urfIlhVFizm-Meub9nR_aD7zmMynNykuU8zTAZkgn21YXVaQmEMFebM/s320/list-2009-11-16+11+48+54.png" /></a><br />
</div><div><span style="font-weight: normal;"><br />
</span><br />
</div><div>That's it!<br />
</div></b>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0tag:blogger.com,1999:blog-611277469305933739.post-67794027290072677422009-11-14T22:00:00.000-08:002009-11-14T22:45:13.473-08:00How to Join Database Tables (Models) in CakePHPCakePHP has four association types to handle all database table (model) joining operations.<br />
1. hasOne<br />
2. hasMany<br />
3. belongsTo<br />
4. hasAndBelongsToMany (HABTM)<br />
<br />
In our database model, each category should have many posts.<br />
First add a foreign key, category_id. in the post table.<br />
SQL:<br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">ALTER TABLE `posts` ADD `category_id` INT NOT NULL AFTER `id` ;</span><br />
<br />
<b>Foreign Key Convention</b><br />
<i>Notice the use of (model_name)_id field in the post table. This is a Cake's convention to name foreign key in related tables. Also notice that I have used category_id, and not <span style="text-decoration: line-through;">categories_id</span>. So, the foreign key rule is to name the foreign key field as (model_name_in_singular)_id in the related table. That's it.</i><br />
<br />
Now I'll update both category model and post model to include their association.<br />
<br />
<b>Category Model</b><br />
File: // app/models/category.php<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">class Category extends AppModel {</span><br />
<span style="color: orange;">var $name = 'Category';</span><br />
<span style="color: orange;">var $actsAs = array('Tree');</span><br />
<span style="color: orange;">var $hasMany = 'Post'; /* each category has many posts */</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;">?></span><br />
<br />
<b>Post Model</b><br />
File: // app/models/post.php<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">class Post extends AppModel {</span><br />
<span style="color: orange;">var $name = 'Post';</span><br />
<span style="color: orange;">var $belongsTo = 'Category'; /* each post belongs to a category */</span><br />
<span style="color: orange;">var $validate = array(</span><br />
<span style="color: orange;">'title' => 'notEmpty',</span><br />
<span style="color: orange;">'body' => 'notEmpty'</span><br />
<span style="color: orange;">);</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;">?></span><br />
<br />
<b>Modify PostsController Class</b><br />
Now in posts_controller.php, modify your add function.<br />
file: // app/controllers/posts_controller.php<br />
<br />
<br />
<span style="color: orange;"> function add() {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> if (!empty($this->data)) {</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if ($this->Post->save($this->data)) {</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Session->setFlash('Your post has been saved.');</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->redirect(array('action' => 'index'));</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">} else {</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->set('categories', $this->Post->Category->generatetreelist(null,null,null," - "));</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> }</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<br />
<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Note:<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">$this->set('categories', $this->Post->Category->generatetreelist(null,null,null," - "));<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">This will fetch the category tree from categories table.<br />
</div><div><br />
</div><div><b>Modify Related Views to show category tree.</b><br />
</div><div>file: // app/views/posts/add.ctp<br />
</div><div><div><br />
</div><div><span style="color: orange;"><h1>Add Post</h1></span><br />
</div><div><span style="color: orange;"><?php</span><br />
</div><div><span style="color: orange;">echo $form->create('Post');</span><br />
</div><div><span style="color: orange;">echo $form->input('category_id',array('label'=>'Select a category'));</span><br />
</div><div><span style="color: orange;">echo $form->input('title');</span><br />
</div><div><span style="color: orange;">echo $form->input('body', array('rows' => '3'));</span><br />
</div><div><span style="color: orange;">echo $form->end('Save Post');</span><br />
</div><div><span style="color: orange;">?></span><br />
</div></div><br />
<br />
<br />
Now, point your browser to:<br />
http://caketest.local/posts/add<br />
<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw6CXbwWrMYDCXvvEPbRATfyob8wV5NIv_NQqLhjhXWQAumFrFlb0zvddvUIFekn5NSjH_seudwuwz87nD21K1Ii7za9tmPWzqfPr_BPWBlkn9OchEP6vo6q5lo4WaAOD862iVi4_8Hyc/s1600-h/cat-2009-11-15+11+16+25.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw6CXbwWrMYDCXvvEPbRATfyob8wV5NIv_NQqLhjhXWQAumFrFlb0zvddvUIFekn5NSjH_seudwuwz87nD21K1Ii7za9tmPWzqfPr_BPWBlkn9OchEP6vo6q5lo4WaAOD862iVi4_8Hyc/s320/cat-2009-11-15+11+16+25.png" /></a><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjw6CXbwWrMYDCXvvEPbRATfyob8wV5NIv_NQqLhjhXWQAumFrFlb0zvddvUIFekn5NSjH_seudwuwz87nD21K1Ii7za9tmPWzqfPr_BPWBlkn9OchEP6vo6q5lo4WaAOD862iVi4_8Hyc/s1600-h/cat-2009-11-15+11+16+25.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><br />
</a><br />
</div>In this example: Cake has created the magical associations to take care of everything. Cake generates Category Tree, displays it in the form, and save category_id in the posts table on the fly.<br />
<br />
For a complete tutorial on Models, Saving/ Retrieving Data, and building associations between different models in CakePHP, please see <a href="http://book.cakephp.org/view/66/Models">this</a> tutorial.<br />
<br />
Now in my next example, I'll try to list posts by categories.<br />
<br />
Take care.<br />
<br />
<b>Update</b><br />
Besides, you might just want to update posts as well.<br />
<br />
<b>Modify PostsController</b><br />
Modify edit() function in the following file.<br />
File: // app/controllers/posts_controller.php<br />
<br />
<span style="color: orange;">function edit($id = null) {</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Post->id = $id;</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if (empty($this->data)) {</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->data = $this->Post->read();</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->set('categories', $this->Post->Category->generatetreelist(null,null,null," - "));</span><br />
<span style="color: orange;"><br />
</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">} else {</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">if ($this->Post->save($this->data)) {</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->Session->setFlash('Your post has been updated.');</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">$this->redirect(array('action' => 'index'));</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<span class="Apple-tab-span" style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">}</span><br />
<br />
<b>2. Now modify post view</b><br />
file: // app/views/posts/edit.php<br />
<br />
<br />
<span style="color: orange;"><h1>Edit Post</h1></span><br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">echo $form->create('Post', array('action' => 'edit'));</span><br />
<span style="color: orange;">echo $form->input('category_id',array('label'=>'Select a category'));</span><br />
<span style="color: orange;">echo $form->input('title');</span><br />
<span style="color: orange;">echo $form->input('body', array('rows' => '3'));</span><br />
<span style="color: orange;">echo $form->input('id', array('type'=>'hidden')); </span><br />
<span style="color: orange;">echo $form->end('Save Post');</span><br />
<span style="color: orange;">?></span><br />
<br />
Now if you try to edit an existing post, you can see the category tree with the selected category being displayed.<br />
<b>Done.</b>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com1tag:blogger.com,1999:blog-611277469305933739.post-53353714760484797992009-11-14T01:15:00.000-08:002009-11-14T02:21:24.837-08:00How to Create a Category Tree with CakePHP 'Tree' behaviorOkay! Let's try to create a category tree using CakePHP (This is something like parent category -> child category type records).<br />
<br />
<b>SQL:</b><br />
<br />
<span style="color: orange;">CREATE TABLE categories (</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">parent_id INTEGER(10) DEFAULT NULL,</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">lft INTEGER(10) DEFAULT NULL,</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">rght INTEGER(10) DEFAULT NULL,</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">name VARCHAR(255) DEFAULT '',</span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">PRIMARY KEY (id)</span><br />
<span style="color: orange;">);</span><br />
<br />
Now insert some record:<br />
<span style="color: orange;">INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(1, 'Tutorials', NULL, 1, 8);</span><br />
<span style="color: orange;">INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(2, 'PHP', 1, 2, 5);</span><br />
<span style="color: orange;">INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(3, 'MySQL', 1, 6, 7);</span><br />
<span style="color: orange;">INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(4, 'CakePHP', 2, 3, 4);</span><br />
<br />
Now I'll create a model for this category.<br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">1. Create a new file.<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">2. Copy-paste the following code:<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="color: orange;"><?php</span><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">class Category extends AppModel { </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">var $name = 'Category';</span><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="color: orange;"> </span><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">var $actsAs = array('Tree'); </span><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;">} </span><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><span style="color: orange;">?></span><br />
</div><br />
<div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">3. Save the files as app/models/category.php.<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;"><br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">Note:<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">The variable $actsAs tells Cake to attach 'Tree' behavior to this model, i.e., Cake will generate a Tree data structure for category model. I think it is also a good time to introduce you with another fascinating feature of CakePHP - 'Behaviors'. CakePHP has built-in behaviors, like - behaviors for tree structures, translated content, access control list interaction etc., which you can attach with any model. As you might know - 'add', 'edit', 'delete' options for these type of data structures need special care. Cake takes care of it once you have specified the applicable 'behavior' in the model. Behaviors are attached with models using $actsAs variable. In this case, I have specified $actsAs = array('Tree'). This will enforce 'Tree' behavior on Category model. Simple.<br />
</div><div style="margin-bottom: 0px; margin-left: 0px; margin-right: 0px; margin-top: 0px;">To learn more about 'Behaviors', please refer to <a href="http://book.cakephp.org/view/88/Behaviors">CakePHP online book</a>.<br />
</div><div><br />
</div><span style="font-weight: bold;">Now I'll create CategoriesController</span><br />
Step:<br />
1. Create a new file.<br />
2. Copy-paste the following code.<br />
<br />
<span style="color: orange;"><?php </span><br />
<span style="color: orange;">class CategoriesController extends AppController {</span><br />
<span style="color: orange;"> var $name = 'Categories'; </span><br />
<span style="color: orange;"> </span><br />
<span style="white-space: pre;"><span style="color: orange;"> </span></span><span style="color: orange;"> function index() {</span><br />
<span style="color: orange;"> $categories = $this->Category->generatetreelist(null, null, null, '&nbsp;&nbsp;&nbsp;');</span><br />
<span style="color: orange;"> $this->set(compact('categories')); </span><br />
<span style="color: orange;"> } </span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;">?></span><br />
3. Save that file as categories_controller.php under 'app/controllers' folder.<br />
<br />
Note: generatetreelist() method generates a tree-type views for our Categories. There are lots of options you can use with this method. For a complete guidelines on options for this method, please refer to <a href="http://book.cakephp.org/view/517/generatetreelist">CakePHP book</a>.<br />
<a href="http://php.net/manual/en/function.compact.php">compact()</a>; function is used to pass variables to your views in CakePHP. Compact() method detects the variables having the same name (in this case 'categories') in your Controller and splits them as an array() of $key => value pairs. Now $this->set() is used to set those values for using them in your view file.<br />
<br />
<b>Now I'll create a view for our index() function.</b><br />
file: '/app/views/categories/index.php'<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">echo $html->link("Add Category",array('action'=>'add'));</span><br />
<span style="color: orange;">echo "<ul>";</span><br />
<span style="color: orange;"> foreach($categories as $key=>$value){</span><br />
<span style="color: orange;"> echo "<li>$value</li>";</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> echo "</ul>";</span><br />
<span style="color: orange;">?></span><br />
<span style="color: orange;"><br />
</span><br />
<b>Now point your browser to:</b><br />
http://caketest.local/categories<br />
<br />
And you should see following structure:<br />
<br />
> Tutorials <br />
> PHP <br />
<span style="white-space: pre;"> </span>> CakePHP <br />
<span style="white-space: pre;"> </span>> MySQL<br />
<br />
<b>To Add a new category to the list:</b><br />
1. Open categories_controller.php (found under '/app/controllers')<br />
2. Copy-paste the following function:<br />
<br />
<br />
<span style="color: orange;">function add() {</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">if (!empty($this -> data) ) {</span><br />
<span style="color: orange;">$this->Category->save($this -> data);</span><br />
<span style="color: orange;">$this->Session->setFlash('A new category has been added');</span><br />
<span style="color: orange;">$this->redirect(array('action' => 'index'));</span><br />
<span style="color: orange;">} else {</span><br />
<span style="color: orange;">$parents[0] = "[Top]";</span><br />
<span style="color: orange;">$categories = $this->Category->generatetreelist(null,null,null," - ");</span><br />
<span style="color: orange;">if($categories) {</span><br />
<span style="color: orange;">foreach ($categories as $key=>$value)</span><br />
<span style="color: orange;">$parents[$key] = $value;</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;">$this->set(compact('parents'));</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">}</span><br />
<br />
3. Save this file.<br />
<br />
Now we need to create a view file for this add() method (to display the add category form).<br />
<br />
1. Create a new file.<br />
2. Copy-paste the following code:<br />
<br />
<br />
<span style="color: orange;"><h1>Add a new category</h1></span><br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">echo $form->create('Category');</span><br />
<span style="color: orange;">echo $form->input('parent_id',array('label'=>'Parent'));</span><br />
<span style="color: orange;">echo $form->input('name',array('label'=>'Name'));</span><br />
<span style="color: orange;">echo $form->end('Add');</span><br />
<span style="color: orange;">?></span><br />
<br />
3. Save the file as '/app/views/categories/add.ctp'<br />
<br />
Now point your browser to this location:<br />
http://caketest.local/categories/add<br />
<br />
You should be able to add a new category.<br />
<br />
<b>EDIT Category</b><br />
To edit category, I'll specify a controller action. To do so:<br />
1. Open categories_controller.php (found under '/app/controllers').<br />
2. Copy-paste the following function:<br />
<br />
<br />
<span style="color: orange;">function edit($id=null) {</span><br />
<span style="color: orange;">if (!empty($this->data)) {</span><br />
<span style="color: orange;">if($this->Category->save($this->data)==false)</span><br />
<span style="color: orange;">$this->Session->setFlash('Error saving Node.');</span><br />
<span style="color: orange;">$this->redirect(array('action'=>'index'));</span><br />
<span style="color: orange;">} else {</span><br />
<span style="color: orange;">if($id==null) die("No ID received");</span><br />
<span style="color: orange;">$this->data = $this->Category->read(null, $id);</span><br />
<span style="color: orange;">$parents[0] = "[ Top ]";</span><br />
<span style="color: orange;">$categories = $this->Category->generatetreelist(null,null,null," - ");</span><br />
<span style="color: orange;">if($categories) </span><br />
<span style="color: orange;">foreach ($categories as $key=>$value)</span><br />
<span style="color: orange;">$parents[$key] = $value;</span><br />
<span style="color: orange;">$this->set(compact('parents'));</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;"><br />
</span><br />
3. Save that function.<br />
<br />
Now, I'll write the view file (the form to edit a category). To do so:<br />
1. Create a new file.<br />
2. Copy paste the following code:<br />
<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;">echo $html->link('Back',array('action'=>'index'));</span><br />
<span style="color: orange;">echo $form->create('Category');</span><br />
<span style="color: orange;"> echo $form->hidden('id');</span><br />
<span style="color: orange;"> echo $form->input('name');</span><br />
<span style="color: orange;"> echo $form->input('parent_id', array('selected'=>$this->data['Category']['parent_id']));</span><br />
<span style="color: orange;"> echo $form->end('Update');</span><br />
<span style="color: orange;">?></span><br />
<div><br />
</div><div>3. Now save the file as '/app/views/categories/edit.ctp'.<br />
</div><div><br />
</div><div><b>Hold on!</b><br />
</div><div>There is one more thing we should do. We need to show the link to edit record. To do show:<br />
</div><div>1. Open '/app/views/categories/index.ctp' file.<br />
</div><div>2. Replace the existing code with this one:<br />
</div><div><div><br />
</div><div><span style="color: orange;"><?php</span><br />
</div><div><span style="color: orange;">echo $html->link("Add Category",array('action'=>'add'));</span><br />
</div><div><span style="color: orange;">echo "<ul>";</span><br />
</div><div><span style="color: orange;"> foreach($categories as $key=>$value){</span><br />
</div><div><span style="color: orange;">$edit = $html->link("Edit", array('action'=>'edit', $key));</span><br />
</div><div><span style="color: orange;"> echo "<li>$value &nbsp;[$edit]</li>";</span><br />
</div><div><span style="color: orange;"> }</span><br />
</div><div><span style="color: orange;"> echo "</ul>";</span><br />
</div><div><span style="color: orange;">?></span><br />
</div><div><br />
</div><div>3. Now save the file.<br />
</div><div><br />
</div><div>Now point your browser to:<br />
</div><div>http://caketest.local/categories/<br />
</div><div>You should be able to see the 'Edit' option against each category name.<br />
</div><div><br />
</div><div><span style="font-weight: bold;">Delete Category</span><br />
</div><div>CakePHP Format:<br />
</div><div>removeFromTree($id=null, $delete=false)<br />
</div><div><br />
</div><div>Using this method will either delete [to delete, set ($delete=true)] or move a node but retain its sub-tree, which will be re-parented one level higher.<br />
</div><div><br />
</div><div>Steps:<br />
</div><div>1. Open '/app/controllers/categories_controller.php'<br />
</div><div>2. Copy paste the following code:<br />
</div><div><br />
</div><div><div><span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"></span><br />
<span style="color: orange;"><div>function delete($id=null) {<br />
</div><div> if($id==null)<br />
</div><div> die("No ID received");<br />
</div><div> $this->Category->id=$id;<br />
</div><div> if($this->Category->removeFromTree($id,true)==false)<br />
</div><div> $this->Session->setFlash('The Category could not be deleted.');<br />
</div><div> $this->Session->setFlash('Category has been deleted.');<br />
</div><div> $this->redirect(array('action'=>'index'));<br />
</div><div>}<br />
</div></span><br />
</div><div>3. Now save that file.<br />
</div><div><br />
</div></div><div>Next, I'll display the option to 'delete' a category.<br />
</div><div>Step:<br />
</div><div>1. Open '/app/views/categories/index.ctp<br />
</div><div>2. Replace the existing code with this one:<br />
</div><div><br />
</div><div><div><span style="color: orange;"><?php</span><br />
</div><div><span style="color: orange;">echo $html->link("Add Category",array('action'=>'add'));</span><br />
</div><div><span style="color: orange;">echo "<ul>";</span><br />
</div><div><span style="color: orange;"> foreach($categories as $key=>$value){</span><br />
</div><div><span style="color: orange;">$edit = $html->link("Edit", array('action'=>'edit', $key));</span><br />
</div><div><span style="color: orange;"> $delete = $html->link("Delete", array('action'=>'delete', $key));</span><br />
</div><div><span style="color: orange;"> echo "<li>$value &nbsp;[$edit]&nbsp;[$delete]</li>";</span><br />
</div><div><span style="color: orange;"> }</span><br />
</div><div><span style="color: orange;"> echo "</ul>";</span><br />
</div><div><span style="color: orange;">?></span><br />
</div><div>3. Save the file.<br />
</div><div><br />
</div><div><b>Done</b><br />
</div><div>Point your browser to:<br />
</div><div>http://caketest.local/categories<br />
</div><div>Here is a screenshot of what you should see:<br />
</div><div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy_VFF1mtx12ekxDdnPN5QG7d3dFHe-rhi4X2nT7GW1tNxdjoxMleK8QToRFk3ajZv_ywNrrT9Pq9LYMnRtFTCgk3C9MAYiF7KL4yN8-oXb4xeYga6zhY-T5vtSoLv51A3tDFTBwDSK20/s1600-h/delete-2009-11-14+14+33+14.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEjy_VFF1mtx12ekxDdnPN5QG7d3dFHe-rhi4X2nT7GW1tNxdjoxMleK8QToRFk3ajZv_ywNrrT9Pq9LYMnRtFTCgk3C9MAYiF7KL4yN8-oXb4xeYga6zhY-T5vtSoLv51A3tDFTBwDSK20/s320/delete-2009-11-14+14+33+14.png" /></a><br />
</div><div><br />
</div><div>[<b>ACKNOWLEDGEMENT</b>]<br />
</div><div>The code above is mostly based on<br />
</div><div>Bram Borggreve's beautiful website - <a href="http://bvirtual.nl/2009/11/easy-trees-with-tree-behavior-in.html">Tree Behavior</a><br />
I express my sincere gratitude to Bram for his wonderful contribution.<br />
</div><div>Further, to learn more about 'Tree' behavior, please visit: <a href="http://book.cakephp.org/view/91/Tree">CakePHP Book</a>.<br />
<br />
<br />
<br />
<br />
<br />
<span style="font-weight: bold;">Here is the COMPLETE script files:</span><br />
<br />
<b>1. categories_controller.php ('to be saved under '/app/controllers')</b><br />
<br />
<br />
<span style="color: orange;"><?php</span><br />
<span style="color: orange;"> class CategoriesController extends AppController {</span><br />
<span style="color: orange;"> var $name = 'Categories';</span><br />
<span style="color: orange;"> function index() {</span><br />
<span style="color: orange;"> $categories = $this->Category->generatetreelist(null, null, null, '&nbsp;&nbsp;&nbsp;');</span><br />
<span style="color: orange;"> // debug ($this->data); die; </span><br />
<span style="color: orange;"> $this->set(compact('categories')); </span><br />
<span style="color: orange;"> </span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> </span><br />
<span style="color: orange;"> function add() {</span><br />
<span style="color: orange;"> </span><br />
<span style="color: orange;"> if (!empty($this -> data) ) {</span><br />
<span style="color: orange;"> $this->Category->save($this -> data);</span><br />
<span style="color: orange;"> $this->Session->setFlash('A new category has been added');</span><br />
<span style="color: orange;"> $this->redirect(array('action' => 'index'));</span><br />
<span style="color: orange;"> } else {</span><br />
<span style="color: orange;"> $parents[0] = "[ Top ]";</span><br />
<span style="color: orange;"> $categories = $this->Category->generatetreelist(null,null,null," - ");</span><br />
<span style="color: orange;"> if($categories) {</span><br />
<span style="color: orange;"> foreach ($categories as $key=>$value)</span><br />
<span style="color: orange;"> $parents[$key] = $value;</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> $this->set(compact('parents'));</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> </span><br />
<span style="color: orange;"> }</span><br />
<br />
<span style="color: orange;"> function edit($id=null) {</span><br />
<span style="color: orange;"> if (!empty($this->data)) {</span><br />
<span style="color: orange;"> if($this->Category->save($this->data)==false)</span><br />
<span style="color: orange;"> $this->Session->setFlash('Error saving Category.');</span><br />
<span style="color: orange;"> $this->redirect(array('action'=>'index'));</span><br />
<span style="color: orange;"> } else {</span><br />
<span style="color: orange;"> if($id==null) die("No ID received");</span><br />
<span style="color: orange;"> $this->data = $this->Category->read(null, $id);</span><br />
<span style="color: orange;"> $parents[0] = "[ Top ]";</span><br />
<span style="color: orange;"> $categories = $this->Category->generatetreelist(null,null,null," - ");</span><br />
<span style="color: orange;"> if($categories) </span><br />
<span style="color: orange;"> foreach ($categories as $key=>$value)</span><br />
<span style="color: orange;"> $parents[$key] = $value;</span><br />
<span style="color: orange;"> $this->set(compact('parents'));</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"> function delete($id=null) {</span><br />
<span style="color: orange;"> if($id==null)</span><br />
<span style="color: orange;"> die("No ID received");</span><br />
<span style="color: orange;"> $this->Category->id=$id;</span><br />
<span style="color: orange;"> if($this->Category->removeFromTree($id,true)==false)</span><br />
<span style="color: orange;"> $this->Session->setFlash('The Category could not be deleted.');</span><br />
<span style="color: orange;"> $this->Session->setFlash('Category has been deleted.');</span><br />
<span style="color: orange;"> $this->redirect(array('action'=>'index'));</span><br />
<span style="color: orange;"> }</span><br />
<span style="color: orange;"><br />
</span><br />
<span style="color: orange;">}</span><br />
<span style="color: orange;"> ?></span><br />
<div><br />
</div><div><b>2. Category Model (file: '/app/models/category.php')</b><br />
</div><div><br />
</div><div><span style="color: orange;"><?php</span><br />
</div><div><span style="color: orange;">class Category extends AppModel { </span><br />
</div><div><span style="color: orange;">var $name = 'Category';</span><br />
</div><div><span style="color: orange;">var $actsAs = array('Tree'); </span><br />
</div><div><span style="color: orange;">} </span><br />
</div><div><span style="color: orange;">?> </span><br />
</div><div><br />
</div><div><b>3. Views for Category Files</b><br />
</div><div><b>(a)File: '/app/views/categories/index.php'</b><br />
</div><div><br />
</div><div><span style="color: orange;"><?php</span><br />
</div><div><span style="color: orange;">echo $html->link("Add Category",array('action'=>'add'));</span><br />
</div><div><span style="color: orange;">echo "<ul>";</span><br />
</div><div><span style="color: orange;"> foreach($categories as $key=>$value){</span><br />
</div><div><span style="color: orange;">$edit = $html->link("Edit", array('action'=>'edit', $key));</span><br />
</div><div><span style="color: orange;"> $delete = $html->link("Delete", array('action'=>'delete', $key));</span><br />
</div><div><span style="color: orange;"> echo "<li>$value &nbsp;[$edit]&nbsp;[$delete]</li>";</span><br />
</div><div><span style="color: orange;"> }</span><br />
</div><div><span style="color: orange;"> echo "</ul>";</span><br />
</div><div><span style="color: orange;">?></span><br />
</div><div><br />
</div><br />
<br />
<div><b>(b) File: '/app/views/categories/add.php'</b><br />
</div><div><b></b><br />
<b></b><br />
<b></b><br />
<b><div><span style="font-weight: normal;"><br />
</span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;"><h1>Add a new category</h1></span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;"><?php</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->create('Category');</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->input('parent_id',array('label'=>'Parent'));</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->input('name',array('label'=>'Name'));</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->end('Add');</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">?></span></span><br />
</div><div><span style="font-weight: normal;"><br />
</span><br />
</div><div>(c) File: 'app/views/categories/edit.php'<br />
</div><div><br />
</div><div><div><span style="font-weight: normal;"><span style="color: orange;"><h1>Add a new category</h1></span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;"><?php</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->create('Category');</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->input('parent_id',array('label'=>'Parent'));</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->input('name',array('label'=>'Name'));</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">echo $form->end('Add');</span></span><br />
</div><div><span style="font-weight: normal;"><span style="color: orange;">?></span></span><br />
</div></div></b><br />
</div><div><b><br />
</b><br />
</div><div><b>Thanks for reading the entry.</b><br />
</div></div></div></div>Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com16tag:blogger.com,1999:blog-611277469305933739.post-8524661209262831692009-11-12T20:12:00.000-08:002009-11-12T20:12:47.699-08:00CakePHP - Fine-tune Your Scaffolded ApplicationIn my previous post, I tried to explain how you can create a workable application on the fly using <a href="http://my-cakephp.blogspot.com/2009/11/how-to-develop-php-application-on-fly.html">scaffolding</a>. Now I'll try to show you how to fine tune your scaffolded application. Since, I'll be referring to my <a href="http://my-cakephp.blogspot.com/2009/11/how-to-develop-php-application-on-fly.html">previous post</a> a lot, so, please read that first.<br />
<b><br />
</b><br />
<b>Control Display Fields</b><br />
<br />
In our previous example, say, I want to display only the comments title, body, and created fields. So, I will add the following lines in comments_controller.php (found under '/app/controllers') just below<br />
var $scaffold;<br />
statement.<br />
<br />
<br />
function beforeRender() {<br />
if($this->action === 'index'){<br />
$this->set(<span class="Apple-tab-span" style="white-space: pre;"> </span>'scaffoldFields', array( 'title', 'body', 'created' ) );<br />
}<br />
}<br />
<br />
<br />
Note 'beforeRender()' is a CakePHP callback. It gets executed before the actual controller action. This helps you to add some more logic in your controller. There are three controller callback methods in common use: beforeFilter(), beforeRender(), afterFilter()<br />
<br />
And here is that much desired screenshot:<br />
<div class="separator" style="clear: both; text-align: center;"><a href="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe4kl8tAMVKNS1UNDyh6oQffA-9Q9NrYXyBYqhADk56zsq4Craz_6LFMZziWBBHAZNG2yPND_fA8YoJCbKRcnp5fLR_Scs5BZJ8FKuSWdiH_mUUkfdkRWbDeqOIIoGtDNdFemMp31lhn4/s1600-h/before-render2009-11-13+09+41+49.png" imageanchor="1" style="clear: left; float: left; margin-bottom: 1em; margin-right: 1em;"><img border="0" src="https://blogger.googleusercontent.com/img/b/R29vZ2xl/AVvXsEhe4kl8tAMVKNS1UNDyh6oQffA-9Q9NrYXyBYqhADk56zsq4Craz_6LFMZziWBBHAZNG2yPND_fA8YoJCbKRcnp5fLR_Scs5BZJ8FKuSWdiH_mUUkfdkRWbDeqOIIoGtDNdFemMp31lhn4/s320/before-render2009-11-13+09+41+49.png" /></a><br />
</div><br />
For a more detailed discussion, please go through the <a href="http://book.cakephp.org/view/57/Controller-Methods">book</a>.Siddharthahttp://www.blogger.com/profile/04012747042515614464noreply@blogger.com0