Programming and general geekiness.

Archive for December, 2011

Building a simple blogging system in PHP – Part 2

In yesterday’s section of the tutorial we considered the basic layout, CSS and database structure. Today we are going to build the initial code that will fetch posts and other information. The previous tutorial ended looking like this:

Clearly there wasn’t any information so we need to begin adding things. The first thing we should do before doing anything else is to add some sample data to the database so that we can begin creating code that works. I added the following:

  • A blog post with the title ‘My first blog post!’ and the link My_first_blog_post along with some basic content
  • I added the category ‘life’ to the category table by adding a row with Id 1, Category life and Post 1 (links with the post table)
  • I added some tags the same way I added categories

The next simple bit of code to be run is to fetch a category list to display on the sidebar. I wrote the following code in code.php:

$pdo = new PDO("mysql:host=localhost;dbname=myblog", "root", "");
$pageTitle = "My Blog";
$pageContent = "";
$categoryList = "<ul class=\"category-list\">";
foreach ($pdo->query("SELECT DISTINCT Category FROM categories ORDER BY Category ASC")->fetchAll() as $cat)
{
 $categoryList .= "<li><a href=\"http://localhost/myblog/category/" . $cat[0] . "\">" . $cat[0] . "</a></li>";
}
$categoryList .= "</ul>";

Here’s a quick walkthrough of the code:

  • First we create a new PHP Data Object which is connected to the database we created. If you haven’t used PDO before it maybe worth looking it up in the PHP Manual
  • We then set default values for the variables and start an HTML list element in the $categoryList variable
  • We then loop through all the unique values in alphabetical order in the categories table and add them as a list item and link
  • We finish the list off

The end result of my sidebar is the following (I added some additional styling and layout stuff):

In the database I had all the category names as lowercase however CSS can style these as an uppercase letter at the beginning of each word. Now we need to look back at how the URLs work.

We have already established that the server will direct everything that doesn’t exist already into index.php to give us clean URLs. We therefore need to write some code that will interpret the requested URL. We also need to consider that we are including an RSS feed feature which will mean that people can subscribe to the site. I have therefore including the code that will generate the feed:

$url = explode("/", substr($_SERVER['REQUEST_URI'], strpos($_SERVER['REQUEST_URI'], "myblog/")+7));
if ($url[0] == "feed" || $url[0] == "rss")
{
 header("Content-type:application/rss+xml; charset=ISO-8859-1");
 echo "<?xml version=\"1.0\"?>\n";
 echo "<rss version=\"2.0\">\n";
 echo "<channel>\n";
 echo "<title>My Blog</title>\n";
 echo "<link>http://localhost/myblog/</link>\n";
 echo "<description>The source of information about my life!</description>\n";
 echo "<language>en-us</language>\n";
 foreach ($pdo->query("SELECT * FROM posts ORDER BY Posted DESC LIMIT 0, 20")->fetchAll() as $row)
 {
 echo "<item>\n";
 echo "<title>" . $row['Title'] . "</title>\n";
 echo "<link>http://localhost/myblog/post/" . $row['Link'] . "</link>\n";
 echo "<description><![CDATA[" . $row['Content'] . "]]></description>\n";
 echo "<pubDate>" . date('D, d M Y H:i:s O', strtotime($row['Posted'])) . "</pubDate>\n";
 echo "</item>\n";
 }
 echo "</channel>\n</rss>";
 exit;
}
else
{
}

I won’t explain what all the code that generates individual items of XML does, but here is roughly what happens:

  • We get everything in the URL after the myblog/ part and split it where there is a forward slash character
  • We check if the first part of the URL is feed or rss and if it is send an XML header
  • Echo the initial required data about the feed
  • Loop through the twenty most recent items and print the required details – note that the date has to be first passed into a PHP date and then into a valid RSS date
  • If the feed wasn’t requested, continue running code.

The next stage of code is rather massive but gives us the core stuff for the blog and goes inside that last else statement. I won’t chunk it out into sections so here is the block:

