Zend framework tutorial, build your Blog

I have been trying to work with zendframework 1.8 and now with 1.9 . I have created a simple blog application using zend framework ( You may call it as a zend framework tutorial . Changing name from "A simple Blog tutorial using Zend framework 1.9" to Zendframework tutorial : Developing a blog for some search engine optimization technique ) . When I say a blog application with zend framework , never expect it , something like wordpress . Its a simple application which can add posts , add comments , can fetch albums from Picasa now , which I developed to learn Zend framework .

As I am new to zendframework and MVC , I know there is errors and some are for my convienience I have placed as it is I am new to unit testing , so have not written any code for test data too . sorry . I know the drawbacks of this application and the database itself is not proper . But I am publishing it if this helps some one to understand Zend_ACL , Zend_Auth , Zend_Form etc. I have added a gallery to get the albums , photos from picasa using the Zend_Gdata API . Thinking to implement to add photos through admin side . Need to implement the feature in admin . Will do it if I get some time

I have looked various blogs and some are upto date applications and some are not . I am using the Zend Toolkit  as I love to work in command line rather than GUI . I have added the link to download the complete zend framework 1.9 blog application example . Feel free to grab the complete working example code of the zend framework 1.9 from github to which a link is given to the last of the document .

Development Environment :

1 ) LAMP or WAMP or MAMP

2 ) Zendframework 1.9 configured .

3 ) I am using eclipse , netbeans and zend studio i5 . If you are using zend studio i5 , there is no need to look the command line, many are already in it .

I hope you have configured the first two . Now lets move to command line to create project , controllers and actions . The dollar ( $ ) symbol represents the command prompt .

$ zf create project blog

This will create the zend framework directory structure > 1.8 . Change the directory . ie cd <projectname>

hari@hari-laptop:/var/www/blog$ zf show profile
ProjectDirectory
    ProjectProfileFile
    ApplicationDirectory
        ConfigsDirectory
            ApplicationConfigFile
        ControllersDirectory
            ControllerFile
                ActionMethod
            ControllerFile
        ModelsDirectory
        ViewsDirectory
            ViewScriptsDirectory
                ViewControllerScriptsDirectory
                    ViewScriptFile
                ViewControllerScriptsDirectory
                    ViewScriptFile
            ViewHelpersDirectory
        BootstrapFile
    LibraryDirectory
    PublicDirectory
        PublicIndexFile
        HtaccessFile
    TestsDirectory
        TestPHPUnitConfigFile
        TestApplicationDirectory
            TestApplicationBootstrapFile
        TestLibraryDirectory
            TestLibraryBootstrapFile
 

This is how the directory structure will appear .

 zf create controller posts

Creating a controller at //var/www/blog/application/controllers/PostsController.php
Creating an index action method in controller posts
Creating a view script for the index action method at //var/www/blog/application/views/scripts/posts/index.phtml
Creating a controller test file at //var/www/blog/tests/application/controllers/PostsControllerTest.php
Updating project profile '//var/www/blog/.zfproject.xml'

 zf create action view posts

Creating an action named view inside controller at //var/www/blog/application/controllers/PostsController.php
Updating project profile '//var/www/blog/.zfproject.xml'
Creating a view script for the view action method at //var/www/blog/application/views/scripts/posts/view.phtml
Updating project profile '//var/www/blog/.zfproject.xml'

zf create action edit posts

Creating an action named edit inside controller at //var/www/blog/application/controllers/PostsController.php
Updating project profile '//var/www/blog/.zfproject.xml'
Creating a view script for the edit action method at //var/www/blog/application/views/scripts/posts/edit.phtml
Updating project profile '//var/www/blog/.zfproject.xml'

zf create action add posts

Creating an action named add inside controller at //var/www/blog/application/controllers/PostsController.php
Updating project profile '//var/www/blog/.zfproject.xml'
Creating a view script for the add action method at //var/www/blog/application/views/scripts/posts/add.phtml
Updating project profile '//var/www/blog/.zfproject.xml'

zf create action login index

Creating an action named login inside controller at //var/www/blog/application/controllers/IndexController.php
Updating project profile '//var/www/blog/.zfproject.xml'
Creating a view script for the login action method at //var/www/blog/application/views/scripts/index/login.phtml
Updating project profile '//var/www/blog/.zfproject.xml'

zf create action logout index

Creating an action named logout inside controller at //var/www/blog/application/controllers/IndexController.php
Updating project profile '//var/www/blog/.zfproject.xml'
Creating a view script for the logout action method at //var/www/blog/application/views/scripts/index/logout.phtml
Updating project profile '//var/www/blog/.zfproject.xml'

Create a database and add the tables users , comments and posts .

