Placed in: Home arrow Programming arrow Building a blog with CakePHP - Part 2: SEO and Management

Cialis Online

Building a blog with CakePHP - Part 2: SEO and Management

A while ago, I placed an article called building a blog with CakePHP - Part 1: Getting started. The tutorial gave you a good start in the world of CakePHP, just to learn the basics of the framework.

Now we're improving the blog by adding some functionality. We'll make it a little bit more search engine friendly and we're going to build an admin panel to add new articles.

Building a blog with CakePHP - Part 2

What we did last time

  1. Creating the database
  2. Clearing CakePHP errors
  3. Creating the "Blog" model
  4. Data from controller to view
  5. Altering the layout & styling with CSS

Make sure you've read the previous article before starting with this one if you want to learn the framework. You can also try viewing the source code of part 2 if you want to show your chest hair.

Download the source code for this tutorial

There we go! Strap on your cooks hat; We're going to bake some delicious Blog-cake.

Updates on Part 1

Cake placed the following comment:

findAll() is deprecated, use find('all') and find('first')

Which is true, so let's open blog_controller.php and change the findAll() to find('all').

Teknoid placed a longer comment, but I'm going to implement the following:

You really don't need to specify $primaryKey if you follow the convention (which it seems that you do: 'id').

Another great comment that is true. CakePHP automatically recognizes the $primaryKey when the key is 'id'. You'll only need to add the $primaryKey variable when the primary key is not 'id'. Personally, I still like to add it just to have a good overview.

Basic SEO

Let's add some basic SEO functionality to our blog. We'll be adding keywords and description for the individual pages and make the URL's more search engine friendly.

Let's start by changing the database. Open up your phpMyAdmin and execute the following SQL:

ALTER TABLE `blogs` ADD `meta_keywords` TEXT NOT NULL ,
ADD `meta_description` TEXT NOT NULL ;

We now have added two extra fields for our blog inputs to add keywords and description. Let's add it to our previous articles:

UPDATE `blogs` SET `meta_keywords` = 'marcofolio, joomla, cakephp',
`meta_description` = 'First blog post on a custom build CakePHP blog.'
  WHERE `blogs`.`id` = 1;
UPDATE `blogs` SET `meta_keywords` = 'read more, object oriented blog',
`meta_description` = 'Second blog post description'
  WHERE `blogs`.`id` = 2;
UPDATE `blogs` SET `meta_keywords` = 'last, marcofolio, blog',
`meta_description` = 'My last description for the CakePHP blog.'
  WHERE `blogs`.`id` = 3;

Now for the PHP coding part. Since title and description are part of the header which is rendered in "default.ctp", let's open that file (/app/views/layouts/) and add the following code between <head> and </head>. Make sure you first delete the <title> tags before adding the new one.

<title><?= $pagetitle ?></title>
<meta name="keywords" content="<?= $pagekeywords ?>" />
<meta name="description" content="<?= $pagedescription ?>" />

