Pejman Moghadam / PHP

CakePHP 1.3 - Simple Blog Example with Authentication

Public domain


Preparing files and directories:

  1. Rename cakephp directory :

    cd /var/www/htdocs
    tar xf ~/cakephp-cakephp-1.3.13-0-g924fb6f.tar.gz
    mv cakephp-cakephp-1.3.13-0-g924fb6f/ blog
    
  2. Change app/tmp/ owner and all it's subdirectories :

    chown -R apache app/tmp/
    
  3. Change Security.salt and Security.cipherSeed values in app/config/core.php :

    Configure::write('Security.salt', 
                               'DYhG93b0qyJfIxfs2guVoUubWwvniR2G0FgaC9mi');
    Configure::write('Security.cipherSeed', 
                                          '76859309657453542496749683645');
    

Preparing Database

  1. Create a database :

    CREATE DATABASE blog;
    
  2. Create a table with plural name and a primary key named 'id' :

    USE blog;
    
    
    CREATE TABLE posts (
        id INT UNSIGNED AUTO_INCREMENT PRIMARY KEY,
        title VARCHAR(50),
        body TEXT,
        created DATETIME DEFAULT NULL,
        modified DATETIME DEFAULT NULL
    );
    
  3. Insert sample data for testing :

    INSERT INTO posts (title,body,created,modified) 
      VALUES ('The title', 'This is the post body.', NOW(), NOW());
    INSERT INTO posts (title,body,created,modified) 
      VALUES ('A title once again', 'And the post body follows.', NOW(), NOW());
    INSERT INTO posts (title,body,created,modified) 
      VALUES ('Title strikes back', 'This is really exciting! Not.', NOW(), NOW());
    
  4. Rename database.php.default to database.php :

    mv app/config/database.php{.default,}
    
  5. edit app/config/database.php , remove $test array and change $default array :

    class DATABASE_CONFIG {
        var $default = array(
          'driver' => 'mysql',
          'persistent' => false,
          'host' => 'localhost',
          'login' => 'root',
          'password' => '',
          'database' => 'blog',
          'prefix' => '',
          //'encoding' => 'utf8',
        );
    }
    
  6. Check the result in browser :

    http://localhost/blog
    

Create a Model

  1. Create a .php file, named same as database table name but singular, in app/models/ directory :

    <?php
    // File: app/models/post.php
    class Post extends AppModel {
            var $name = 'Post';
    }
    ?>
    

Create a Controller

  1. Create a .php file, named same as database table name (plural) with _controller.php postfix in app/controllers directory :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
    }
    ?>
    

Create an Acion/View pare: Showing the list of posts

  1. Add an action named 'index' to controller :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
            function index() {
                    $this->set('posts', $this->Post->find('all'));
            }
    }
    ?>
    
  2. Create a directory, named same as database table (plural), in app/views/ directory:

    mkdir app/views/posts
    
  3. Create a .ctp file, named same as action name in controller, in previously made directory :

    <!-- File: app/views/posts/index.ctp -->
    <h1>Blog posts</h1>
    <table>
      <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Created</th>
      </tr>
      <!-- Here is where we loop through our $posts array and 
                                   printing out post info -->
      <?php foreach ($posts as $post): ?>
      <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td>
        <?php 
          echo $this->Html->link($post['Post']['title'],
          array('controller' => 'posts', 'action' => 'view', 
                                      $post['Post']['id']));
        ?>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
      </tr>
      <?php endforeach; ?>
    </table>
    
  4. Check the result in browser :

    http://localhost/blog/posts
    

Create an Action/View pare: Showing a single post

  1. Add an action named 'view' to controller :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
            function index() {
                    $this->set('posts', $this->Post->find('all'));
            }
            function view($id = null) {
                    $this->Post->id = $id;
                    $this->set('post', $this->Post->read());
            }
    }
    ?>
    
  2. Create a .ctp file, named same as the action name, in views directory:

    <!-- File: app/views/posts/view.ctp -->
    <h1><?php echo $post['Post']['title']?></h1>
    <p><small>Created: <?php echo $post['Post']['created']?></small></p>
    <p><?php echo $post['Post']['body']?></p>
    
  3. Check the result in browser :

    http://localhost/blog/posts
    http://localhost/blog/posts/view/1
    