CREATE TABLE IF NOT EXISTS `comments` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Post_id` int(11) NOT NULL,
  `Description` varchar(300) NOT NULL,
  `Name` varchar(200) NOT NULL,
  `Email` varchar(250) NOT NULL,
  `Webpage` varchar(200) NOT NULL,
  `Postedon` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Title` varchar(250) NOT NULL,
  `Description` text NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;
CREATE TABLE IF NOT EXISTS `users` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `Username` varchar(200) NOT NULL,
  `Password` varchar(250) NOT NULL,
  `Role` varchar(10) NOT NULL,
  `Name` varchar(200) NOT NULL,
  PRIMARY KEY (`id`)
) ENGINE=MyISAM  DEFAULT CHARSET=latin1 AUTO_INCREMENT=1 ;

Add the code to Bootstrap.php so the other classes can be autoloaded . Same like __autoload() .

protected function _initAutoload()
    {
        $moduleLoader = new Zend_Application_Module_Autoloader(array(
            'namespace' => '',
            'basePath' => APPLICATION_PATH));
        return $moduleLoader;
    }

[ pagebreak ]

Part 2

Add the layout and db connection details in application/configs/application.ini . The complete code is kept below

[production]
phpSettings.display_startup_errors = 0
phpSettings.display_errors = 0
includePaths.library = APPLICATION_PATH "/../library"
bootstrap.path = APPLICATION_PATH "/Bootstrap.php"
bootstrap.class = "Bootstrap"
resources.frontController.controllerDirectory = APPLICATION_PATH "/controllers"
resources.layout.layoutPath = APPLICATION_PATH "/layouts/scripts"
resources.view[] = 
resources.db.adapter = PDO_MYSQL
resources.db.params.host = localhost
resources.db.params.username = root
resources.db.params.password = 
resources.db.params.dbname = hari_zendblog
[staging : production]
[testing : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1
[development : production]
phpSettings.display_startup_errors = 1
phpSettings.display_errors = 1

Add application/layouts/scripts/layout.phtml file with the code below

<?php 
echo $this->doctype() ?>
<html xmlns="http://www.w3.org/1999/xhtml"> 
<head>  
  <meta http-equiv="Content-Type" content="text/html; charset=utf-8" /> 
  <title>Bloggers turns to developers</title>
  <?php echo $this->headLink()->appendStylesheet('/quickstart/public/css/global.css') ?>
  <?php echo $this->headLink()->prependStylesheet($this->baseUrl().'/css/main.css'); ?>
</head> 
<body>
<div id="header" style="background-color: #EEEEEE; height: 30px;">
    <div id="header-logo" style="float: left">
        <b><a href="<?php echo $this->baseurl(); ?>">ZF Quickstart Application</a></b>&nbsp; &nbsp; 
        <a href="<?php 
        if( Zend_Auth::getInstance()->hasIdentity() ) { 
            $str = "/index/logout";
            $log = "Logout";  
           } else { 
               $str = "/index/login";
               $log = "Login";  
           } 
           echo $this->baseurl().$str; ?>"><?php echo $log; ?></a>
    </div>
</div>
<div><?php echo $this->layout()->content ?></div>
</body>
</html>
 

You can insert sample datas through the phpmyadmin or what ever way you like . So we can show some posts in the front . Add the below code to indexActon of IndexController .

public function indexAction()
    {
        // action body
        $posts = new Model_DbTable_Posts();
        $result = $posts->getPosts();
/* The below line is for pagination */
        $page = $this->_getParam('page',1);
        $paginator = Zend_Paginator::factory($result);
        $paginator->setItemCountPerPage(2);
/* Number of items in a page . I have kept 2 so you can easily see the pagination when there is 3 items inserted to posts table . */
        $paginator->setCurrentPageNumber($page);
        $this->view->paginator = $paginator;
    }

The complete code of IndexController.php is given below .

<?php
class IndexController extends Zend_Controller_Action
{
    public function init()
    {
        /* Initialize action controller here */
    }
    public function indexAction()
    {
        // action body
        $posts = new Model_DbTable_Posts();
        $result = $posts->getPosts();
        $page = $this->_getParam('page',1);
        $paginator = Zend_Paginator::factory($result);
        $paginator->setItemCountPerPage(2);
        $paginator->setCurrentPageNumber($page);
        $this->view->paginator = $paginator;
    }
    public function loginAction()
    {        
        $loginForm = new Form_Login();
        $redirect = $this->getRequest()->getParam('redirect', 'index/index');
        $loginForm->setAttrib('redirect', $redirect );
        $auth = Zend_Auth::getInstance();
        if(Zend_Auth::getInstance()->hasIdentity()) {
            $this->_redirect('/index/hello');
        } else if ($this->getRequest()->isPost()) {
            if ( $loginForm->isValid($this->getRequest()->getPost()) ) {
                $username = $this->getRequest()->getPost('username');
                $pwd = $this->getRequest()->getPost('pass');
                $authAdapter = new Model_AuthAdapter($username, $pwd);
                $result = $auth->authenticate($authAdapter);
                if(!$result->isValid()) {
                    switch ($result->getCode()) {
                       case Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID:
                            $this->view->errors = 'user credentials not found';
                    }
                } else {
                    //Successfully logged in
                    $this->_redirect( $redirect );
                }
            }
        }
        $this->view->loginForm = $loginForm;
//        $this->_redirect($redirectUrl);
    }
    public function logoutAction()
    {
        $auth = Zend_Auth::getInstance();
        $auth->clearIdentity();
        $this->_redirect('/');
    }
}

Forgot to add the post controller . Added after seeing the comment . Thanks for notifying me .

<?php

class PostsController extends Zend_Controller_Action
{

	public function init()
	{
		/* Initialize action controller here */
	}

	public function indexAction()
	{
		// action body
	}

	public function viewAction()
	{
		// action body
		$postid = (int)$this->_getParam('id');
		if( empty($postid) ) {
		}
		$post = new Model_DbTable_Posts();
		$result = $post->getPost($postid);
		$this->view->post = $result;
		$commentsObj = new Model_DbTable_Comments();
		$request = $this->getRequest();
		$commentsForm = new Form_Comments();
		/*
		 * Check the comment form has been posted
		 */
		if ($this->getRequest()->isPost()) {
			if ($commentsForm->isValid($request->getPost())) {
				$model = new Model_DbTable_Comments();
				$model->saveComment($commentsForm->getValues());
				$commentsForm->reset();
			}
		}
		$data = array( 'id'=> $postid );
		$commentsForm->populate( $data );
		$this->view->commentsForm = $commentsForm;
		$comments = $commentsObj->getComments($postid);
		$this->view->comments = $comments;
		$this->view->edit = '/posts/edit/id/'.$postid;
	}

	public function commentsAction()
	{
		// action body
	}

	public function addAction()
	{
		// action body
		if(!Zend_Auth::getInstance()->hasIdentity()) {
			$this->_redirect('index/index');
		}
                $acl = new Model_Acl();
		$identity = Zend_Auth::getInstance()->getIdentity();
                if( $acl->isAllowed( $identity['Role'] ,'posts','add') ) {
                    $request = $this->getRequest();
                    $postForm = new Form_Post();
                    if ($this->getRequest()->isPost()) {
                            if ($postForm->isValid($request->getPost())) {
                                    $model = new Model_DbTable_Posts();
                                    $model->savePost($postForm->getValues());
                                    $this->_redirect('index/index');
                            }
                    }
                    $this->view->postForm = $postForm;
                }
	}

	public function editAction()
	{
		// action body
		$request = $this->getRequest();
		$postid = (int)$request->getParam('id');
		if(!Zend_Auth::getInstance()->hasIdentity()) {
			$this->_redirect('posts/view/id/'.$postid);
		}
		$identity = Zend_Auth::getInstance()->getIdentity();
		
		$acl = new Model_Acl();
		if( $acl->isAllowed( $identity['Role'] ,'posts','edit') ) {
			$postForm = new Form_Post();
			$postModel = new Model_DbTable_Posts();
			if ($this->getRequest()->isPost()) {
				if ($postForm->isValid($request->getPost())) {
					$postModel->updatePost($postForm->getValues());
					$this->_redirect('posts/view/id/'.$postid);
				}
			} else {
				$result = $postModel->getPost($postid);
				$postForm->populate( $result );
			}
			$this->view->postForm = $postForm;
		} else {
			var_dump( $identity['Role'] );
			//$this->_redirect('posts/view/id/'.$postid);
		}
	}

}

Now you need to create a connection to posts table so that we can do insertion , edit etc . Keep the file in application/Models/DbTable/Posts.php

<?php
class Model_DbTable_Posts extends Zend_Db_Table_Abstract
{
    protected $_name = 'posts';
    public function getPosts()
    {
        $orderby = array('id DESC');
        $result = $this->fetchAll('1', $orderby );
        return $result->toArray();
    }
    public function getPost( $id )
    {
        $id = (int)$id;
        $row = $this->fetchRow('id = ' . $id);
        if (!$row) {
            throw new Exception("Count not find row $id");
        }
        return $row->toArray();
    }
    /*
     * Add new posts
     */
    public function savePost( $post )
    {
        $data = array( 'Title'=> $post['Title'],
                'Description'=> $post['Description']);
        $this->insert($data);
    }
    /*
     * Update old posts
     */
    public function updatePost( $post )
    {
        $data = array(
                'id'=> $post['id'],
                'Title'=> $post['Title'],
                'Description'=> $post['Description']);
        $where = 'id = '.$post['id'];
        $this->update($data , $where );
    }
}

[ pagebreak ]

Create application/Models/DbTable/Users.php

<?php
class Model_DbTable_Users extends Zend_Db_Table_Abstract
{
    protected $_name = 'users';
    public function findCredentials($username, $pwd)
    {
        $select = $this->select()->where('username = ?', $username)
            ->where('password = ?', $this->hashPassword($pwd));
        $row = $this->fetchRow($select);
        if($row) {
            return $row;
        }
        return false;
    }
    protected function hashPassword($pwd)
    {
        return md5($pwd);
    }
}

Create application/Models/DbTable/Comments.php

<?php
class Model_DbTable_Comments extends Zend_Db_Table_Abstract
{
    protected $_name = 'comments';
    public function getComments( $postid ) 
    {
        $result = $this->fetchAll( "post_id = '$postid'"  );
        return $result->toArray();
    }
    public function saveComment( $commentForm )
    {
        $data = array('post_id' => $commentForm['id'] ,
                'Description' => $commentForm['comment'],
                'Name' => $commentForm['name'],
                'Email' => $commentForm['email'],
                'Webpage' => $commentForm['webpage'] );
        $this->insert($data);
    }
}

 Now lets create a login form in /application/forms/Login.php directory . 

<?php
class Form_Login extends Zend_Form
{
    public function __construct()
    {
        parent::__construct($options);
        $this->setName('UserLogin');
        $username = new Zend_Form_Element_Text('username');
        $username->setLabel('User Name')
                ->setRequired(true)
                ->addFilter('StripTags')
                ->addFilter('StringTrim')
                ->addValidator('NotEmpty');
        $pass = new Zend_Form_Element_Password('pass');
        $pass->setLabel('Password')
                ->setRequired(true)
                ->addFilter('StripTags')
                ->addFilter('StringTrim')
                ->addValidator('NotEmpty');
        $submit = new Zend_Form_Element_Submit('submit');
        $redirect = new Zend_Form_Element_Hidden('redirect');
        $submit->setAttrib('id', 'submitbutton');
        $this->addElements( array ( $username, $pass, $submit));
    }
}

Create a form for posting and commenting

application/forms/posts.php

<?php
class Form_Post extends Zend_Form
{
    public function __construct()
    {
        parent::__construct($options);
        $this->setName('Posts');
        $id = new Zend_Form_Element_Hidden('id');
        $title = new Zend_Form_Element_Text('Title');
        $title->setLabel('Title')
                ->setRequired(true)
                ->addFilter('StripTags')
                ->addFilter('StringTrim')
                ->addValidator('NotEmpty');
        $description = new Zend_Form_Element_Textarea('Description');
        $description->setLabel('Description')
                ->setRequired(true)
                ->setAttrib('rows',20)
                ->setAttrib('cols',50)
                ->addFilter('StripTags')
                ->addFilter('StringTrim')
                ->addValidator('NotEmpty');
        $submit = new Zend_Form_Element_Submit('submit');
        $submit->setAttrib('id', 'submitbutton');
        $this->addElements( array( $id, $title, $description, $submit ));
    }
}

Create a comments form application/forms/Comments.php for adding comments

<?php
class Form_Comments extends Zend_Form
{
    public function __construct()
    {
        $acl = new Model_Acl();
        $identity = Zend_Auth::getInstance()->getIdentity();
        /*
        * Check whether they have permission to add comments
        */
        if( Zend_Auth::getInstance()->hasIdentity()
        && $acl->isAllowed( $identity['role'] ,'comments','add') ) {
            parent::__construct($options);
            $this->setName('Comments');
            $id = new Zend_Form_Element_Hidden('id');
            $name = new Zend_Form_Element_Text('name');
            $name->setLabel('Your Name')
            ->setRequired(true)
            ->addFilter('StripTags')
            ->addFilter('StringTrim')
            ->addValidator('NotEmpty');
            $email = new Zend_Form_Element_Text('email');
            $email->setLabel('Email')
            ->setRequired(true)
            ->addFilter('StripTags')
            ->addFilter('StringTrim')
            ->addValidator('NotEmpty');
            $webpage = new Zend_Form_Element_Text('webpage');
            $webpage->setLabel('Webpage')
            ->setRequired(true)
            ->addFilter('StripTags')
            ->addFilter('StringTrim')
            ->addValidator('NotEmpty');
            $comment = new Zend_Form_Element_Textarea('comment');
            $comment->setLabel('Comments')
            ->setRequired(true)
            ->setAttrib('rows',7)
            ->setAttrib('cols',30)
            ->addFilter('StripTags')
            ->addFilter('StringTrim')
            ->addValidator('NotEmpty');
            $submit = new Zend_Form_Element_Submit('submit');
            $submit->setAttrib('id', 'submitbutton');
            $this->addElements( array ($id, $name, $email, $webpage, $comment, $submit));
        }
    }
}

Create application/Models/Acl.php

<?php
class Model_Acl extends Zend_Acl 
{
    public function __construct() 
    {
        /*
         *  Add a new role called "guest"
         *  Guest can view contents of the site 
         */
        $this->addRole(new Zend_Acl_Role('guest'));
        /* 
         * Add a role called user, which inherits from guest
         * Users can post comments in site
         */
        $this->addRole(new Zend_Acl_Role('user'), 'guest');
        /* 
         * Add a role called blogger, which inherits from user
         * Bloggers can post contents
         */
        $this->addRole(new Zend_Acl_Role('blogger'), 'user');
        /*
         * Add a role for admin which inherits blogger
         * With every privilages
         */
        $this->addRole(new Zend_Acl_Role('admin'), 'blogger');
        //Add a resource called posts
        $this->add(new Zend_Acl_Resource('posts'));
        //Add a resource called edit, which inherits posts
        //$this->add(new Zend_Acl_Resource('edit'), 'posts');
        //Add a resource called edit
        //$this->add(new Zend_Acl_Resource('add'), 'posts');
        //Finally, we want to allow guests to view pages
        $this->allow('guest', 'posts', 'view');
        // Bloggers can add, edit posts
        $this->allow('blogger', 'posts', 'edit');
        $this->allow('blogger', 'posts', 'add');
    }
}

Create application/Models/AuthAdapter.php

<?php
class Model_AuthAdapter implements Zend_Auth_Adapter_Interface
{
    protected $username;
    protected $password;
    protected $user;
    public function __construct($username, $password) {
        $this->username = $username;
        $this->password = $password;
        $this->user = new Model_DbTable_Users();
    }
    public function authenticate()
    {
        $match = $this->user->findCredentials($this->username, $this->password);
        //var_dump($match);
        if(!$match) {
            $result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);
        } else {
            $user = current($match);
            $result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $user);
        }
        return $result;
    }
}

