Showing posts with label CakePHP. Show all posts
Showing posts with label CakePHP. Show all posts

About PHP data types

In this part of the PHP tutorial, we will talk about data types.
Computer programs work with data. Spreadsheets, text editors, calculators or chat clients. Tools to work with various data types are essential part of a modern computer language. According to the wikipedia definition, a data type is a set of values, and the allowable operations on those values.
PHP has eight data types:
Scalar types
  • boolean
  • integer
  • float
  • string
Compound types
  • array
  • object
Special types
  • resources
  • NULL
Unlike in languages like Java, C or Visual Basic, in PHP you do not provide an explicit type definition for a variable. A variable's type is determined at runtime by PHP. If you assign a string to a variable, it becomes a string variable. Later if you assign an integer value, the variable becomes an integer variable.

Boolean values

There is a duality built in our world. There is a Heaven and Earth, water and fire, jing and jang, man and woman, love and hatred. In PHP the boolean data type is a primitive data type having one of two values: True or False. This is a fundamental data type. Very common in computer programs.
Happy parents are waiting a child to be born. They have chosen a name for both possibilities. If it is going to be a boy, they have chosen John. If it is going to be a girl, they have chosen Victoria.
<?php

$male = False;

$r = rand(0, 1);

$male = $r ? True: False;

if ($male) {
echo "We will use name John\n";
} else {
echo "We will use name Victoria\n";
}
?>
The script uses a random integer generator to simulate our case.
$r = rand(0, 1);
The rand() function returns a random number from the given integer boundaries. In our case 0 or 1.
$male = $r ? True: False;
We use the ternary operator to set a $male variable. The variable is based on the random $r value. If $r equals to 1, the $male variable is set to True. If $r equals to 0, the $male variable is set to False.
if ($male) {
echo "We will use name John\n";
} else {
echo "We will use name Victoria\n";
}
We print the name. The if command works with boolean values. If the variable $male is True, we print the "We will use name John" to the console. If it has a False value, we print the other string.
The following script shows some common values that are considered to be True or False. For example, empty string, empty array, 0 are considered to be False.
<?php
class Object {};

var_dump((bool) "");
var_dump((bool) 0);
var_dump((bool) -1);
var_dump((bool) "PHP");
var_dump((bool) array(32));
var_dump((bool) array());
var_dump((bool) "false");
var_dump((bool) new Object());
var_dump((bool) NULL);
?>
In this script, we inspect some values in a boolean context. The var_dump() function shows information about a variable. The (bool) construct is called casting. In its casual context, the 0 value is a number. In a boolean context, it is False. The boolean context is when we use (bool) casting, when we use certain operators (negation, comparison operators) and when we use if/else, while keywords.
$ php boolean.php
bool(false)
bool(false)
bool(true)
bool(true)
bool(true)
bool(false)
bool(true)
bool(true)
bool(false)
Here is the outcome of the script.

Integers

Integers are a subset of the real numbers. They are written without a fraction or a decimal component. Integers fall within a set Z = {..., -2, -1, 0, 1, 2, ...} Integers are infinite.
In computer languages, integers are primitive data types. Computers can practically work only with a subset of integer values, because computers have finite capacity. Integers are used to count discrete entities. We can have 3, 4, 6 humans, but we cannot have 3.33 humans. We can have 3.33 kilograms.
Integers can be specified in three different notations in PHP. Decimal, hexadecimal and octal. Octal values are preceded by 0, hexadecimal by 0x.
<?php

$var1 = 31;
$var2 = 031;
$var3 = 0x31;

echo "$var1\n";
echo "$var2\n";
echo "$var3\n";

?>
We assign 31 to three variables using three notations. And we print them to the console.
$ php notation.php 
31
25
49
The default notation is the decimal. The script shows these three numbers in decimal.
Integers in PHP have a fixed maximum size. The size of integers is platform dependent. PHP has built-in constants to show the maximum size of an integer.
$ uname -mo
i686 GNU/Linux
$ php -a
Interactive shell

php > echo PHP_INT_SIZE;
4
php > echo PHP_INT_MAX;
2147483647
php >
On my 32bit Ubuntu system, an integer value size is four bytes. The maximum integer value is 2147483647.
In Java and C, if an integer value is bigger than the maximum value allowed, integer overflow happens. PHP works differently. In PHP, the integer becomes a float number. Floating point numbers have greater boundaries.
<?php

$var = PHP_INT_MAX;