When you now view your blog (http://yourdomain.com/blog/) and view the source, the title, keywords should be empty since we didn't add it (yet). To add it, open up the blog_controller.php found in /app/controllers/ .

Let's change the code which we had last time to make it a bit easier. Change:

$this->set('article', $this->Blog->find("id = $view"));

into:

$article = $this->Blog->find("id = $view");
$this->set('article', $article);

The reason why this is useful, is because we can now use the $article variable to retrieve the metadata from. Add the following directly after the previous code in the controller:

// Retrieve and set the metadata
$this->set('pagetitle', $article['Blog']['title']);
$this->set('pagedescription', $article['Blog']['meta_description']);
$this->set('pagekeywords', $article['Blog']['meta_keywords']);

When you now view the source of an individual blog article (http://yourdomain.com/blog/index/1), you'll see the title, description and keywords have been set.

But what about the main page? For that page, we're going to do it the Joomla! way: The page will contain all keywords and the descriptions all together and the title is a fixed value. This is what we had first:

$this->set('articles', $this->Blog->find('all'));

Change it to:

$articles = $this->Blog->find('all');
$this->set('articles', $articles);
 
// Retrieve and combine keywords / description
$keywords = '';
$description = '';
foreach ($articles as $article)
{
  $keywords = $article['Blog']['meta_keywords'] . ', ' . $keywords;
  $description = $article['Blog']['meta_description'] . ', ' . $description;
}
$this->set('pagekeywords', $keywords);
$this->set('pagedescription', $description);
// Set fixed page title
$this->set('pagetitle', 'Marcofolio.net building a CakePHP blog');

I know this probably isn't the best way the keywords and description could be added, but it's the same was as Joomla! works. Right now, your blog would be fully loaded with title, description and keywords.

For the last part to make it SEO, we're going to make a "Search Engine Trap" by making the URL's Search Engine Friendly. Right now, the URL's look like this:

blog/index/1

No actual words are used in the page URL. Let's fix this by editing the index.ctp from the blog view, found in /app/views/blog/.

Currently, the pages are linked to their ID:

<?= $article['Blog']['id'] ?>

We're going to add the article title after that, just as an empty parameter. Everywhere you see the ID linked (Which is at the <h1> for the page title and the "read more.." link), add the following code directly behind it:

/<?= str_replace(' ', '_', $article['Blog']['title']) ?>

str_replace will replace any "spaces" you have in the page title to an underscore. Now, your URL's will look like this:

blog/index/1/My_first_blog_post

That just looks a lot better, doesn't it? Although the last part is actually useless (you can change it to whatever you want), it still helps (a bit) for search engine optimization.

Routing

Currently, the URL still is not fully human readable and doesn't make sense. Within Cake, you can set up the routing URL's will have. To do this, open routes.php found in /app/config/ . Add the following lines to the file:

// The mainpage (http://yourdomain.com/) will now direct to the blog
Router::connect('/', array('controller' => 'blog', 'action' => 'index'));
// All parameters after /blog/ will be given to the blog controller
Router::connect('/blog/*', array('controller' => 'blog', 'action' => 'index'));

When you now visit the root of your site (http://yourdomain.com/), you should be able to see the blog. When you click on one of the URL's, linking your articles, it'll not work. Let's take a look at the URL:

blog/index/1/My_first_blog_post

With the routes, we've set that everything after the /blog/ will be given as a parameter to the blog_controller. The controller needs the ID as the first parameter, but at this moment, index is the first. To remove it, open up the blog view (/app/views/blog/index.ctp) and remove /index/.

Now, your blog is fully functional again with pretty URL's:

blog/1/My_first_blog_post

Admin panel

Currently, we can only edit the pages by playing around in phpMyAdmin. This isn't something that you want; You want to edit the pages directly on the website. We're going to create an admin panel to achieve this and manage your content.

First, we'll need to create the admin controller. Create a file called admin_controller.php in your /app/controllers/ folder with the following content:

<?php
class AdminController extends AppController {
 
  var $name = 'Admin';
  var $uses = array('Blog');
  
  function index()
  {
    $this->set('articles', $this->Blog->find("all"));
  }
  
  function add()
  {
    if (!empty($this->data))
    {
      $this->Blog->save($this->data);
      $this->redirect('/admin/');
    }
  }
  
  function edit($pageid)
  {
    // If data is submitted, save it
    if (!empty($this->data))
    {
      $this->Blog->save($this->data);
      $this->redirect('/admin/');
    }
    // If no data is submitted, retrieve the old one
    else
    {
      $this->set('data', $this->Blog->find("id = $pageid"));
    }
  }
  
  function delete($pageid)
  {
    $this->Blog->del($pageid);
    $this->redirect('/admin/');
  }
}
?>

And don't forget the views for each page (index, add and edit: delete doesn't need one). Create the following files in /app/views/admin/:

index.ctp

<h1>Admin Panel</h1>
<table>
  <tr>
      <td><h2>ID</h2></td>
        <td><h2>Title</h2></td>
        <td><h2>Delete</h2></td>
    </tr>
<?php foreach ($articles as $article) { ?>
  <tr>
        <td><?= $article['Blog']['id'] ?></td>
        <td><a href="edit/<?= $article['Blog']['id'] ?>">
        <?= $article['Blog']['title'] ?></a></td>
        <td><a href="delete/<?= $article['Blog']['id'] ?>">X</a></td>
    </tr>
<?php } ?>
</table>
<a href="add">Add new article</a>

add.ctp

<h1>Add Article</h1>
<form id="AdminAddForm" method="post" action="/admin/add">
<table>
  <tr>
      <td>Date</td>
        <td><input name="data[Blog][date]" type="text" /></td>
  <tr>
    <tr>
      <td>Title</td>
        <td><input name="data[Blog][title]" type="text" /></td>
  <tr>
    <tr>
      <td>Introtext</td>
        <td><textarea name="data[Blog][introtext]"
            cols="30" rows="3"></textarea></td>
  <tr>
    <tr>
      <td>Maintext</td>
        <td><textarea name="data[Blog][maintext]"
            cols="30" rows="3"></textarea></td>
  <tr>
    <tr>
      <td>Meta Keywords</td>
        <td><textarea name="data[Blog][meta_keywords]"
            cols="30" rows="3"></textarea></td>
  <tr>
    <tr>
      <td>Meta Description</td>
        <td><textarea name="data[Blog][meta_description]"
            cols="30" rows="3"></textarea></td>
  <tr>
</table>
<?php
echo $form->end('Add Article');
?>

edit.ctp

<h1>Edit Article</h1>
<form id="AdminEditForm" method="post" action="/admin/edit">
<table>
  <tr>
      <td>Date</td>
        <td><input name="data[Blog][date]" type="text"
            value="<?= $data['Blog']['date'] ?>" /></td>
  <tr>
    <tr>
      <td>Title</td>
        <td><input name="data[Blog][title]" type="text"
            value="<?= $data['Blog']['title'] ?>"/></td>
  <tr>
    <tr>
      <td>Introtext</td>
        <td><textarea name="data[Blog][introtext]" cols="30"
            rows="3"><?= $data['Blog']['introtext'] ?></textarea></td>
  <tr>
    <tr>
      <td>Maintext</td>
        <td><textarea name="data[Blog][maintext]" cols="30"
            rows="3"><?= $data['Blog']['maintext'] ?></textarea></td>
  <tr>
    <tr>
      <td>Meta Keywords</td>
        <td><textarea name="data[Blog][meta_keywords]" cols="30"
            rows="3"><?= $data['Blog']['meta_keywords'] ?></textarea></td>
  <tr>
    <tr>
      <td>Meta Description</td>
        <td><textarea name="data[Blog][meta_description]" cols="30"
            rows="3"><?= $data['Blog']['meta_description'] ?></textarea></td>
  <tr>
</table>
<input type="hidden" name="data[Blog][id]" value="<?= $data['Blog']['id'] ?>" />
<?php
echo $form->end('Save Article');
?>

Note that this is not the correct way of creating forms in CakePHP. I like to do it this way because you'll have more control over the content of the forms than the one that Cake automatically generates for you. If you want to learn how it should look like, take a look at the CakePHP Blog tutorial - Adding posts and Editing posts. What I'm doing above is actually writing everything myself what CakePHP could generate for you.

Conclusion / Download

Our blog is now technically improved compared to the previous one. Making the blog SEO will really help getting your site higher ranked in certain search engines like Google.

Also the admin panel (Access it by going to http://yourdomain.com/admin/) is more userfriendly than editing and adding articles in phpMyAdmin. Oh and sorry for making several tables: For now it was the easiest thing to do.

Download the source code for this tutorial

I hoped you learned something today, just by getting better and better at programming with the super CakePHP framework. Next time, we'll get into data validation, user authentication and more. Stay tuned or subsribe to the feed. Feel free to give feedback about this tutorial.


Tags:  cakephp framework seo blog webdevelopment programming php

Interested in this topic? You might enjoy another article I've written called

Did you like this article? Subscribe to my feed or email to keep updated on new articles.

Spread the word and submit to:
Digg!Reddit!Del.icio.us!Facebook!StumbleUpon!
Comments
Add NewSearchRSS
Alireza - Thank you   2008-12-06 19:19:23
Gravatar image hi
Thank you.
I started using cakePHP.
your tutorial was cool.
dan - Great!   2009-01-10 19:30:12
Gravatar image This is by far the best and most complete tutorial about how to start with CakePHP. I'll keep an eye on your site!
Thanks! :woohoo:
~ See ya!
mambenanje - great   2009-02-05 17:27:25
Gravatar image nice article but i have a little problem because the codes break for the admin_controller views
in the index.ctp the add new button is

Add new article

instead of this

Add new article

and the add form also doesnt work though the action="admin/add"
I dont know why but I am coming to cake from codeigniter and I want to learn more about stuff, this tutorial is nice but I dont know why I still prefer codeigniter
regards
mambenanje   2009-02-05 17:32:15
Gravatar image nice article but i have a little problem because the codes break for the admin_controller views
in the index.ctp the add new button is

Quote:
Add new article


instead of this

Quote:
Add new article


and the add form also doesnt work though the action="admin/add"
I dont know why but I am coming to cake from codeigniter and I want to learn more about stuff, this tutorial is nice but I dont know why I still prefer codeigniter
regards
rizki - thanks   2009-03-12 14:05:39
Gravatar image thanks..
Tyler - Look into inflector   2009-03-27 17:12:00
Gravatar image You might want to look into 'inflector' to build your slugs instead of the str_replace approach that can leave some unescaped characters in your urls:

Inflector::slug($string)

The inflector page in the manual:
http://book.cakephp.org/pl/view/572/Class-methods
Sham Sehgal - Admin Panel is not proper   2009-10-21 11:57:52
Gravatar image Hi, your article is really good and informative, but its not proper or complete we can say. See an admin panel must have some kind of security. You didn't mentioned any Authentication process to authenticate the users as per their roles. No doubt your article is good but its incomplete. It will be more good if you refine your article by adding Authentication process to it which will be helpful to develop real and secure admin panel for a blog application.

Thanks
Sham Sehgal
dakota   2009-12-08 15:11:39
Gravatar image Wow. Talk about bad code.

The idea is wonderful, but your implementation isn't

Firstly
dogmatic69   2009-12-08 15:16:34
Gravatar image this is some of the worst cakephp code i have seen. if you want to know how to really use cake and create a simple blog visit http://book.cakephp.org/view/219/Blog. that is the official docs.

admin should be done with prefixes and shold use the same controller as the user like this:

Code:
Configure::write('Routing.admin', 'admin');
in configure.php

Code:
class BlogsController extends AppController
{
var $name = 'Blogs';

function index() { ... }

function admin_index() { ... }
}


for security check out http://book.cakephp.org/view/641/Simple-Acl-controlled-Application
emlak ilanlar   2010-03-22 11:32:13
Gravatar image Hi, your article is really good and informative, but its not proper or complete we can say. See an admin panel must have some kind of security. You didn't mentioned any Authentication process to authenticate the users as per their roles. No doubt your article is good but its incomplete. It will be more good if you refine your article by adding Authentication process to it which will be helpful to develop real and secure admin panel for a blog application.

Thanks
Cheap Playstation 3 Slim   2010-05-13 09:29:32
Gravatar image This just made my day much brighter. Thanks a lot. Something else I across was this http://playstation3slim.com/ Take a look!nice codes...........
Kazim - Turkey Property   2010-08-06 10:04:14
Gravatar image I started using cakePHP. your tutorial was good
meier   2010-11-22 10:29:52
Gravatar image Hi,

nice tut, but: the file add_controller.php is missing... can you complete your part 2 and the downloadfiles?

can you tell me where i can modify the tablename "blogs"?

thanks a lot
Nazim - test !!!!!!!   2011-04-07 09:03:41
Gravatar image test !!!!!!!
Read more...
Name:
Email:
  Gravatar enabled.
Website:
Title:
UBBCode:
[b] [i] [u] [url] [quote] [code] [img] 
 
 
:angry::0:confused::cheer:B):evil::silly::dry::lol::kiss::D:pinch:
:(:shock::X:side::):P:unsure::woohoo::huh::whistle:;):s
:!::?::idea::arrow:
 
Security Image
Please input the anti-spam code that you can read in the image.
Unsubscribe from e-mail notifications.
 
< Prev   Next >
Subscribe

7440 readers subscribed here. Subscribe today!