Create application/views/helpers/BaseUrl.php

<?php
class Zend_View_Helper_BaseUrl {
    function baseUrl() {
        $fc = Zend_Controller_Front::getInstance();
        return $fc->getBaseUrl();
    }
}
?>

Create application/views/helpers/LinkTo.php

<?php
class Zend_View_Helper_LinkTo
{
    protected static $baseUrl = null;
    public function linkTo($path)
    {
        if (self::$baseUrl === null) {
            $request = Zend_Controller_Front::getInstance()->getRequest();
            $root = '/' . trim($request->getBaseUrl(), '/');
            if ($root == '/') {
                $root = '';
            }
            self::$baseUrl = $root . '/';
        }
        return self::$baseUrl . ltrim($path, '/');
    }
}

[ pagebreak ]

Create application/views/helpers/LoggedInUser.php

<?php
class Zend_View_Helper_LoggedInUser
{
    protected $_view;
    function setView($view)
    {
    $this->_view = $view;
    }
    function loggedInUser()
    {
        $auth = Zend_Auth::getInstance();
        if($auth->hasIdentity())
        {
            $logoutUrl = $this->_view->linkTo('auth/logout');
            $user = $auth->getIdentity();
            $username = $this->_view->escape(ucfirst($user->username));
            $string = 'Logged in as ' . $username . ' | <a href="' .
            $logoutUrl . '">Log out</a>';
        } else {
            $loginUrl = $this->_view->linkTo('auth/identify');
            $string = '<a href="'. $loginUrl . '">Log in</a>';
        }
        return $string;
    }
}
 