echo var_dump($var);
$var++;
echo var_dump($var);

?>
We assign a maximum integer value to the $var variable. We increase the variable by one. And we compare the contents.
$ php boundary.php 
int(2147483647)
float(2147483648)
As we have mentioned previously, internally, the number becomes a floating point value.
In Java, the value after increasing would be -2147483648. This is where the term integer overflow comes from. The number goes over the top and becomes the smallest negative integer value assignable to a variable.
If we work with integers, we deal with discrete entities. We would use integers to count apples.
<?php

# number of baskets
$baskets = 16;

# number of apples in each basket
$apples_in_basket = 24;

# total number of apples
$total = $baskets * $apples_in_basket;

echo "There are total of $total apples \n";
?>
In our script, we count the total amount of apples. We use the multiplication operation.
$ php apples.php 
There are total of 384 apples
The output of the script.

Floating point numbers

Floating point numbers represent real numbers in computing. Real numbers measure continuous quantities. Like weight, height or speed. Floating point numbers in PHP can be larger than integers and they can have a decimal point. The size of a float is platform dependent.
We can use various syntax to create floating point values.
<?php

$a = 1.245;
$b = 1.2e3;
$c = 2E-10;
$d = 1264275425335735;

var_dump($a);
var_dump($b);
var_dump($c);
var_dump($d);

?>
In this example, we have two cases of notations, that are used by scientists to denote floating point values. Also the $d variable is assigned a large number, so it is automatically converted to float type.
$ php floats.php 
float(1.245)
float(1200)
float(2.0E-10)
float(1264275425340000)
This is the output of the above script.
According to the documentation, floating point numbers should not be tested for equality. We will show an example why.
$ php -a
Interactive shell

php > echo 1/3;
0.333333333333
php > $var = (0.333333333333 == 1/3);
php > var_dump($var);
bool(false)
php >
In this example, we compare two values that seem to be identical. But they yield unexpected result.
Let's say a sprinter for 100m ran 9.87s. What is his speed in km/h?
<?php

# 100m is 0.1 km

$distance = 0.1;

# 9.87s is 9.87/60*60 h

$time = 9.87 / 3600;

$speed = $distance / $time;

echo "The average speed of a sprinter is $speed \n";

?>
In this example, it is necessary to use floating point values.
$speed = $distance / $time;
To get the speed, we divide the distance by the time.
$ php sprinter.php 
The average speed of a sprinter is 36.4741641337
This is the output of the sprinter script. 36.4741641337 is a floating point number.

Strings

String is a data type representing textual data in computer programs. Probably the single most important data type in programming.
Since string are very important in every programming language, we will dedicate a whole chapter to them. Here we only drop a small example.
<?php

$a = "PHP ";
$b = 'PERL';

echo $a, $b;
echo "\n";

?>
We can use single quotes and double quotes to create string literals.
$ php strings.php 
PHP PERL
The script outputs two strings to the console. The \n is a special sequence, a new line. The effect of this character is like if you hit the enter key when typing text.

Arrays

Array is a complex data type which handles a collection of elements. Each of the elements can be accessed by an index. In PHP, arrays are more diverse. Arrays can be treated as arrays, lists or dictionaries. In other words, arrays are all what in other languages we call arrays, lists, dictionaries.
Because collections are very important in all computer languages, we dedicate two chapters to collections - arrays. Here we show only a small example.
<?php

$names = array("Jane", "Lucy", "Timea", "Beky", "Lenka");

print_r($names);

?>
The array keyword is used to create a collection of elements. In our case we have names. The print_r function prints a human readable information about a variable to the console.
$ php init.php 
Array
(
[0] => Jane
[1] => Lucy
[2] => Timea
[3] => Beky
[4] => Lenka
)
Output of the script. The numbers are indeces by which we can access the names.

Objects

So far, we have been talking about built-in data types. Objects are user defined data types. Programmers can create their data types that fit their domain. More about objects in chapter about object oriented programming, OOP.

Resources

Resources are special data types. They hold a reference to an external resource. They are created by special functions. Resources are handlers to opened files, database connections or image canvas areas.

NULL

There is another special data type - NULL. Basically, the data type means non existent, not known or empty.
In PHP, a variable is NULL in three cases:
  • it was not assigned a value
  • it was assigned a special NULL constant
  • it was unset with the unset() function
<?php

$a;
$b = NULL;

$c = 1;
unset($c);

$d = 2;