if (isset($_GET['p'])) $page = ((int)$_GET['p'])-1;
 else $page = 0;
 if ($page < 0) $page = 0;
 if ($url[0] == "post")
 {
 if (isset($url[1]))
 {
 $post = $pdo->prepare("SELECT * FROM posts WHERE Link = :link");
 $post->execute(array(":link" => $url[1]));
 }
 else header("location:http://localhost/myblog/");
 }
 else if ($url[0] == "category")
 {
 if (isset($url[1]))
 {
 $post = $pdo->prepare("SELECT * FROM posts WHERE Id = ANY (SELECT Post FROM categories WHERE Category = :cat) ORDER BY Posted DESC LIMIT " . $page*10 . ", 10");
 $post->execute(array(":cat" => $url[1]));
 }
 else header("location:http://localhost/myblog/");
 }
 else if ($url[0] == "tag")
 {
 if (isset($url[1]))
 {
 $post = $pdo->prepare("SELECT * FROM posts WHERE Id = ANY (SELECT Post FROM tags WHERE Tag = :tag) ORDER BY Posted DESC LIMIT " . $page*10 . ", 10");
 $post->execute(array(":tag" => $url[1]));
 }
 else header("location:http://localhost/myblog/");
 }
 else $post = $pdo->query("SELECT * FROM posts ORDER BY Posted DESC LIMIT " . $page*10 . ", 10");
 if ($post->rowCount() > 0)
 {
 foreach ($post->fetchAll() as $row)
 {
 if ($url[0] == "post") $pageTitle = $row['Title'];
 $pageContent .= "<article>";
 $pageContent .= "<header><h2><a href=\"http://localhost/myblog/post/" . $row['Link'] . "\">" . $row['Title'] . "</a></h2><p>" . date('j F Y', strtotime($row['Posted'])) . "</p></header>\n";
 $pageContent .= $row['Content'];
 $cats = $pdo->prepare("SELECT Category FROM categories WHERE Post = :post");
 $cats->execute(array(":post" => $row['Id']));
 if ($cats->rowCount() > 0)
 {
 $pageContent .= "\n<p>Posted in: ";
 foreach ($cats->fetchAll() as $cat)
 {
 $pageContent .= "<a href=\"http://localhost/myblog/category/" . $cat[0] . "\" class=\"category-link\">" . $cat[0] . "</a> ";
 }
 $pageContent .= "</p>";
 }
 $tags = $pdo->prepare("SELECT Tag FROM tags WHERE Post = :post");
 $tags->execute(array(":post" => $row['Id']));
 if ($tags->rowCount() > 0)
 {
 $pageContent .= "\n<p>Tagged with: ";
 foreach ($tags->fetchAll() as $tag)
 {
 $pageContent .= "<a href=\"http://localhost/myblog/tag/" . $tag[0] . "\" class=\"category-link\">" . $tag[0] . "</a> ";
 }
 $pageContent .= "</p>";
 }
 $pageContent .= "</article>";
 }
 }
  • The first thing that happens is checking if the p variable is set – this tells the user what page they are on
  • If we are looking at an individual post, prepare a query for that post
  • If we are looking at a category, prepare a query for that category
  • If we are looking at a tag, prepare a query for that tag
  • Loop through all the posts and produce the appropriate HTML for them

In reality it is actually relatively simple, it just takes quite a bit of code to work correctly. Here is what the finished result looks like, although you may want to add extra styling:

In the next tutorial we’ll add commenting and a basic admin panel.

Advertisements

Building a simple blogging system in PHP – Part 1

Today there are many blogging systems available to create a blog such as WordPress, Blogger and Tumblr however it can be more rewarding to build your own blogging system that you can use directly in your website. This set of tutorials will go through the procedure of building a blogging system with tags, categories and RSS using PHP and MySQL because they are both easily accessible environments. If you do not have either of these available on your system I recommend that you download WampServer and go through some PHP tutorials because that is what I will be using along with NetBeans 7.1 RC2 for coding.