Change the contents of application/views/scripts/index/index.phtml with

<?php if (count($this->paginator)): ?>
<?php foreach ($this->paginator as $post ): ?>
<div class="post">
  <div class="title"><a href="<?php echo $this->baseUrl()."/posts/view/id/".$post['id']; ?>"><?php echo $this->escape($post['Title']); ?></a></div>
  <div class="description"><?php echo nl2br(substr( strip_tags( $post['Description']), 0 , 300)); ?></div>
  <div class="commentscount">Comments( count )</div>
</div>
<?php endforeach; ?>
<?php endif; ?>
<div class="pagination"><?php echo $this->paginationControl($this->paginator,
                                    'Sliding',
                                    '/partials/my_pagination_control.phtml'); ?></div>

Change the contents of application/views/scripts/index/login.phtml with

<?php echo $this->errors; ?>
<?php echo $this->loginForm; ?>

Change the contents of application/views/scripts/index/logout.phtml with

<div>Successfully Logged out</div>

Create application/views/scripts/partials/my_pagination_control.phtml with (  You can place partials in a different folder too . I forgot to change that )

<?php if ($this->pageCount): ?>
<div class="paginationControl">
<!-- Previous page link -->
<?php if (isset($this->previous)): ?>
  <a href="<?php echo $this->url(array('page' => $this->previous)); ?>">
    &lt; Previous
  </a> |