if (is_null($a)) echo "\$a is null\n";
if (is_null($b)) echo "\$b is null\n";
if (is_null($c)) echo "\$c is null\n";
if (is_null($d)) echo "\$d is null\n";

?>
In our example, we have four variables. Three of them are considered to be NULL. We use the is_null() function to determine, if the variable is NULL.
$ php null.php 
$a is null
$b is null
$c is null
Outcome of the script.

Type casting

We often work with multiple data types at once. Converting one data type to another one is a common job in programming. Type conversion or typecasting refers to changing an entity of one data type into another. There are two types of conversion. Implicit and explicit. Implicit type conversion, also known as coercion, is an automatic type conversion by the compiler.
php > echo "45" + 12;
57
php > echo 12 + 12.4;
24.4
In the above example, we have two examples of implicit type casting. In the first statement, the string is converted to integer and added to the second operand. If either operand is a float, then both operands are evaluated as floats, and the result will be a float.
Explicit conversion happens, when we use the cast constructs, like (boolean).
php > $a = 12.43;
php > var_dump($a);
float(12.43)
php > $a = (integer) $a;
php > var_dump($a);
int(12)
php > $a = (string) $a;
php > var_dump($a);
string(2) "12"
php > $a = (boolean) $a;
php > var_dump($a);
bool(true)
This code snippet shows explicit casting in action. First we assign a float value to a variable. Later we cast it to integer, string and finally boolean data type.
In this part of the PHP tutorial, we covered data types.
Continue Reading

Upload robots.txt file in CakePHP installation

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.
Continue Reading

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.
Continue Reading

Robots Meta Tag to CakePHP View File

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.
Continue Reading

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.
Continue Reading

Open 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.
Continue Reading

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.
Continue Reading

CakePHP 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:
Continue Reading

Complete User Registration with CakePHP

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

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.

Step: 1 Set up CakePHP Console
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 here.

Step: 2 Follow the CakePHP Simple ACL Control Application
This 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 basic working principles of Cake nicely. The tutorial makes full use of different Cake's core components like Acl Component & Auth Component.

Step: 3 Set custom routing
file: // app/config/routes.php

Copy paste following codes:

Router::connect('/login', array('controller' => 'users', 'action' => 'login'));
Router::connect('/logout', array('controller' => 'users', 'action' => 'logout'));
Router::connect('/register', array('controller' => 'users', 'action' => 'register'));


This will show login form, when someone types http://caketest.local/login and likewise.


Step: 3 Create a dynamic login/logout menu
The Cakebook tutorial does not include creating a dynamic login/logout menu. So, you need to create one.
1. Create a new file.
2. Copy-paste the following code.

<?php 
if(!$session->check('Auth.User')){
echo $html->link('Login','/login');
} else {
$username = $session->read('Auth.User.username');
echo " Hello ". $username ."&nbsp;";
echo $html->link("(logout)", "/logout", array(), null, false);
}
?>

3. Save this file as '/app/views/elements/login_menu.ctp'

4. Open '/app/views/layouts/default.ctp'
5. Copy-paste the following code.

<?php echo $this-> element('login_menu'); ?>

6. Save this file.

Now you can see the login/logout option.
Notice I have used SESSION variables to control login/logout option. To learn more about CakePHP session, please visit this page. For a formatted output of contents inside session variables, use pr($_SESSION) - STRICTLY for DEBUG;


Step 4:  Ban a user account
1.Fire the following SQL query:


ALTER TABLE `users` ADD  `is_banned` TINYINT NOT NULL DEFAULT '0';

This adds a field 'is_banned' in the 'users' table. Set default values to zero.

2. Now copy-paste following code in UsersController::beforeFilter()
file:// app/controllers/users_controller.php

$this->Auth->userScope = array('User.is_banned' => 0);

3. Done. Cake will not allow users to login, when you have set 'is_banned' = 1.
Step 5: Email Validation during user registration
The code is pretty long and nicely explained here. 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.

file://  app/controllers/users_controller.php


<?php
 uses('sanitize');
class UsersController extends AppController {




        var $name = 'Users';
var $components = array('Email','Auth');
                                                                    /* "Email' component will handle emailing tasks, 'Auth'    component will handle User Management */
var $helpers = array('Html', 'Form');

/* ..... member functions will go here ... */
}

function beforeFilter()

