webSIGHTdesigns - Web Design, Web Development, Web Hosting

How to Create a Blog in CakePHP

Posted on Saturday, December 21st, 2013 at 12:21 pm
by webSIGHTdesigns

This tutorial explains how to create a blog using CakePHP.

In this tutorial we will discuss how to create a blog in CakePHP, an MVC framework for PHP. You could follow this tutorial without including the latest Twitter Bootstrap 3 in your Layout/default.ctp, but it will look slightly better if you do. 

Model

To set up our model we create a file called Posts.php in our app/Model/ directory:

<?php

class Post extends AppModel {

	public function beforeSave($options = array()) {
		// set the url slug
		if (isset($this->data[$this->alias]['title'])) {
			$this->data[$this->alias]['slug'] = strtolower(Inflector::slug($this->data[$this->alias]['title'], $replacement='-'));
		}
		// set p tags around the lead text
		if (isset($this->data[$this->alias]['lead'])) {
			$this->data[$this->alias]['lead'] = str_replace('<p>', '<p class="lead">', $this->data[$this->alias]['lead']);
		}
		// if published is set to 1 and there is no publish_date, set the publish_date to now.
		if ($this->data[$this->alias]['published'] == "1" && $this->data[$this->alias]['publish_date'] === FALSE) {
			$this->data[$this->alias]['publish_date'] = date('Y-m-d H:i:s');
		}

		return true;
	}

	public $validate = array(
		'title' => array(
			'required' => array(
				'rule' => array('notEmpty'),
				'message' => 'A title is required'
			)
		),
		'body' => array(
			'required' => array(
				'rule' => array('notEmpty'),
				'message' => 'A body is required'
			)
		)
	);

}

In the above model we're setting up a slug for the URL based on the Post title, wrapping p tags around our lead text, and setting a publish_date the first time we save the Post while checking the "Published" checkbox in our edit form.

View

Now we need to create some files to set up our views in the app/View/ directory. We'll start with the index.ctp file:

<?php foreach ($posts as $post): ?>
	<p>
		<a href="<?php echo $this->webroot; ?>posts/view/<?php echo $post['Post']['slug']; ?>" class="list-group-item">
		<?php if($post['Post']['lead']) echo strip_tags($post['Post']['lead']); ?>
		</a>
		<br />
		<small>Posted on <?php
			if($post['Post']['publish_date'] == "0000-00-00 00:00:00" || !$post['Post']['publish_date']) {
				$date = $post['Post']['created'];
			} else {
				$date = $post['Post']['publish_date'];
			}
			echo date("l, F jS, Y \\a\\t g:i a", strtotime($date));
		?></small>
	</p>
<?php endforeach; ?>

<?php echo $this->Paginator->numbers(array(
	'first' => '«',
	'before' => '<ul class="pagination pagination-sm">',
	'after' => '</ul>',
	'separator' => '',
	'tag' => 'li',
	'currentClass' => 'active',
	'currentTag' => 'a'
)); ?>

Next the view.ctp file to show an individual blog post:

<!-- app/View/Posts/view.ctp -->
<?php if(isset($post['Post'])) $title_for_layout =  $post['Post']['title'] . " - webSIGHTdesigns"; ?>
<?php if(isset($post['Post'])): ?>
	<h2 class="featurette-heading"><?php echo $post['Post']['title']; ?></h2>
	<p><small>Posted on <?php
		if($post['Post']['publish_date'] == "0000-00-00 00:00:00" || !$post['Post']['publish_date']) {
			$date = $post['Post']['created'];
		} else {
			$date = $post['Post']['publish_date'];
		}
		echo date("l, F jS, Y \\a\\t g:i a", strtotime($date));
	?></small></p>
	<?php if(isset($post['Post']['lead'])) echo $post['Post']['lead']; ?>
	<?php if(isset($post['Post']['body'])) echo $post['Post']['body']; ?>
<?php else: ?>
	<h2 class="featurette-heading">Page Not Found</h2>
	<p>Sorry we could not find that page.</p>
<?php endif; ?>

And our add.ctp file for adding new blog posts:

<!-- app/View/Posts/add.ctp -->
<?php if ($this->Session->read('Auth.User')) { ?>

	<?php echo $this->Form->create('Post', array(
		'inputDefaults' => array(
			'div' => 'form-group',
			'wrapInput' => false,
			'class' => 'form-control'
		),
		'class' => 'well')); ?>
	<fieldset>
		<legend><?php echo __('Add a New Post'); ?></legend>
		<?php
			echo $this->Form->input('title', array('label' => 'Post Title', 'size' => '58', 'placeholder' => 'Title'));
			echo $this->Form->input('lead', array('label' => 'Introduction', 'class' => 'leadeditor', 'rows' => '4', 'cols' => '62'));
			echo $this->Form->input('body', array('class' => 'editor', 'rows' => '15', 'cols' => '62'));
			echo $this->Form->checkbox('published', array('checked' => 'checked', 'hiddenField' => false)) . ' Publish Now';
		?>
	</fieldset>

	<?php
		$options = array(
			'label' => 'Add Post',
			'class' => 'btn btn-primary',
			'div' => array('style' => 'margin-top:1em;', 'class' => 'submit')
		);
		echo $this->Form->end($options);
	?>

<?php } ?>