<?php else: ?>
  <span class="disabled">&lt; Previous</span> |
<?php endif; ?>
<!-- Numbered page links -->
<?php foreach ($this->pagesInRange as $page): ?>
  <?php if ($page != $this->current): ?>
    <a href="<?php echo $this->url(array('page' => $page)); ?>">
        <?php echo $page; ?>
    </a> |
  <?php else: ?>
    <?php echo $page; ?> |
  <?php endif; ?>
<?php endforeach; ?>
<!-- Next page link -->
<?php if (isset($this->next)): ?>
  <a href="<?php echo $this->url(array('page' => $this->next)); ?>">
    Next &gt;
  </a>
<?php else: ?>
  <span class="disabled">Next &gt;</span>
<?php endif; ?>
</div>
<?php endif; ?>
<?php
/*
 * Drop down paginaton example
 */
/*
?>
<?php if ($this->pageCount): ?>
<select id="paginationControl" size="1">
<?php foreach ($this->pagesInRange as $page): ?>
  <?php $selected = ($page == $this->current) ? ' selected="selected"' : ''; ?>
  <option value="<?php
        echo $this->url(array('page' => $page));?>"<?php echo $selected ?>>
    <?php echo $page; ?>
  </option>
<?php endforeach; ?>
</select>
<?php endif; ?>
<script type="text/javascript"
     src="http://ajax.googleapis.com/ajax/libs/prototype/1.6.0.2/prototype.js">
</script>
<script type="text/javascript">
$('paginationControl').observe('change', function() {
    window.location = this.options[this.selectedIndex].value;
})
</script>
*/?>

