Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

Blog Design Solutions (2006)

.pdf
Скачиваний:
39
Добавлен:
17.08.2013
Размер:
38.67 Mб
Скачать

B L O G D E S I G N S O L U T I O N S

What you have just done is added a Fulltext index to the posts table on the title, summary, and post fields. Now when the database text is searched (I’ll show you how in the next section), it will search all three fields, giving priority to the title, then the summary, then the post. So if you search for the word “donkey”, and one of your posts is titled “Donkey Rides” while another of your posts just has the word “donkey” somewhere in the post, “Donkey Rides” will be returned first in the search results because title is deemed to be more important than the post.

And now to create the search results page, which will show the matching blog posts when someone uses the search form on any of your pages. The search results will look something like Figure 7-22.

Figure 7-22. Search results page

Here is the search results code in its entirety. Copy it into a new document and save it to your root directory as search.php.

<?php

// Open connection to database include("db_connect.php");

$q = (isset($_REQUEST["q"]))?$_REQUEST["q"]:""; $q = trim(strip_tags($q));

if ($q != "") {

// Select posts grouped by month and year

$sql = "SELECT post_id, title, summary, DATE_FORMAT(postdate, '%e %b %Y at %H:%i')

AS dateattime FROM posts WHERE

MATCH (title,summary,post) AGAINST ('$q') LIMIT 50"; $result = mysql_query($sql);

$myposts = mysql_fetch_array($result);

}

326

W R I T E Y O U R O W N B L O G E N G I N E

// format search for HTML display $q = stripslashes(htmlentities($q));

include("functions.php");

?>

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en"> <head>

<meta http-equiv="content-type" content="text/html; charset=iso-8859-1" />

<title>Search | Samuel's Blog</title> <style type="text/css">

@import url(blog.css); </style>

</head>

<body>

<?php include("header.php"); ?>

<!--

this is the main part of the page -->

7

<div

id="maincontent">

 

<div id="posts"> <h2>Search Results</h2> <div id="results"> <?php

if($myposts) {

$numresults = mysql_num_rows($result); $plural1 = ($numresults==1) ? "is" : "are"; $plural2 = ($numresults==1) ? "" : "s";

echo "<p>There $plural1 <em>$numresults</em> post$plural2 matching your search for <cite>$q</cite>.</p>";

echo "<dl>\n"; do {

$post_id = $myposts["post_id"]; $title = $myposts["title"]; $summary = $myposts["summary"];

echo "<dt><a href='post.php?post_id=$post_id'>$title</a></dt>\n"; echo "<dd>$summary</dd>\n";

} while ($myposts = mysql_fetch_array($result)); echo "</dl>";

}else {

echo "<p>There were no posts matching your search for

<cite>$q</cite>.</p>";

}

?>

</div>

</div>

327

B L O G D E S I G N S O L U T I O N S

<div id="sidebar">

<?php include("searchform.php"); ?> </div>

<!-- sidebar ends -->

</div>

<!-- maincontent ends --> <?php include("footer.php"); ?> </body>

</html>

The code should be somewhat familiar by now, with a database query first, followed by a do-while loop in the body of your page. However the SELECT statement in the database query warrants further investigation:

SELECT post_id, title, summary, DATE_FORMAT(postdate, '%e %b %Y at %H:%i')

AS dateattime FROM posts WHERE

MATCH (title,summary,post) AGAINST ('$q') LIMIT 50

MySQL text searching is performed by combing the MATCH and AGAINST functions. The arguments passed to the MATCH function should be a comma-separated list of the columns you used to create the fulltext index, and the argument to the AGAINST function should be the search term. MySQL automatically returns the results in order of relevance.

Because you have only a few posts in your database, the fulltext searching can produce some unexpected results, particularly if you search for a word you know to be repeated in all your posts. In this instance, MySQL will deem the word as “common,” and you might receive no results for the search. However, as you write more and more, the search results become increasingly accurate.

Indexing your blog database

MySQL fulltext searching is extremely quick because it uses an index. If you were trying to find a topic in a reference book, you would most likely look at the index first, rather than leafing through the book page by page. In essence, this is how database indexes work, too.