Initial considerations

A blogging system has a few basic requirements. Here is what I think they are:

  • Simplistic two column layout – the left is for posts and the right is for a sidebar including category links, recent posts, RSS and search
  • Ability to fetch many posts or individual posts
  • Ability to tag a post with as many tags as required and as many categories as required
  • RSS feed automatically generated
  • Commenting on posts
  • Admin panel for editing
  • Well structured database for storing data

Clearly a blogging system is quite a large project and it is important to carefully consider how you will build it. In part 1 of this tutorial I shall develop the appropriate tables in a database, setup the server and basic layout of the pages.

Making the database

For simplicity I created a database called myblog in PHPMyAdmin on WampServer. I created the following tables:

  • posts
    • Id INTEGER PRIMARY_KEY AUTO_INCREMENT
    • Title TEXT
    • Link TEXT
    • Content TEXT
    • Posted DATETIME
  • categories
    • Id INTEGER PRIMARY_KEY AUTO_INCREMENT
    • Category TEXT
    • Post INTEGER
  • tags
    • Id INTEGER PRIMARY_KEY AUTO_INCREMENT
    • Tag TEXT
    • Post INTEGER

Incredibly this is all that we need in our database because we will be taking advantage of other web services to manage things like commenting. The next stage involves configuring Apache.

Configuring Apache

Apache is the web server of the web because its free and it does the job. Before we move on it is worth considering how we wish URLs on the blog to appear. One option is to have something like blog/post.php?id=3 to direct to the third blog post in the database however this is a cumbersome old school approach that is not used on many websites. Instead we will have something like blog/post/My_blog_post. Before we do this we first need to do a few things. The first is to ensure that the rewrite_module is enabled in Apache. In WampServer this can be done by clicking the WampServer icon in the taskbar, clicking Apache, clicking Apache Modules and then ensuring there is a tick against the rewrite_module. You then need to navigate to where you intend to put your blog (I’ve created a folder called myblog in C:\wamp\www) and create a new file called .htaccess and put in the following:

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^(.+) - [PT,L]
RewriteRule ^(.*) index.php

These five lines of code basically (I won’t go into detail) cause everything that doesn’t exist on the server (such as image files) in the directory to go through index.php which is where our basic code will be stored.

Creating index.php

For simplicity purposes this is where we are directing the server to for requesting posts. I’ve created the following in the file:

<?php include("code.php"); ?>
<!DOCTYPE html>
<html>
 <head>
 <link rel="stylesheet" type="text/css" href="http://localhost/myblog/css.css" />
 <title><?php echo $pageTitle ?></title>
 </head>
 <body>
 <div id="page">
 <div id="header">
 <h1>My blog</h1>
 <h3>The source of information about my life</h3>
 <div id="header-image">&nbsp;</div> 
 </div>
 <div id="page-content">
 <div id="left">
 <?php echo $pageContent ?>
 </div>
 <div id="right">
 <a href="http://localhost/myblog/rss" id="feed-link">Feed</a>
 <?php echo $categoryList ?>
 </div>
 </div>
 <div id="footer">My blog was created by Programming Thomas</div>
 </div>
 </body>
</html>

There is very little to observed from this other than it defines our basic layout. It is worth noting that the links have to be full lengths because they will not have the same relativity in localhost/myblog/post/My_post_name and localhost/myblog. I also created code.php and gave the variables some default variables so that I could view the page without errors. Here is what it looked like after styling:

I decided to use Google Web Fonts to get the Open Sans font which I thought looked quite nice. The image is from Flickr however I’ve cropped it. Here is the full CSS (I’ve tried to make it as small as possible):