Change application/views/scripts/posts/add.phtml with

<div><?php echo $this->postForm; ?></div>

Change application/views/scripts/posts/edit.phtml with

<h2>Edit Post</h2>
<div><?php echo $this->postForm; ?></div>

Change application/views/scripts/posts/view.phtml with

<div class="title"><?php echo $this->post['Title']; ?></div>
<div class="description"><?php echo $this->post['Description'];  ?></div>
<?php
    $acl = new Model_Acl(); 
    $identity = Zend_Auth::getInstance()->getIdentity();
    if( Zend_Auth::getInstance()->hasIdentity() && $acl->isAllowed( $identity['role'] ,'posts','edit') ) : ?>
<div><a href="<?php echo $this->baseurl().$this->edit; ?>">Edit</a></div> 
<?php endif; ?> 
<div class="comments">
    <?php if( count($this->comments) ) : ?>
        <?php foreach( $this->comments as $comment ) : ?>
            <div class="postedby"><a href="<?php echo $comment['Webpage']; ?>" ><?php echo $this->escape( $comment['Name'] ); ?></a> on <span><?php echo $this->escape( date( 'd-m-Y', strtotime($comment['Postedon']) ) ); ?></span></div>
            <div class="comment"><?php echo $this->escape( $comment['Description'] ); ?></div>
        <?php endforeach; ?>
    <?php else : ?>
    <div>No comments</div>
    <?php endif; ?>
</div>
<div class="newcomments">
<?php if( Zend_Auth::getInstance()->hasIdentity() ) : 
        echo $this->commentsForm;
    else :
        ?>Login to Post comments<?php 
    endif;
?>
</div>

I hope I have not missed any when adding to the blog . If there is any erros  do let me know . You can grab the working copy from git , that will be good if there is some errors . I have got many helps from more than 50 blogs . I have made a custom search engine for the zend framework learning too . In the earlier post I have posted .

Thanks and I hope you will enjoy my small blog, and If there is any confusing part let me know it. You can post comments rather than directly mailing to me . You can grab the piece of code from http://github.com/harikt/zendblog and don't be shy as Jon Lembord of http://zendcasts.com says . . Thanks for the wonderful facility provided by github and git .

I have also posted a new post for those who are looking for a module and admin layout. Do check it and get the files from http://www.harikt.com/content/base-files-start-your-zend-framework-project . This may be useful for you to start your zend framework project .

Tags: 

Comments

The mysql driver is not currently installed Error Message

Cany's picture