Every time you have a WHERE clause in a SELECT query you should ensure that you have an index on each field mentioned in the clause, which can increase speed by an order of magnitude or more (especially for tables with large amounts of data).

When you created the posts table, you set the Primary Key option. When this was done, an index was automatically created for the post_id field. However, some queries are being performed on fields that are not indexed: archive.php also queries the postdate field, and post.php queries the post_id field in the comments table.

To add indexes to these fields, open up phpMyAdmin in your browser, select the blog database, and click the posts link in the left frame. In the Indexes box, type 1 in the Create an index on n columns box and click Go. Now name the index as idx_postdate, select Index as the Index type (it is probably already selected) and select postdate as the Fields, then press Save (see Figure 7-23).

328

W R I T E Y O U R O W N B L O G E N G I N E

Figure 7-23. Adding an index to the postdate field in phpMyAdmin

Now do the same for the post_id field in the comments table, and your blog database will be fully optimized.

Creating an RSS feed

The final thing every blog should have is an RSS feed, which is a web content syndication format. (RSS stands for Really Simple Syndication.) An RSS feed is an XML file that tells the

outside world when you have updated your blog so your readers don’t have to keep com- 7 ing back to your website to find out whether you made any changes. RSS feeds can be

read online, through websites such as Bloglines (www.bloglines.com), or by using news reader software. There are many different news readers available for all operating systems.

Your RSS feed might well end up being the most frequently downloaded

 

file on your website. Many robots, indexers, and software will come and

 

grab it so they can keep their users up to date with when your blog has

 

been updated. Assuming that you want your blog to be read (and who

 

doesn’t), this is a good thing. However, it also means that your database

 

server could end up fairly stressed if a database query were required

 

every time the RSS file is requested. For this reason, I will show you how

 

to create a static file that is updated only when you make a change to

 

your blog. Because, by definition, static files do not require a database

 

connection, your site will be more easily able to handle lots of nosy RSS

 

software.

 

Traditionally, the main RSS feed for a site is named index.xml. The first

 

step is to create an empty index.xml file—just create a new document

 

in your text editor and save it to your root directory as index.xml.

 

Because your code will eventually be rewriting this document, it needs

 

to have read-write privileges. On Windows machines that should already

 

be the case, but on Mac OS X machines you need to change the file

 

properties. To do so, locate your index.xml file in Finder and select File

 

Get Info. Open the Details area of Ownership & Permissions and

Figure 7-24. Changing file permissions

select Read & Write access for Owner, Group, and Others; then close

of index.xml on Mac OS X

the Info window (see Figure 7-24).

 

329

B L O G D E S I G N S O L U T I O N S

Here is the function that will write your RSS file:

function makerssfeed() { // set file to write

$filename = $_SERVER["DOCUMENT_ROOT"] . "/index.xml";

// open file

$fh = @fopen($filename, "w");

if($fh) {

$rssfile = "<rss version=\"2.0\"> <channel>

<title>Samuel's Blog</title> <link>http://your-domain-name.com</link> <description>A blog by Samuel Pepys</description> <language>en-gb</language>";

// pull blogs from database

$sql = "SELECT post_id, title, summary, DATE_FORMAT(postdate, '%a, %d %b %Y %T GMT') as pubdate FROM posts ORDER BY postdate DESC LIMIT 10";

$result = mysql_query($sql);

if ($mypost = mysql_fetch_array($result)) { do {

$post_id = $mypost["post_id"]; $pubdate = $mypost["pubdate"]; $summary = format($mypost["summary"]); $title = $mypost["title"];

$title = strip_tags($title); $title = htmlentities($title);

$rssfile .= "

<item>\n";

$rssfile .= "

<pubDate>$pubdate</pubDate>\n";

$rssfile .= "

<title>$title</title>\n";

$rssfile .= "

<link>http://your-domain-name.com/

post.php?post_id=$post_id</link>\n";

$rssfile .= "

<description><![CDATA[$summary]]>

</description>\n";

 

$rssfile .= "

</item>\n";

} while ($mypost = mysql_fetch_array($result));

}

$rssfile .=" </channel> </rss>";

// write to file

$fw = @fwrite($fh, $rssfile);

330

W R I T E Y O U R O W N B L O G E N G I N E

if (!$fw) {

$message = "Could not write to the file $filename";

}else {

$message = "RSS file updated.";

}

// close file fclose($fh);

}else {

$message = "Could not open file $filename";

}

return $message;

}