@import url(http://fonts.googleapis.com/css?family=Open+Sans);
body
{
 font-family:"Open Sans", sans-serif;
}
#page
{
 width:750px;
 padding:5px;
 margin:10px auto;
}
#header h1, #header h3
{
 margin:0;
 font-weight:normal;
}
#header-image
{
 background:url(http://farm8.staticflickr.com/7159/6576537579_fcc8f6efd8_b_d.jpg) center center;
 height:175px;
 margin:5px 0;
}
#left
{
 width:490px;
 padding:5px;
 float:left;
}
#right
{
 width:240px;
 padding:5px;
 float:right;
}
#footer
{
 clear:both;
 text-align:center;
}
#feed-link
{
 background:url("http://localhost/myblog/feed-icon-28x28.png") no-repeat;
 padding:0 0 0 33px;
 color:black;
 text-decoration:none;
 width:100%;
 font-size:21px;
}

I think that is all that we will do today, check back tomorrow for Part 2 of the tutorial.

Shortest route algorithm

A common (ish) problem in computing is identifying the lightest/quickest/shortest route across a graph or map. From the above graph we can clearly see that the fast route from A to G is ADG or ABDG however for some people it may be unclear how to identify this in an algorithm. Thankfully I spent all of yesterday evening writing up the following Python algorithm. It is relatively efficient however there are a few bugs that I am working on resolving. I’ve tried to do it in as few lines as possible:

nodeNames = []
nodeWeights = {}
nodeConnect = {}
cons = open(raw_input("Please enter a file name of the graph: ")).read().splitlines()
for c in cons:
cS = c.split(" ")
if cS[0] not in nodeNames:
nodeNames.append(cS[0])
nodeConnect[cS[0]] = []
if cS[1] not in nodeNames:
nodeNames.append(cS[1])
nodeConnect[cS[1]] = []
if cS[0] != cS[1]:
nodeConnect[cS[0]].append(cS[1])
nodeConnect[cS[1]].append(cS[0])
nodeWeights[cS[0] + ">" + cS[1]] = int(cS[2])
nodeWeights[cS[1] + ">" + cs[0]] = int(cS[2])
print "Graph loaded."
nodeStart, nodeEnd  = raw_input("Please enter location and destination: ").split(" ")
nodeSolved = {}
nodeSolvedRoute = {}
maxRoute = 1000000
for i in nodeNames:
nodeSolved[i] = maxRoute
nodeSolvedRoute[i] = ""
nodeSolved[nodeStart] = 0
nodeSolvedRoute[nodeStart] = nodeStart + ", "
options = []
examined = []
def evaluateLightest(current):
for connected in nodeConnect[current]:
if nodeSolvedRoute[current] + connected not in examined:
pathWeight = nodeSolved[current] + nodeWeights[current + ">" + connected]
examined.append(nodeSolvedRoute[current] + connected)
if pathWeight < nodeSolved[connected]:
nodeSolved[connected] = pathWeight
nodeSolvedRoute[connected] = nodeSolvedRoute[current] + connected + ", "
evaluateLightest(current)
evaluateLightest(nodeStart)
print nodeSolved[nodeEnd]
print nodeSolvedRoute[nodeEnd]

I think that it probably is possible to improve the algorithm and if I do I’ll update the source. The graph file should be as follows (for the above graph):

A B 2
A C 2
B D 1
B F 4
C D 2
C E 1
D F 1
D G 3
F G 3

For this example the program correctly outputs 6 and ABDG. I will make available a file I am working on with all of the London Tube Stations (and journey times).

Get Java Swing to use the Operating System style

Java Swing is an incredibly easy way of designing a user interface however there’s a major problem with it: the default style is disgusting. The default style that shows up is really horrible because it is designed to be a mix of the designs of Windows, Mac and Linux so that a button is recognizable as a button but not as nice as the default style. Thankfully there is a really easy way to change an app from looking like the one on the right to the default OS style on the left. It is worth noting (as demonstrated by the position of the Next button) that this doesn’t always work brilliantly but that it does look better.

All you have to do is make sure you have imported javax.swing.UIManager and then add the following code before you create the interface:

try 
{
      UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName());
} 
catch (Exception e) { }

This will fetch the OS’ default style allowing you to easily use it in your application. On Mac this application’s menu should display at the top rather than in the window itself, thus allowing your application to look nice on all platforms.