And our edit.ctp file for editing blog posts:

<!-- app/View/Posts/edit.ctp -->
<?php if ($this->Session->read('Auth.User')) { ?>

	<?php echo $this->Form->create('Post'); ?>
	<fieldset>
		<legend><?php echo __('Edit Post'); ?></legend>
		<?php
			echo $this->Form->input('title', array('label' => 'Title', 'size' => '58'));
			echo $this->Form->input('lead', array('label' => 'Introduction', 'class' => 'leadeditor', 'rows' => '4', 'cols' => '62'));
			echo $this->Form->input('body', array('label' => 'Body', 'class' => 'editor', 'rows' => '15', 'cols' => '62'));
			echo $this->Form->checkbox('published', array('value' => 1)) . ' Published';
		?>
	</fieldset>
	<?php
		$options = array(
			'label' => 'Save Post',
			'class' => 'btn btn-primary',
			'div' => array('style' => 'margin-top:1em;', 'class' => 'submit')
		);
		echo $this->Form->end($options);
	?>

<?php } ?>

Controller

Next we'll set up our Controller by creating a PostsController.php file in the app/Controllers/ directory:

<?php

class PostsController extends AppController {

	public $components = array('Paginator', 'RequestHandler');

	public $helpers = array('Html', 'Form', 'Text');

	/**
	 * index method
	 *
	 * @return void
	 */
	public function index() {
		if ($this->RequestHandler->isRss()) {
			$posts = $this->Post->find('all', array(
				'conditions' => array('Post.published' => '1'),
				'limit' => 20,
				'order' => 'Post.publish_date DESC'
			));
			return $this->set(compact('posts'));
		}
		$limit = '10';
		if($this->Session->read('Auth.User')) {
			if($this->Session->read('Auth.User.role') == "admin" || $this->Session->read('Auth.User.role') == "editor") {
				$this->paginate = array(
					'limit' => $limit,
					'order' => 'Post.publish_date DESC'
				);
			} elseif($this->Session->read('Auth.User.role') == "author") {
				$this->paginate = array(
					'conditions' => array(
						array(
							'or' => array(
								'Post.published' => '1',
								'Post.author_id' => $this->Session->read('Auth.User.id')
							)
						)
					),
					'limit' => $limit,
					'order' => array('Post.publish_date' => 'DESC')
				);
			} else {
				$this->paginate = array(
					'conditions' => array('Post.published' => '1'),
					'limit' => $limit,
					'order' => array('Post.publish_date' => 'DESC')
				);
			}
		} else {
			$this->paginate = array(
				'conditions' => array('Post.published' => '1'),
				'limit' => $limit,
				'order' => array('Post.publish_date' => 'DESC')
			);
		}
		$this->set('posts', $this->paginate('Post'));
	}

	/**
	 * view method
	 *
	 * @throws NotFoundException
	 * @param string $slug
	 * @return void
	 */
	public function view($slug=null) {
		if (is_null($slug)) {
			throw new NotFoundException(__('Not Found'));
		} else {
			$this->Post->updateAll(array('Post.views'=>'Post.views+1'), array('Post.slug'=>$slug));
			$post = $this->Post->find('first', array('conditions'=>array('Post.slug'=>$slug)));
			if (!$post) {
				throw new NotFoundException(__('Not Found'));
			} else {
				if($this->Session->read('Auth.User')) {
					if($this->Session->read('Auth.User.role') == "admin" || $this->Session->read('Auth.User.role') == "editor") {
						$this->set('title_for_layout', $post['Post']['title']);
						$this->set(compact('post'));
					} else {
						if($post['Post']['published'] != "0") {
							$this->set('title_for_layout', $post['Post']['title']);
							$this->set(compact('post'));
						} else {
							throw new NotFoundException(__('Not Found'));
						}
					}
				} else {
					if($post['Post']['published'] == "0") {
						throw new NotFoundException(__('Not Found'));
					} elseif($post['Post']['published'] == "1") {
						$this->set('title_for_layout', $post['Post']['title']);
						$this->set(compact('post'));
					}
				}
			}
		}
	}

	/**
	 * search method
	 *
	 * @return void
	 */
	public function search() {
		$limit = '10';
		$this->paginate = array(
			'conditions' => array(
				array(
					'or' => array(
						'Post.title LIKE' => '%'.$this->request->query['q'].'%',
						'Post.lead LIKE' => '%'.$this->request->query['q'].'%',
						'Post.body LIKE' => '%'.$this->request->query['q'].'%'
					),
					'Post.published' => '1'
				)
			),
			'limit' => $limit
		);
		$posts = $this->paginate('Post');
		$this->set('title_for_layout', "Search Results");
		$this->set(compact('posts'));
	}