/* CakePHP CallBack methods */
function beforeFilter() {
   parent::beforeFilter(); 
$this->Email->delivery = 'debug'; /* used to debug email message */
$this->Auth->autoRedirect = false; /* this allows us to run further checks on login() action.*/
$this->Auth->allow('register', 'thanks', 'confirm', 'logout'); 
$this->Auth->userScope = array('User.is_banned' => 0); /* admin can ban a user by updating `is_banned` field of users table to '1' */
}

function register()

// Allows a user to sign up for a new account
        function register() {

                if (!empty($this->data)) {
                        // Applying Auth Components's Password Hashing Rules
/*
We have commented the following field as this was double-hashing password.
$this->Auth->password($this->data['User']['passwrd']); 

*/
                   //      $this->data['User']['passwrd'] = $this->Auth->password($this->data['User']['passwrd']);
 
                        $this->User->data = Sanitize::clean($this->data);
           
// Successfully created account – send activation email     
            
                        if ($this->User->save()) {
                                $this->__sendActivationEmail($this->User->getLastInsertID());


// pr($this->Session->read('Message.email')); /*Uncomment this code to view the content of email FOR DEBUG */


                                // this view is not show / listed – use your imagination and inform
                                // users that an activation email has been sent out to them.
                                $this->redirect('/users/thanks');
                        }
                        // Failed, clear password field
                        else {
                                $this->data['User']['passwrd'] = null;
                        }
                }
$groups = $this->User->Group->find('list');
$this->set(compact('groups'));
        }


Function login()


function login() {
                // Check for incoming login request.
//pr($this->data);
                if ($this->data) {
                        // Use the AuthComponent's login action
                        if ($this->Auth->login($this->data)) {
                                // Retrieve user data
                                $results = $this->User->find(array('User.username' => $this->data['User']['username']), array('User.active'), null, false);
                                // Check to see if the User's account isn't active
                                if ($results['User']['active'] == 0) {
                                        // Uh Oh!
                                        $this->Session->setFlash('Your account has not been activated yet!');
                                        $this->Auth->logout();
                                        $this->redirect('/users/login');
                                }
                                // Cool, user is active, redirect post login
                                else {
                                        $this->redirect('/');
                                }
                        }
                }
        }

function logout()
function logout() {
$this->Session->setFlash('Good-Bye');
$this->redirect($this->Auth->logout());
}


/* function to validate activation link

* and to set 'active' = 1
*/  

function activate()

function activate($user_id = null, $in_hash = null) {

        $this->User->id = $user_id;

if ($this->User->exists() && ($in_hash == $this->User->getActivationHash())) {
         if (empty($this->data)) {

$this->data = $this->User->read(null, $user_id);
   // Update the active flag in the database
$this->User->set('active', 1);
$this->User->save();

$this->Session->setFlash('Your account has been activated, please log in below.');
                $this->redirect('login');
}
}

     // Activation failed, render '/views/user/activate.ctp' which should tell the user.
}


function __sendActivationEmail()

/* function to send activation email */
 function __sendActivationEmail($user_id) {
                $user = $this->User->find(array('User.id' => $user_id), array('User.email', 'User.username','User.id'), null, false);
                if ($user === false) {
                        debug(__METHOD__." failed to retrieve User data for user.id: {$user_id}");
                        return false;
                }

                // Set data for the "view" of the Email
                $this->set('activate_url', 'http://' . env('SERVER_NAME') . '/users/activate/' . $user['User']['id'] . '/' . $this->User->getActivationHash());
                $this->set('username', $this->data['User']['username']);
                
                $this->Email->to = $user['User']['email'];
                $this->Email->subject = env('SERVER_NAME') . ' – Please confirm your email address';
                $this->Email->from = 'noreply@' . env('SERVER_NAME');
                $this->Email->template = 'user_confirm';
                $this->Email->sendAs = 'text';   // you probably want to use both :)    
                return $this->Email->send();

        }

Copy paste function getActivationHash at file:// app/models/user.php

function getActivationHash()
        {
                if (!isset($this->id)) {
                        return false;
                }
                return substr(Security::hash(Configure::read('Security.salt') . $this->field('created') . date('Ymd')), 0, 8);
        }
Copy-paste following code in the file:// app/app_controller.php inside the function beforeFilter()
function beforeFilter() {
$this->Auth->fields = array('username' => 'username', 'password' => 'passwrd');
       /* ... Rest of the function body goes here */
}

Now View Files


Registration form
file:// app/views/users/register.ctp