Please help!!! I am stuck When I run the tutorial website using the ZendFramework, I am getting this error, "The mysql driver is not currently installed". There are no errors in my Apache error logs. I am using: Apache2.2 PHP5.3 latest ZendFramework version Below is the error I am getting: Error Message: The mysql driver is not currently installed Stack trace: #0 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Adapter\Pdo\Mysql.php(96): Zend_Db_Adapter_Pdo_Abstract->_connect() #1 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Adapter\Abstract.php(448): Zend_Db_Adapter_Pdo_Mysql->_connect() #2 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Adapter\Pdo\Abstract.php(238): Zend_Db_Adapter_Abstract->query('DESCRIBE `album...', Array) #3 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Adapter\Pdo\Mysql.php(156): Zend_Db_Adapter_Pdo_Abstract->query('DESCRIBE `album...') #4 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Abstract.php(814): Zend_Db_Adapter_Pdo_Mysql->describeTable('albums', NULL) #5 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Abstract.php(857): Zend_Db_Table_Abstract->_setupMetadata() #6 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Abstract.php(964): Zend_Db_Table_Abstract->_setupPrimaryKey() #7 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Select.php(100): Zend_Db_Table_Abstract->info() #8 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Select.php(78): Zend_Db_Table_Select->setTable(Object(Model_DbTable_Albums)) #9 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Abstract.php(1000): Zend_Db_Table_Select->__construct(Object(Model_DbTable_Albums)) #10 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Db\Table\Abstract.php(1286): Zend_Db_Table_Abstract->select() #11 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\application\controllers\IndexController.php(16): Zend_Db_Table_Abstract->fetchAll() #12 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Controller\Action.php(513): IndexController->indexAction() #13 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Controller\Dispatcher\Standard.php(289): Zend_Controller_Action->dispatch('indexAction') #14 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Controller\Front.php(946): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #15 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Application\Bootstrap\Bootstrap.php(77): Zend_Controller_Front->dispatch() #16 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\library\Zend\Application.php(346): Zend_Application_Bootstrap_Bootstrap->run() #17 C:\Program Files\Apache Software Foundation\Apache2.2\htdocs\zf-tutorial\public\index.php(26): Zend_Application->run() #18 {main} Request Parameters: array ( 'controller' => 'index', 'action' => 'index', 'module' => 'default', ) Please help!!

How do i install PDO_MYSQL driver in windows

Cany's picture

I installed PHP, Mysql, and Apache separately. I am using windows. I am getting this error, "The mysql driver is not currently installed". How do I installed and configure the PDO MYSQL Driver in windows. I already enable these and other extensions in my PHP.ini file; extension=php_pdo.dll extension=php_mysql.dll extension=php_mysqli.dll extension=php_pdo_mysql.dll extension=php_pdo_sqlite.dll Do I have to do something in phpForApach.ini file?? Help!!!

Problems

Anonymous's picture

Good Tutorial but i get this Error Notice: Undefined variable: options in E:\ab\cd\ef\gh\application\forms\Login.php on line 6

I get $option error

Ulferik's picture

I have installed your application and it works fine. Now I am trying to implement the login method and get the eroor "C:\Program Files (x86)\Zend\Apache2\htdocs\Ulferik\application\forms\Login.php on line 6".
Can you tell me where this $option is suppose to come from? I have found it in several places but not where it is declared.

Thank's for sharing this tutorial whit us.

Ulferik

RE: Typo & What version of ZF?

Chris's picture

Hey I am following this tutorial and was wondering what version of ZF this works with? Also, if you check line 12 in the application.ini listing, you will see that its actually the title for the list below! :) It makes it kinda difficult to know which file the listing is for!?

Hi, First, thank-you very

Ader's picture

Hi, First, thank-you very much for your tutorial. It was very helpfull. I´m doing an implementation of your code, but when I try to submit the form, I get the error below. I believe that the problem comes from the "$result = new Zend_Auth_Result(Zend_Auth_Result::FAILURE_CREDENTIAL_INVALID, null);" and "$result = new Zend_Auth_Result(Zend_Auth_Result::SUCCESS, $user);" in the AuthAdapter.php file. When I comment them, the error below doesn´t happen. Fatal error: Uncaught exception 'Zend_Controller_Dispatcher_Exception' with message 'Invalid controller specified (error)' in H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\library\Zend\Controller\Dispatcher\Standard.php:241 Stack trace: #0 H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\library\Zend\Controller\Front.php(936): Zend_Controller_Dispatcher_Standard->dispatch(Object(Zend_Controller_Request_Http), Object(Zend_Controller_Response_Http)) #1 H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\library\Zend\Application\Bootstrap\Bootstrap.php(77): Zend_Controller_Front->dispatch() #2 H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\library\Zend\Application.php(303): Zend_Application_Bootstrap_Bootstrap->run() #3 H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\public\index.php(38): Zend_Application->run() #4 {main} thrown in H:\SERVER_ADER\WEBARCHITECT\HTDOCS\DP_INTRANET\PRODUCAO\library\Zend\Controller\Dispatcher\Standard.php on line 241 What am I doing wrong? Thanks in Advance.

Just another doubt

Ader's picture

Hey Hari,

I hope I´m not being a burden, but answering your question I did not create my project using zf.

Instead, I´ve made exactly as they explain at this tutorial http://framework.zend.com/docs/quickstart/create-your-project, but the structure itself I created by hand.