	/**
	 * add method
	 *
	 * @todo add related info that every post will need to get started, i.e. global template
	 *
	 * @return void
	 */
	public function add() {
		if($this->Session->read('Auth.User')) {
			if ($this->request->is('post')) {
				if ($post = $this->Post->save($this->request->data)) {
					$this->Session->setFlash(__('The post has been saved.'), 'flash/success');
					$this->redirect(array('action' => 'index'));
				} else {
					$this->Session->setFlash(__('The post could not be saved. Please, try again.'), 'error');
				}
			}
			$this->set('posts', $this->Post->find('all'));
		} else {
			throw new NotFoundException(__('Not Found'));
		}
	}

	/**
	 * edit method
	 *
	 * @throws NotFoundException
	 * @param string $slug
	 * @return void
	 */
	public function edit($slug = null) {
		if($this->Session->read('Auth.User')) {
			if (is_null($slug)) {
				throw new NotFoundException(__('Page not found.'));
			}
			$post = $this->Post->findBySlug($slug);
			$this->Post->id = $post['Post']['id'];
			if ($this->request->is('post') || $this->request->is('put')) {
				if ($this->Post->save($this->request->data)) {
					$this->Session->setFlash(__('The post has been saved.'), 'flash/success');
					$this->redirect(array('action' => 'view', $slug));
				} else {
					$this->Session->setFlash(__('The post could not be saved. Please, try again.'), 'error');
				}
			}
			$this->request->data = $this->Post->findBySlug($slug);
			$this->set('post_id', $this->Post->id);
		} else {
			throw new NotFoundException(__('Not Found'));
		}
	}

	/**
	 * delete method
	 *
	 * @throws MethodNotAllowedException
	 * @throws NotFoundException
	 * @param string $id
	 * @return void
	 */
	public function delete($slug = null) {
		if($this->Session->read('Auth.User')) {
			if (!$this->request->is('post')) {
				throw new MethodNotAllowedException();
			}
			$post = $this->Post->findBySlug($slug);
			$this->Post->id = $post['Post']['id'];
			if (!$this->Post->exists()) {
				throw new NotFoundException(__('Invalid post'));
			}
			if ($this->Post->delete()) {
				$this->Session->setFlash(__('Post deleted.'), 'flash/success');
				$this->redirect(array('action' => 'index'));
			}
			$this->Session->setFlash(__('Post was not deleted.'), 'error');
			$this->redirect(array('action' => 'index'));
		} else {
			throw new NotFoundException(__('Not Found'));
		}
	}
}

Database

You will also need to create a table in your database to store your posts. You can do so by running the following SQL statement:

CREATE TABLE IF NOT EXISTS `posts` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `slug` varchar(255) NOT NULL,
  `title` varchar(100) NOT NULL,
  `lead` text NOT NULL,
  `body` text NOT NULL,
  `views` int(11) NOT NULL,
  `published` int(1) NOT NULL,
  `publish_date` datetime DEFAULT NULL,
  `category_id` int(11) NOT NULL,
  `created` datetime DEFAULT NULL,
  `modified` datetime DEFAULT NULL,
  PRIMARY KEY (`id`),
  UNIQUE KEY `url` (`slug`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1;

RSS Feed

To set up an RSS Feed of your posts, create a file at app/View/Posts/rss/index.ctp:

<?php

	$this->set('channelData', array(
		'title' => __("Most Recent Posts"),
		'link' => $this->Html->url('/', true),
		'description' => __("Most recent posts."),
		'language' => 'en-us'
	));

	foreach ($posts as $post) {
		$postTime = strtotime($post['Post']['created']);

		$postLink = array(
			'controller' => 'posts',
			'action' => 'view',
			$post['Post']['slug']
		);

		// Remove & escape any HTML to make sure the feed content will validate.
		$bodyText = h(strip_tags($post['Post']['body']));
		$bodyText = $this->Text->truncate($bodyText, 400, array(
			'ending' => '...',
			'exact'  => true,
			'html'   => true,
		));

		echo $this->Rss->item(array(), array(
			'title' => $post['Post']['title'],
			'link' => $postLink,
			'guid' => array('url' => $postLink, 'isPermaLink' => 'true'),
			'description' => $bodyText,
			'pubDate' => $post['Post']['created']
		));
	}

?>

Then add a line to app/Config/routes.php:

Router::parseExtensions('rss');

The RSS feed will then be available at /posts/index.rss.

Please Sign In

Please sign in to post a comment.

Web Development

View details »

Web Hosting

View details »

Our Portfolio

View portfolio »

WebSight Designs webSIGHTdesigns preferred email webSIGHTdesigns United States United States