Create an Action/View pare: Adding a post

  1. Include required helpers and components to the controller:

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
            var $helpers = array ('Html','Form');
            var $components = array('Session');
            function index() {
                    $this->set('posts', $this->Post->find('all'));
            }
            function view($id = null) {
                    $this->Post->id = $id;
                    $this->set('post', $this->Post->read());
            }
    }
    ?>
    
  2. Add an action named 'add' to controller :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
            var $helpers = array ('Html','Form');
            var $components = array('Session');
            function index() {
                    $this->set('posts', $this->Post->find('all'));
            }
            function view($id = null) {
                    $this->Post->id = $id;
                    $this->set('post', $this->Post->read());
            }
            function add() {
                if (!empty($this->data)) {
                    if ($this->Post->save($this->data)) {
                      $this->Session->setFlash('Your post has been saved.');
                      $this->redirect(array('action' => 'index'));
                    }
                }
            }
    }
    ?>
    
  3. Create a .ctp file, named same as the action name, in views directory:

    <!-- File: app/views/posts/add.ctp -->
    <h1>Add Post</h1>
    <?php
    echo $this->Form->create('Post');
    echo $this->Form->input('title');
    echo $this->Form->input('body', array('rows' => '3'));
    echo $this->Form->end('Save Post');
    ?>
    
  4. Add a link to this action in app/views/posts/index.ctp :

    <?php echo $this->Html->link('Add Post', 
          array('controller' => 'posts', 'action' => 'add')); ?>
    
  5. Check the result in browser :

    http://localhost/blog/posts
    http://localhost/blog/posts/add
    

Data Validation

  1. Add required validation array to Model:

    <?php
    // File: app/models/post.php
    class Post extends AppModel {
            var $name = 'Post';
            var $validate = array(
                'title' => array('rule' => 'notEmpty'),
                'body' => array('rule' => 'notEmpty')
            );
    }
    ?>
    

Create an Action: Deleting a post

  1. Add an action named 'delete' to controller :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
            var $name = 'Posts';
            var $helpers = array ('Html','Form');
            var $components = array('Session');
            function index() {
                    $this->set('posts', $this->Post->find('all'));
            }
            function view($id = null) {
                    $this->Post->id = $id;
                    $this->set('post', $this->Post->read());
            }
            function add() {
                if (!empty($this->data)) {
                    if ($this->Post->save($this->data)) {
                      $this->Session->setFlash('Your post has been saved.');
                      $this->redirect(array('action' => 'index'));
                    }
                }
            }
            function delete($id) {
                    if ($this->Post->delete($id)) {
                        $this->Session->setFlash('The post with id: ' .
                                           $id . ' has been deleted.');
                        $this->redirect(array('action' => 'index'));
                    }
            }
    }
    ?>
    
  2. Edit 'index' view and Add a link to 'delete' action with appropriate table header:

    <!-- File: app/views/posts/index.ctp -->
    <h1>Blog posts</h1>
    <?php echo $this->Html->link('Add Post',
    array('controller' => 'posts', 'action' => 'add')); ?>
    <table>
      <tr>
        <th>Id</th>
        <th>Title</th>
        <th>Actions</th>
        <th>Created</th>
      </tr>
    <!-- Here is where we loop through our $posts array and 
                                 printing out post info -->
    <?php foreach ($posts as $post): ?>
    <tr>
    <td><?php echo $post['Post']['id']; ?></td>
    <td><?php echo $this->Html->link($post['Post']['title'],
                          array('controller' => 'posts', 'action' => 'view',
                                              $post['Post']['id'])); ?></td>
    <td><?php echo $this->Html->link('Delete',
                           array('action' => 'delete', $post['Post']['id']),
                                               null, 'Are you sure?')?></td>
    <td><?php echo $post['Post']['created']; ?></td>
    </tr>
    <?php endforeach; ?>
    </table>
    
  3. Check the result in browser :

    http://localhost/blog/posts
    http://localhost/blog/posts/delete/3
    