As soon as I created an Error controller, it worked perfectly. So my question is just one thing: why do I need an error controller in this case? Where in the project it would say that it is required, if there´s such parameter? application.ini ? Would it be the "phpSettings.display_startup_errors = 1" ?

Thanks a lot in advance.

wrong use of headlink()

RapidShare's picture

Hello, first of all great tutorial, I am learning a lot from it. You have a little bug in the HEAD section. headlink() should be echoed only once. In your case the link tags for the css will be duplicated in the output. The correct version would be : <?php $this->headLink()->appendStylesheet('/quickstart/public/css/global.css') ?> <?php $this->headLink()->prependStylesheet($this->baseUrl().'/css/main.css'); ?> <?php echo $this->headLink(); ?> Friendly regards.

Hi, Just curious, why

edwardc's picture

Hi, Just curious, why does "Change the contents of application/views/scripts/index/logout.phtml with" Appear twice with 2 source code boxes? Is it an error?

Hi, Thanks so much for the

edwardc's picture

Hi, Thanks so much for the tutorial, the Auth and Acl was especially useful. However I'm confused by two mentions of: Change the contents of application/views/scripts/index/logout.phtml with is that an error?

This may be just a tutorial

Noel Darlow's picture

This may be just a tutorial for a simple application but the entire code is a mess. I know the Zend Framework is meant to give a modular approach to PHP development but like so many examples I see, this is openly absuive. It's nothing personal, as you are not alone - there is just so much rubbish out there and unfortunately you are only contributing to it.

Great post. I am pretty new

arash's picture

Great post. I am pretty new to zend but I just wanted to know how you retrive the parameters from the ini file and instantiate the database connection. Thank you

Hi, there are few bugs. In

Jan Tlapák's picture

Hi,

there are few bugs.

In application/forms/Comments.php on line 13 there should be $identity['Role'] instead of $identity['role']

In application/Models/Acl.php you should add $this->allow('blogger', 'comments', 'add');

But still helpfull tut.

Thank you!
Jan

Great tutorial but...

Chris's picture

great stuff but i have read loads of tutorials about acl and auth but never get shown how to assign a role to a user? how to do it properly, i have found it quite hard searching for acl and auth info for cakephp and zend framework that actually shows all steps...any help or websites would be great! :D thanks

Controllers are not passing

santhosh's picture

hi thanks for ur Blog regarding zend acl perfect blog to start with but i'm new to zend framework every thing is working fine with the index controller but its not taking to other controllers such as Gallery controller as well as the postcontrollers please help me out with some tips ASAP

Its showing error like
Not Found

The requested URL /harikt-zendblog-86859be/public/gallery was not found on this server.
Apache/2.2.11 (Ubuntu) PHP/5.2.6-3ubuntu4.2 with Suhosin-Patch Server at localhost Port 80
please help me out with some tips ASAP

Thanks n Best wishes

Thanks!

David Weinraub's picture

Hi Hari,

I, too, am learning ZF, so I want to say thanks for two things.

1. Thanks for a great sample app. A nice level, not too trivial, not too difficult. Especially the Auth/ACL stuff. Very helpful.

2. Thanks for being so open about your experience. I appreciate your candor that: you are learning; you are doing the best you can; you might make some mistakes, either in code or in design; you welcome the feedback about mistakes and ways to do things better. Your app might not be the most polished out there, but I find your manner to be quite refreshing. It gives me a bit more confidence to simply put myself out there like you are doing.

It would be interesting perhaps to add Routing to the blog app. Perhaps not out of necessity - there is nothing wrong with the current urls of the form "controller/action/k1/v1/k2/v2". But it might be instructive to see an example of how to define routes, some ideas about where to define them, conventions for naming the plugin class and for placing the plugin file in the file-system. All that good stuff.

Again, thanks for an excellent contribution to the ZF community, especially for us noobs.

Cheers!

Hi, Firstly thanks for all

Mahmood's picture

Hi,

Firstly thanks for all the open minded posts you wrote. I read most of them. I still could not figure out how to run this application. I can run the public/index page which lists the items from the database but when i click on an item for detail - on its title it gives me these errors
--->

An error occurred
message ?>
Exception information:
Message: exception->getMessage() ?>

Stack trace:
exception->getTraceAsString() ?>
Request Parameters:
request->getParams()) ?>

<----

I can see the pagination on the first page of public but when i click on anything else its gone. Can you help me out. Thanks. Can it be that your application here is a bit different than on github code.

Thanks,
Mahmood

Hi, it is really useful stuff

Marek's picture

Hi, it is really useful stuff for beginners, thanks.

I found a little bug in your code:
application/controllers/IndexController in loginAction you have line
$this->view->errors = 'user credentials not found';
and in login view there is
<?php echo $this->error; ?>
so you should change 'error' to 'errors' in login.phtml file

Pages