Placed in: Home arrow Programming arrow Building a blog with CakePHP - Part 2: SEO and Management comprar viagra en espaƱa
comprar viagra online
comprar viagra generico barato
comprar cialis generico online
comprar cialis online seguro
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!
 
< Prev   Next >
Subscribe

Subscribe to Marcofolio