Your code will be calling the function from more than one place, so the ideal place to add it is in the functions.php include you made earlier. Make sure that the makerssfeed function is placed before the closing ?> delimiter.

I will now step through the function. It is really just a simplified version of your blog homepage: It grabs the ten most recent blog entries from the database and writes them to a file. The main differences will be the RSS file syntax (which is similar to but different from

HTML) and some new functions for file handling, which is what we kick off with:

7

function makerssfeed() { // set file to write

$filename = $_SERVER["DOCUMENT_ROOT"] . "/index.xml";

// open file

$fh = @fopen($filename, "w");

if($fh) {

Here, the full server path of the RSS file is written to the $filename variable. Next, the fopen function is used to open the file for writing (that’s what the w means). As mentioned earlier in the chapter, the @ before the function call prevents any ugly errors being written to the screen. I’m writing the fopen function to the $fh variable. If the fopen function failed (perhaps the index.xml file doesn’t exist or it is read-only), the value of $fh is false, and there’s no point continuing with the function.

$rssfile = "<rss version=\"2.0\"> <channel>

<title>Samuel's Blog</title> <link>http://your-domain-name.com</link> <description>A blog by Samuel Pepys</description> <language>en-gb</language>";

The script has verified that your RSS file has been opened for writing, so it now starts to piece together the contents of the file. The script will compile the entire file in a variable called $rssfile and then write it to index.xml. Here the script has begun with the opening elements required by RSS (make sure that you change these details to match your

331

B L O G D E S I G N S O L U T I O N S

blog). More information on the RSS 2.0 syntax can be found at feedvalidator. org/docs/rss2.html.

// pull blogs from database

$sql = "SELECT post_id, title, summary, DATE_FORMAT(postdate, '%a, %d %b %Y %T GMT') as pubdate FROM posts ORDER BY postdate DESC LIMIT 10";

$result = mysql_query($sql);

The script now performs the familiar SELECT query in which it grabs the latest ten blog post titles and summaries. The postdate is formatted in a special way for RSS feeds and includes the time zone (in this case, GMT), which you may have to change according to where your live website is hosted.

if ($mypost = mysql_fetch_array($result)) { do {

$post_id = $mypost["post_id"]; $pubdate = $mypost["pubdate"]; $summary = format($mypost["summary"]); $title = $mypost["title"];

$title = strip_tags($title); $title = htmlentities($title);

$rssfile .= " <item>\n";

$rssfile .= " <pubDate>$pubdate</pubDate>\n"; $rssfile .= " <title>$title</title>\n";

$rssfile .= " <link>http://your-domain-name.com/ post.php?post_id=$post_id</link>\n";

$rssfile .= " <description><![CDATA[$summary]]> </description>\n";

$rssfile .= " </item>\n";

} while ($mypost = mysql_fetch_array($result));

}

This code should again look familiar as the script loops through the posts and writes them to the $rssfile variable. Because you are writing RSS instead of HTML, the mark-up will look different, but it is still structured in a similar manner.

$rssfile .=" </channel> </rss>";

Here, the final closing tags are added to the RSS feed. It is now ready for writing to your index.xml file.

// write to file

$fw = @fwrite($fh, $rssfile); if (!$fw) {

$message = "Could not write to the file $filename"; } else {

332

W R I T E Y O U R O W N B L O G E N G I N E

$message = "RSS file updated.";

}

// close file fclose($fh);

The script uses the fwrite function to write the contents of $rssfile to the $fh file handler created at the beginning of the script. As with fopen, fwrite returns false if the writing process fails. Finally, the fclose function is used to release the index.xml file, and your RSS feed has been updated.

But all you have at the moment is a function that can update your RSS feed. That function is not actually called from anywhere. Your RSS feed will need updating on three occasions: when you add a new blog post, when you update a post, and when you delete a post. The first two instances happen in the addpost.php file. So open that file. Just after the opening <?php delimiter, add this code to bring in the functions.php:

include($_SERVER["DOCUMENT_ROOT"] . "/functions.php");

Now find the line that says the following:

$message = "Successfully inserted post '$title'.";

7

Following that line, add this call to the makerssfeed function:

$message .= "<br />" . makerssfeed();

Now find this line:

$message = "Successfully update post '$title'.";

After that line, add the same call to makerssfeed. The delete blog function is on the index.php page in your CMS, so add the functions.php include to that file in the same way and add the same call to makerssfeed after this line:

$message = "Post $delete deleted.";

Now try making a change to one of your blog posts using your CMS, which will force the RSS file to be created. Once you have received the message RSS file updated in your CMS, open up index.xml in your text editor and you should see something like this:

<rss version="2.0"> <channel>

<title>Samuel's Blog</title> <link>http://your-domain-name.com</link> <description>A blog by Samuel Pepys</description> <language>en-gb</language> <item>

<pubDate>Sun, 03 Apr 2005 15:30:00 GMT</pubDate> <title>Knight of the Burning Pestle</title> <link>http://your-domain-name.com/post.php?post_id=2</link> <description><![CDATA[<p>News of the fleet and an

afternoon with Mrs. Turner to see a dreadful play.</p>]]>