Create an Action/View pare: Editing a post

  1. Add an action named 'edit' to controller :

    <?php
    // File: app/controllers/posts_controller.php
    class PostsController extends AppController {
        var $name = 'Posts';
        var $helpers = array ('Html','Form');
        var $components = array('Session');
        function index() {
                $this->set('posts', $this->Post->find('all'));
        }
        function view($id = null) {
                $this->Post->id = $id;
                $this->set('post', $this->Post->read());
        }
        function add() {
                if (!empty($this->data)) {
                    if ($this->Post->save($this->data)) {
                      $this->Session->setFlash('Your post has been saved.');
                      $this->redirect(array('action' => 'index'));
                    }
                }
        }
        function delete($id) {
                if ($this->Post->delete($id)) {
                    $this->Session->setFlash('The post with id: ' . 
                                       $id . ' has been deleted.');
                    $this->redirect(array('action' => 'index'));
                }
        }
        function edit($id = null) {
            $this->Post->id = $id;
            if (empty($this->data)) {
                $this->data = $this->Post->read();
            } else {
                if ($this->Post->save($this->data)) {
                    $this->Session->setFlash('Your post has been updated.');
                    $this->redirect(array('action' => 'index'));
                }
            }
        } 
    }
    ?>
    
  2. Create a .ctp file, named same as the action name, in views directory:

    <!-- File: app/views/posts/edit.ctp -->
    <h1>Edit Post</h1>
    <?php
    echo $this->Form->create('Post', array('action' => 'edit'));
    echo $this->Form->input('title');
    echo $this->Form->input('body', array('rows' => '3'));
    echo $this->Form->input('id', array('type' => 'hidden'));
    echo $this->Form->end('Update Post');
    ?>
    
  3. Add a link to this action in app/views/posts/index.ctp :

    <!-- File: app/views/posts/index.ctp -->
    <h1>Blog posts</h1>
    <?php echo $this->Html->link('Add Post', 
    array('controller' => 'posts', 'action' => 'add')); ?><br>
    <table>
      <tr>
        <th>Id</th>
         <th>Title</th>
         <th>Actions</th>
         <th>Created</th>
      </tr>
    <!-- Here is where we loop through our $posts array and 
                                 printing out post info -->
      <?php foreach ($posts as $post): ?>
      <tr>
        <td><?php echo $post['Post']['id']; ?></td>
        <td><?php echo $this->Html->link($post['Post']['title'],
                          array('controller' => 'posts', 'action' => 'view',
                                              $post['Post']['id'])); ?></td>
        <td>
          <?php echo $this->Html->link('Delete', 
                           array('action' => 'delete', $post['Post']['id']),
                                                   null, 'Are you sure?') ?>
          <?php echo $this->Html->link('Edit', 
                          array('action' => 'edit', $post['Post']['id']));?>
        </td>
        <td><?php echo $post['Post']['created']; ?></td>
      </tr>
      <?php endforeach; ?>
    </table>
    
  4. Check the result in browser:

    http://localhost/blog/posts
    http://localhost/blog/posts/edit/2
    

Routes

  1. Change default route in app/config/routes.php :

    Router::connect('/', array('controller' => 'posts', 
                                 'action' => 'index'));
    
  2. Check the result in browser:

    http://localhost/blog/
    

Authentication


Preparing Database

  1. Create a table named 'users' with id, username and password fields (password shuold be at least 40 characters) :

    USE blog;
    
    
    CREATE TABLE users (
        id integer auto_increment primary key,
        username char(50),
        password char(40)
    );
    

Making MVC for user model

  1. Bake complete MVC for user model using cake console :

    cake/console/cake bake all user
    
  2. Repair tmp directory permissions

    chown -R apache app/tmp
    

Enabling site wide authentication

  1. Create a file in app/app_controller.php :

    <?php
    // File : app/app_controller.php
    class AppController extends Controller {
            var $components = array('Auth', 'Session');
    }
    

Preparing login/logout actions and views:

  1. Add 'login' and 'logout' acctions to app/controllers/users_controller.php:

    function login() {
    }
    function logout() {
            $this->redirect($this->Auth->logout());
    }
    
  2. Add a view for login in app/views/users/login.ctp:

    <?php
    echo $this->Session->flash('auth');
    echo $this->Form->create('User');
    echo $this->Form->input('username');
    echo $this->Form->input('password');
    echo $this->Form->end('Login');
    ?>
    
  3. Add 'Logout' link in app/views/posts/index.ctp:

    <?php echo $this->Html->link('Logout',
          array('controller' => 'users', 'action' => 'logout')); ?><br>
    

Adding first user

  1. Temporarily disable authentication for all actions:

    <?php
    // File : app/app_controller.php
    class AppController extends Controller {
            var $components = array('Auth', 'Session');
            function beforeFilter() {
                $this->Auth->allow('*');
            }
    }
    
  2. Add first user in browser:

    http://localhost/weblog/users/add
    
  3. Enable autentication again:

    <?php
    // File : app/app_controller.php
    class AppController extends Controller {
            var $components = array('Auth', 'Session');
    }
    
  4. Check authentication in browser:

    http://localhost/weblog
    

BY: Pejman Moghadam
TAG: php, cakephp
DATE: 2011-11-04 10:57:03


Pejman Moghadam / PHP [ TXT ]