<h2>Create an Account</h2>
<?php
echo $form->create('User', array('action' => 'register'));
echo $form->input('username');
// Force the FormHelper to render a password field, and change the label.
echo $form->input('group_id', array('type' => 'hidden', 'value' => 'Insert-Default-Value'));
echo $form->input('passwrd', array('type' => 'password', 'label' => 'Password'));
echo $form->input('email', array('between' => 'We need to send you a confirmation email to check you are human.'));
echo $form->submit('Create Account');
echo $form->end();
?>

Notice replace 'Insert-Default-Value' with the actual value of your group_id.
   
Login form
file:// app/views/users/login.ctp



<?php
echo $form->create('User', array('action' => 'login'));
echo $form->input('username');
echo $form->input('passwrd', array('label' => 'Password', 'type' => 'password'));
echo $form->end('Login');
?>



user_confirm.ctp
file:// app/views/elements/email/text/user_confirm.ctp

<?php
  # /app/views/elements/email/text/user_confirm.ctp
  ?>
  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:
  <?= $activate_url ?>

With all the above scripts, you should be able to get a workable user registration system.
Here, you will have groups/ users/ and you can set group level access per controller, even per action following Cake's default mechanism!

[Acknowledgements]
My sincere regards to Jonny Revees for his wonderful work on this CakePHP user registration system. It works like a charm!


Here are some more stuff I found helpful:
CakePHP Auth Component variables.
Understanding CakePHP Session
Saving data in CakePHP found in book.cakephp.org
Debuggable.com - this post explains how to debug CakePHP email.
Continue Reading

Create Category Tree with CakePHP 'Tree' behavior

Okay! Let's try to create a category tree using CakePHP (This is something like parent category -> child category type records).

SQL:

CREATE TABLE categories (
id INTEGER(10) UNSIGNED NOT NULL AUTO_INCREMENT,
parent_id INTEGER(10) DEFAULT NULL,
lft INTEGER(10) DEFAULT NULL,
rght INTEGER(10) DEFAULT NULL,
name VARCHAR(255) DEFAULT '',
PRIMARY KEY  (id)
);

Now insert some record:
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(1, 'Tutorials', NULL, 1, 8);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(2, 'PHP', 1, 2, 5);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(3, 'MySQL', 1, 6, 7);
INSERT INTO `categories` (`id`, `name`, `parent_id`, `lft`, `rght`) VALUES(4, 'CakePHP', 2, 3, 4);

Now I'll create a model for this category.

1. Create a new file.
2. Copy-paste the following code:

<?php
   class Category extends AppModel {  
var $name = 'Category';
   var $actsAs = array('Tree');
}
?>

3. Save the files as app/models/category.php.

Note:
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.
To learn more about 'Behaviors', please refer to CakePHP online book.

Now I'll create CategoriesController
Step:
1. Create a new file.
2. Copy-paste the following code.

<?php
class CategoriesController extends AppController {
            var $name = 'Categories';  
             
function index() {
                  $categories = $this->Category->generatetreelist(null, null, null, '&nbsp;&nbsp;&nbsp;');
                  $this->set(compact('categories'));    
                  }
 }
?>
3. Save that file as categories_controller.php under 'app/controllers' folder.

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 CakePHP book.
compact(); 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.

Now I'll create a view for our index() function.
file: '/app/views/categories/index.php'

<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
  foreach($categories as $key=>$value){
  echo "<li>$value</li>";
  }
  echo "</ul>";
?>


Now point your browser to:
http://caketest.local/categories

And you should see following structure:

> Tutorials    
   > PHP    
> CakePHP    
> MySQL

To Add a new category to the list:
1. Open categories_controller.php (found under '/app/controllers')
2. Copy-paste the following function:


function add() {


if (!empty($this -> data) ) {
$this->Category->save($this -> data);
$this->Session->setFlash('A new category has been added');
$this->redirect(array('action' => 'index'));
} else {
$parents[0] = "[Top]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories) {
foreach ($categories as $key=>$value)
$parents[$key] = $value;
}
$this->set(compact('parents'));
}


}

3. Save this file.

Now we need to create a view file for this add() method (to display the add category form).

1. Create a new file.
2. Copy-paste the following code:


<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>

3. Save the file as '/app/views/categories/add.ctp'

Now point your browser to this location:
http://caketest.local/categories/add

You should be able to add a new category.

EDIT Category
To edit category, I'll specify a controller action. To do so:
1. Open categories_controller.php (found under '/app/controllers').
2. Copy-paste the following function:


function edit($id=null) {
if (!empty($this->data)) {
if($this->Category->save($this->data)==false)
$this->Session->setFlash('Error saving Node.');
$this->redirect(array('action'=>'index'));
} else {
if($id==null) die("No ID received");
$this->data = $this->Category->read(null, $id);
$parents[0] = "[ Top ]";
$categories = $this->Category->generatetreelist(null,null,null," - ");
if($categories) 
foreach ($categories as $key=>$value)
$parents[$key] = $value;
$this->set(compact('parents'));
}
}


3. Save that function.

Now, I'll write the view file (the form to edit a category). To do so:
1. Create a new file.
2. Copy paste the following code:


<?php
echo $html->link('Back',array('action'=>'index'));
echo $form->create('Category');
  echo $form->hidden('id');
  echo $form->input('name');
  echo $form->input('parent_id', array('selected'=>$this->data['Category']['parent_id']));
  echo $form->end('Update');
?>

3. Now save the file as '/app/views/categories/edit.ctp'.

Hold on!
There is one more thing we should do. We need to show the link to edit record. To do show:
1. Open '/app/views/categories/index.ctp' file.
2. Replace the existing code with this one:

<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
  foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
 echo "<li>$value &nbsp;[$edit]</li>";
  }
  echo "</ul>";
?>

3. Now save the file.

Now point your browser to:
http://caketest.local/categories/
You should be able to see the 'Edit' option against each category name.

Delete Category
CakePHP Format:
removeFromTree($id=null, $delete=false)

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.

Steps:
1. Open '/app/controllers/categories_controller.php'
2. Copy paste the following code:









function delete($id=null) {
  if($id==null)
  die("No ID received");
  $this->Category->id=$id;
  if($this->Category->removeFromTree($id,true)==false)
     $this->Session->setFlash('The Category could not be deleted.');
   $this->Session->setFlash('Category has been deleted.');
   $this->redirect(array('action'=>'index'));
}

3. Now save that file.

Next, I'll display the option to 'delete' a category.
Step:
1. Open '/app/views/categories/index.ctp
2. Replace the existing code with this one:

<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
  foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
  $delete = $html->link("Delete", array('action'=>'delete', $key));
  echo "<li>$value &nbsp;[$edit]&nbsp;[$delete]</li>";
  }
  echo "</ul>";
?>
3. Save the file.

Done
Point your browser to:
http://caketest.local/categories
Here is a screenshot of what you should see:


[ACKNOWLEDGEMENT]
The code above is mostly based on
Bram Borggreve's beautiful website - Tree Behavior
I express my sincere gratitude to Bram for his wonderful contribution.
Further, to learn more about 'Tree' behavior, please visit: CakePHP Book.





Here is the COMPLETE script files:

1. categories_controller.php ('to be saved under '/app/controllers')


<?php
  class CategoriesController extends AppController {
 var $name = 'Categories';
 function index() {
  $categories = $this->Category->generatetreelist(null, null, null, '&nbsp;&nbsp;&nbsp;');
  // debug ($this->data); die; 
  $this->set(compact('categories')); 
  
  }
  
  function add() {
  
  if (!empty($this -> data) ) {
  $this->Category->save($this -> data);
  $this->Session->setFlash('A new category has been added');
  $this->redirect(array('action' => 'index'));
  } else {
  $parents[0] = "[ Top ]";
  $categories = $this->Category->generatetreelist(null,null,null," - ");
  if($categories) {
  foreach ($categories as $key=>$value)
  $parents[$key] = $value;
  }
  $this->set(compact('parents'));
  }
  
  }

  function edit($id=null) {
  if (!empty($this->data)) {
  if($this->Category->save($this->data)==false)
  $this->Session->setFlash('Error saving Category.');
  $this->redirect(array('action'=>'index'));
  } else {
  if($id==null) die("No ID received");
  $this->data = $this->Category->read(null, $id);
  $parents[0] = "[ Top ]";
  $categories = $this->Category->generatetreelist(null,null,null," - ");
  if($categories) 
  foreach ($categories as $key=>$value)
  $parents[$key] = $value;
  $this->set(compact('parents'));
  }
  }
 function delete($id=null) {
  if($id==null)
  die("No ID received");
  $this->Category->id=$id;
  if($this->Category->removeFromTree($id,true)==false)
  $this->Session->setFlash('The Category could not be deleted.');
  $this->Session->setFlash('Category has been deleted.');
  $this->redirect(array('action'=>'index'));
  }


}
  ?>

2. Category Model (file: '/app/models/category.php')

<?php
class Category extends AppModel { 
var $name = 'Category';
var $actsAs = array('Tree'); 

?> 

3. Views for Category Files
(a)File: '/app/views/categories/index.php'

<?php
echo $html->link("Add Category",array('action'=>'add'));
echo "<ul>";
  foreach($categories as $key=>$value){
$edit = $html->link("Edit", array('action'=>'edit', $key));
  $delete = $html->link("Delete", array('action'=>'delete', $key));
  echo "<li>$value &nbsp;[$edit]&nbsp;[$delete]</li>";
  }
  echo "</ul>";
?>



(b) File: '/app/views/categories/add.php'





<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>


(c) File: 'app/views/categories/edit.php'

<h1>Add a new category</h1>
<?php
echo $form->create('Category');
echo $form->input('parent_id',array('label'=>'Parent'));
echo $form->input('name',array('label'=>'Name'));
echo $form->end('Add');
?>



Thanks for reading the entry.
Continue Reading

Creating HTML Text Links with CakePHP

So, we have just created our about_us page. Now we need to create a link to this page. CakePHP has defined its own class for you to create links. The basic syntax is simple.

<?php echo $html->link('Link Text', 'Link URL'); ?>

For example: I wanted to create a link to http://book.cakephp.org

My Syntax:
<?php echo $html->link('CakePHP Book', 'http://book.cakephp.org'); ?>

And output:
 <a href="http://book.cakephp.org">CakePHP Book</a>

Note:
1. To create a link you need to echo the entire statement.
2. You can change link to point to any path - even relative paths.
3. You can use additional attributes to mention CSS class

Let us add a CSS class to that link.
<p><?php echo $html->link('CakePHP Book', 'http://book.cakephp.org', array('class'=>'ext')); ?></p>

Note the part I have marked with red ink. This link is now associated with class 'ext'. (Do not forget to define the 'ext' class in your css, in my case it is cake.generic.css file). And you are done.

To open this link in a new window:
<?php echo $html->link('CakePHP Book', 'http://book.cakephp.org', array('class'=>'ext', 'target'=>'_blank')); ?>
Note I have added 'target'=>'_blank' to that statement.

To add a javascript confirmation box to that link:
<?php echo $html->link('CakePHP Book', 'http://book.cakephp.org', array('class'=>'ext', 'target'=>'_blank'), "Do you really want to visit this website?"); ?>

Note I have added just the string to display and nothing more. Cake takes care of the rest of the stuff efficiently. And there's really much more to explore!

In my CakeTest Application now I'll display a link in the footer section to 'about_us' page.

I'll edit default.ctp (found under 'app/views/layouts' and add the following lines (mark with red color).


<div id="footer">
<?php

echo $html->link('About us','about_us',array('class'=>'footer-link'));

?>
</div>


Note:
I have not used the complete path to about us page, which is:
/pages/about_us
You need to specify just that 'about_us' part in place of the 'link url'. Cake does the rest successfully.

Further, I'll add a new style to cake.generic.css file (found under 'app/webroot/css')


a.footer-link:link,a.footer-link:visited, a.footer-link:active {
color:#C1C1C1;
font-size:10px;
background-color:#ffffff;
text-decoration:none;
}
a.footer-link:hover{
color:#C1C1C1;
font-size:10px;
background-color:#ffffff;
text-decoration:underline;
}


That's it.
Here is a preview:















That's it.

Cheers!
Continue Reading

Create a Custom CakePHP Template

So, I hope by far you have downloaded CakePHP (A.K.A. 'Cake'), installed it, changed security settings and connected to database.

You have seen the messages in the welcome screen has changed after each of your action.

Now you will note the following:
Editing this Page

1. To change the content of this page, create: APP/views/pages/home.ctp.
2. To change its layout, create: APP/views/layouts/default.ctp.
3. You can also add some CSS styles for your pages at: APP/webroot/css.
Create DEFAULT Home Page


So, I created a new folder called 'pages' under app/views/ . And then I created a new file (using any text editor) and saved that file as 'home.ctp' under 'app/views/pages/'.

Now point your browser to:
http://caketest.local/

You can see all the messages are gone!!! You can see this is a nearly empty page!


As the name says, 'home.ctp' is the default homepage for your website. You can write anything here (with HTML tags). Those will be displayed at your homepage.

Create Default LAYOUT

Now create another new file (using any text editor) and save it as 'default.ctp' under 'app/views/layouts/' folder.

'default.ctp' is the default layout to display your content. If it is empty, CakePHP will display nothing. This is exactly what you see after saving default.ctp - a completely blank page!!!

Do not worry!

Just copy and paste the following code in the newly created 'default.ctp' file.

--: BEGIN COPY :--



<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
  <html xmlns="http://www.w3.org/1999/xhtml">
  <head>
  <?php echo $html->charset(); ?>
  <title>
  <?php __('My-CakePHP Tutorials'); ?>
  <?php echo $title_for_layout; ?>
  </title>
  <?php
  echo $html->meta('icon');


echo $html->css('cake.generic');


echo $scripts_for_layout;
  ?>
  </head>
  <body>
  <div id="container">
  <div id="header">
  Header Elements Will Go Here
  </div>
  <div id="content">


<?php $session->flash(); ?>


<?php echo $content_for_layout; ?>


</div>
  <div id="footer">
  Footer Text Goes Here!
  </div>
  </div>
  <?php echo $cakeDebug; ?>
  </body>
  </html>



----: END COPY :---


I have used red color to mark things you should note.
Change 'My-CakePHP Tutorials' to the title of your website. Like 'My Pet Dog Roombiq', or, anything you want.

NOTE:
There are FOUR IMPORTANT VARIABLES
$title_for_layout
$scripts_for_layout
$content_for_layout
$cakeDebug


The name suggests exactly what they do.
NOTE: 1
$title_for_layout MUST be included in between <title>  </title> tag.

<title>
  <?php echo $title_for_layout; ?>
</title>

As such, CakePHP gives a default title to every content page of your website following its own rules. But you can set a custom title as well. I'll show that in the next page.

NOTE: 2
$scripts_for_layout MUST be included before the closing </head> tag.


NOTE: 3
$content_for_layout MUST be included in between <body>
</body> tag.
<body>
<?php echo $content_for_layout; ?>
</body>

NOTE: 4
$cakeDebug SHOULD be placed before closing </body>

<?php echo $cakeDebug; ?>
</body>

AND you are done! You can add any CSS style/'div' layer to this page ('default.ctp') to give your website the layout/look you want.


For example, I tried a simple TWO Column Layout.

<div id="content">
  <div id="menu-box">
  menu items go here!
  </div>
  <div id="content-box">
<?php $session->flash(); ?>
<?php echo $content_for_layout; ?>
  </div>
</div>

I have added one div layer 'menu-box' and another one 'content-box' to display menu items and content items in two separate columns.
Now I need to add these CSS styles in a stylesheet file.

Modifying Stylesheet


As such Cake ('short-form of CakePHP) has already told us how to do that:
You can also add some CSS styles for your pages at: APP/webroot/css.
You can see the default CSS file under 'app/webroot/css' folder. The name of the file is 'cake.generic.css'. You can simply modify the content of this file (cake.generic.css).

I preferred to go to the bottom of that page and type the following lines


/* Custom CSS */

#menu-box{
width:250px;
float:left;
}
#content-box{
width:700px;
float:left;
}

It gives me a workable presentation for my custom template.

But I really need to make some more changes.

So, I just pressed (Ctrl+U) to view the source code, and I located the CSS division layers/ HTML tags being displayed in the source code, and modified them.

Here is the code: (Remember: I added the code at the bottom of cake.generic.css file.)


/* Custom CSS */

#menu-box{
width:250px;
float:left;
border-right:1px solid #CCCCCC;
}
#content-box{
margin-left:10px;
width:700px;
float:left;
border:1px solid #CCCCCC;
padding:10px;
background-color:#F3F3F3;
}
#header {
height:100px;
width:100%;
color:#000000;
background-color:#b5fad1;
font-size:2.0em;
border-bottom:1px solid #cccccc;
}
body
{
background-color:#FFFFFF;
color:#000000;
font-family:Verdana, Arial, Helvetica, sans-serif;
}

#footer
{
text-align:center;
}

..............................................................
And here is my custom template:














So, I have once again DONE that! If you are following me, you MUST have done so as well.

Congratulations!

Next, I'll try to create my 'About us' page using CakePHP. In general, I think this will give me some idea on how to create a static page with CakePHP.

Cheers!
Continue Reading