Friday, April 15, 2011

Two Important CakePHP Plugins You Must Use In Your Next Cake Project - ACL Plugin & Facebook Plugin

I 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:

1) ACL plugin
2) facebook plugin

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:

/app/plugins/your-plugin-name/config/config.php

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.

Regarding these two plugins here is what I think.

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.

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.



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 facebook (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.

Once you have installed those plugins, you can access it using the following urls:

http://your-good-domain.com/plugin-name (if you are NOT using admin routing)
http://your-good-domain.com/admin/plugin-name (if you are using admin routing)

Remember installing and using cakePHP plugin is pretty simple. FOLLOW the steps accurately. You must not have any reason to become frustrated anymore. 
Happy Baking!

Links to downloads:

Sunday, December 5, 2010

CakePHP: Tweak With Search, Managing Form Post Data

Nowadays, 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.

USE SESSION VARIABLES.

In your controller setup:

function my_function() {

if(!empty($this->data)){
$this ->Session->write('search',$this->data['Model']['field']);
$search_string =$this->data['Model']['field'];
} else {
$search_string =$this ->Session->read('search');
}

$condition = array('Model.field_name'=>$search_string);
$search_data = $this->Model->find('all',array('conditions'=>$condition));
$this->set('search_data',$search_data);
}

/* in your view file use */
debug($search_data);
/* you can see the recordset, if debug mode is set to 2 or above. */

Hope this helps someone else as well.
Happy baking.

Sunday, August 29, 2010

How to Open a File (xls, doc, pdf etc) through a link in CakePHP

Well this question was discussed in Google Group.
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.

Solution:
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 file upload component. 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.

2. Create a variable name $file_path in the respective view files.

Say,  $file_path='my_file_name.doc';
Now simply create a link to that path.

Saturday, August 21, 2010

Something on CakePHP Notice (8): Undefined Index

I 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.


Settings:

1. You are using proper Model/ Controller/ View setup.
2. You are firing correct SQL statement to fetch records. And database has at least one matching record.
3. Everything is just fine to the best of your knowledge and yet you don't really see any output in your view file.


To debug:


1. Set debug level to '2'.
As such my localhost is configured in that format by default. So, I do not have to change that setting too often. 



2. Read the output in the debug mode very carefully. Here lies the clue.
If you see a message like: 
Notice (8): Undefined index .. blah blah blah
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.


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.

Check the value of the fetched recordset using debug($data) in your controller/action.
If you can see the values as per expectation, move on to your view files.
If you can't see any result, re-frame your find() conditions, examine your controller/action statements very carefully.

4. Check for typos.
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:
my_funny_vars
to:
myFunnyVars

So, in your view file, you need to mention myFunnyVars and not my_funny_vars.
I wasted more than few hours to fix that.

5. Few other tips I have found elsewhere:
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.

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.

Sounds too complicated? That's how CakePHP goes on.
Hope it helps someone, who might have been stumbling with Notice (8): Undefined index!!!

Saturday, August 7, 2010

How to use SEO urls in CakePHP without the ID

CakePHP 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!

I'll refer to the post table.
1. Create a field called 'slug' (must be UNIQUE and NOT NULL) in the post table.

2. Download and use sluggable behavior to create post slug! Follow instructions step-by-step. It works perfectly.

3. Define routing rules in config/router.php file to display SEO friendly urls.

Router::connect(


       '/posts/:slug',


       array(


               'controller' => 'posts',


               'action' => 'view'


       ),


       array(


               'slug' => '[-a-z0-9]+',


               'pass' => array('slug')


       )


);

4. In posts_controller.php view() function modify query,

function view($slug = null)
{
        if (empty($slug))
        {
                // redirect ...
        }
    
         $data = $this->Post->findBySlug($slug) ; 
      
}

You you should be able to access urls of the form:
http://example.com/your-seo-friendly-post-url/

Hope it helps someone.

Friday, June 18, 2010

How to Add Robots Meta Tag to a CakePHP View File

This is a pirated idea... and hats off to Maquel Collado for his wonder post

Adding robots meta-tag to a CakePHP view

You should check the original there. And here is a carbon copy:
Code:


<?php $html->meta('robots', null, array('name' => 'robots', 'content' => 'noindex') ,false); ?>

Add this html helper in its exact form in your view file. 

Output:

<meta name="robots" content="noindex"/> 

And it will appear within the <head> </head>   

And all the well behaved robots (Sure! Google is so) will stop indexing those pages.

Thanks Miquel. You are a genius!

Thursday, May 6, 2010

How to Create Multiple AJAX Forms on Same Page in CakePHP

Settings: Say, your posts/index.ctp page displays the latest ten posts. You want to allow user to rate each post.
Requirement: You MUST have a Post Model and a Comment Model.
In your respective view file: /app/view/posts/view.ctp
Type:

$i = 0; // a counter to create new divs

foreach ($posts as $post) :

// Code to display your post title, body etc.
// Now our comment form for each post

$i++;

$new_comment = 'new_comment_'.$i ; // for comment div id
$form_id = 'form_id_'.$i; // for form id

echo '<div id="'.  $new_comment .'"</div>';

echo $ajax->form(array('type' => 'post', 'options' => array(
'model'=>'Post', 
'update'=>$new_comment,
 'url'=>array('controller'=>'comments','action'=>'add'),
 'id'=>$form_id,'class'=>'CommentForm')
                                        ));

echo $form->input('comment',array('label'=>'Write your comment','type'=>'textarea', 'cols'=>'60','rows'=>'4'));

echo $form->end('Submit'); // close the form

// now close div
echo '</div>';
endforeach;

- - - - - - - - -
The idea is to create unique div to position each form and creating unique id for each form.

I created this post just before leaving for my office on the fly. Let me know if it helps.

Friday, April 30, 2010

Where Should I Upload robots.txt file in CakePHP installation & Why I Thanked Google Webmaster Tool Once Again

For those rather newbies (ME too!), robots.txt 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.

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:

http://your-lovely-domain-name.com/app/webroot/robots.txt 


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.

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.

Lesson today?

ALWAYS DOUBLE CHECK EVERYTHING WHEN YOU ARE GOING WITH CAKEPHP

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.

Thanks.

Thursday, February 18, 2010

CakePHP Pagination & Custom Routes Issue

Custom Routes 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.

The problems may be many-folded which all simplifies to one simple issue:

UNFORMATTED URL
Say, you want to display url in the following format using custom routes

CakePHP default url structure
http://example.com/categories/index/categoryID

Your WELL FORMATTED URL structure:
http://example.com/category-name-ID

Obviously, your custom route element points to 'index' action of 'categories' controller with two parameters - category-name and 'categoryID'.

Router::connect(

 '/:slug-:id/*',
  array('controller' => 'categories', 'action' => 'index'),
  array(
  // order matters
  'pass' => array('slug','id'),
 'id'=> '[0-9]+'
  )
  );

This works perfectly for URLs like
http://example.com/my-first-category-ID1
http://example.com/my-second-category-ID2

But it may cause problem when you try to paginate

Cake will not pick  your params (here 'slug' and 'id') passed through url if you do not force Cake to do so while paginating.  

To fix this issue, you MAY use:

 $paginator->options(array('url' => $this->passedArgs));  
or, as I have told here earlier following CakePHP book.

But this will format your paginated urls like
http://example.com/categories/index/param1/param2/page:xxxx

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. 

You may still get a bad URL.

DO NOT WORRY!

While defining paginator 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:

file:// /app/views/categories/index.php

$paginator->options(array('url'=> array(
'controller' => 'categories', 
  'action' => 'index',
'slug'=>$this->params['slug']),
'id'=>$this->params['id'])
  ));

Now Cake will make well formatted URL automatically, and your paginated url should look like

http://example.com/category-name-id1/page:2
http://example.com/category-name-id1/page:3

Done!
I hope it helps someone.
Does it?

Please Note
I have marked asterisk symbol (*) with RED color while talking about custom route elements. This (*) MUST be there for pagination to work properly. 
Good night.

Saturday, February 13, 2010

How to Find Records using MySQL Match Against Query in CakePHP

To use MySQL Match Against Query in CakePHP:

$needle = 'Search String';

$conditions = array( 
 "MATCH(Post.title) 
  AGAINST('$needle' IN BOOLEAN MODE)" 
  );
 $matches = $this->Post->find('all', array('conditions' => $conditions));

It does not need any explanation. I hope.