333

B L O G D E S I G N S O L U T I O N S

</description>

</item>

<item>

<pubDate>Mon, 28 Mar 2005 22:15:00 GMT</pubDate> <title>Paying my debts</title> <link>http://your-domain-name.com/post.php?post_id=4</link> <description><![CDATA[<p>Paying my debts and thence to

Covent Garden and an Italian puppet play.</p>]]> </description>

</item>

<item>

<pubDate>Sat, 01 May 2004 23:10:00 GMT</pubDate> <title>Bad arm</title> <link>http://your-domain-name.com/post.php?post_id=3</link> <description><![CDATA[<p>My arme not being well,

I staid within all the morning.</p>]]></description> </item>

</channel>

</rss>

Finally, you need to tell the world that you have an RSS feed. Many indexers will automatically look for an index.xml file, but you should also add this line just after the <title> in your blog homepage to make sure:

<link rel="alternate" type="application/rss+xml" title="RSS 2.0 feed" href="http://your-domain-name.com/index.xml" />

Once your RSS feed is up and running on your live site, I recommend submitting it to pingomatic.com, which will automatically notify all the web-based RSS news readers that your RSS feed exists.

Making it live

And so your blog engine is complete. You now have an administration site to add and edit blog posts and a blog site with a homepage listing your latest entries, a page for each post allowing comments, an archive of all past entries, search functionality, and an RSS feed. All that remains is to move the whole lot onto a live web server.

Migrating your database

I assume that your Internet Service Provider has provided you with FTP access, PHP, and MySQL. If so, it probably provided you with phpMyAdmin as well. If phpMyAdmin is not installed, you can use FTP software to copy your phpMyAdmin files to your live server. In this case, you will probably have to edit the username and password in the config.inc.php file, as explained in Chapter 2.

334

W R I T E Y O U R O W N B L O G E N G I N E

Now you’re ready to copy your database to your live server. Open up your local installation of phpMyAdmin in your browser and select the blog database. Click the Export tab. Now click the Select All link in the Export box so that the posts and comments tables are both selected. Finally select the Save as file option and click Go (see Figure 7-25). A file called blog.sql should be saved to your default download folder (usually your desktop).

7

Figure 7-25. Exporting your database in phpMyAdmin

Now you have a complete copy of your database: table structure, indexes, and data. To import this onto your live server, open up the remote installation of phpMyAdmin and create a database called blog. Now click the SQL tab and browse to select your blog.sql file in the Location of the textfile section. Click Go, and your database will be uploaded. Easy as that!

335