Posts Tagged ‘web development’
Using WordPress as a website backend
How often have you found yourself creating a great new website design for a friend, family or a client, just to realize after all your HTML and CSS is done that the thing will need an administration panel? Way too often, the administration comes as an afterthought, and thus it ends up being incomplete, hard to use or in some cases absent. Two months down the track you end up being contacted again to do some “site updates”, and these just keep coming.
Making a good administration panel takes a bit of work, and it takes planning to ensure that the client can update the parts of the site as he/she wishes, and more importantly, that your interface gets all the information it needs. If your design has a thumbnail for every post, your administration panel has to provide the opportunity to upload an image and attach it to a post.
For years, I have been making these admin pages myself, until I read a post on WordPress custom themes. This post was on how to write a theme for WordPress, but it hinted at the possibility of having a standalone site that used WordPress as its backend, thus providing a full-fledged, well designed and familiar administration interface to any site. At first I was skeptical to the idea because I thought WordPress was way to inflexible to allow for the variety of pages I make. I was wrong. You see, if you really thing about it, all you need to make most websites are two things: Posts in categories and dynamic text/HTML blocks.
To give you an idea on how flexible WordPress is, and how it can be used, consider the following website which I am currently working on. The site is for a sound production company, and will contain the following:
- Short posts giving updates on what the studio is working on at the moment. These have to have a short text to be shown on the front page, a feature image and a rich-text full article.
- An image feed showing images of the sound studio
- A page with the various projects the studio has completed. Each project has an image, a description and one or more music tracks. Each track has two variants, a streaming-quality MP3 and a high-quality WAV.
- An about page with two separate columns, one on the sound designer, and one on the company
- A list of previous clients with a short description and a link to the client’s website
At first, this seems outside the scope of WordPress which only deals with Posts and Pages, but let’s have a closer look.
The posts are clearly just regular WordPress posts. Let us put them in a category called “Frontpage”.
The image feed is just a stream of images. We here have two choices, use WordPress’ media library, and attach all images to be shown in the feed to a static page, or use a flickr stream. I opted for the latter, but WordPress could have handled this fine!
Each music project can be a blog post (you heard me right) in the category “Projects”. We can then attach images and songs to the post using the WordPress media library. The two versions of each music file can be given the same name, and we can use the MIME type to distinguish between them.
The two text blocks 0n the about page can be two WordPress Pages (let’s call them ‘designer’ and ‘studio’)
Finally, the list of clients can be implemented using a set of links in a link category.
So, how would we go about and convert our static HTML into a fully dynamic site with a complete administration interface? Let’s dig into some code.
Getting access to WordPress from your code
The first step to a well-integrated site is to include the following code at the top of any page that needs to access WordPress functions. Naturally this does not need to be included in included/required files.
define('WP_USE_THEMES', false);
require('./wp-blog-header.php');
This gives you access to a whole set of WordPress functions (http://codex.wordpress.org/Function_Reference) that will aid us in integrating your site with WordPress. Unfortunately, the WordPress API is not very well structured, and naming conventions are a bit all over the place, but we’ll make do.
Getting content from WordPress
From the WordPress function list, there are a couple of terms you need to become accustomed to in order to start using the API. First of all, “The Loop”.
Now, we will not actually be using the loop to display any of our pages for two reasons: “The Loop” is a magic thing that mysteriously figures out what posts/pages to display, and is associated with some magic methods such as get_the_author which magically contain data about the “current” post, whatever that is. Second, it provides very little flexibility for selecting only certain posts/pages.
I will not go into the details of “The Loop” here, I will just say that it is a while loop that most WordPress templates use to print blog posts, pages, etc. to abstract away the backend query. There are several methods in the WordPress API that depend on being used in The Loop, and these usually contain “the” in the function name. Avoid these!
Next, in WordPress, pages are posts. Special types of posts, but posts nonetheless. This means that if you fetch a page, the various fields available will be the exact same as those for post, and they will be named post_title, post_content, etc…
When printing the content of posts (that is, any field that has a rich text field as input), WordPress depends on you running the data through another magical function: wpautop. This function automatically adds p tags where it thinks is appropriate to mimic the appearance in TinyMCE in the admin panel. Always put post_content through this function, otherwise your output is going to look very weird indeed.
Finally, the WordPress API usually returns objects or lists of objects. This is very convenient for most uses, but it also means that you have to take care in those cases where it doesn’t. One such method that you will probably be using is wp_get_attachment_image_src; this function actually returns a numerically indexed array.
Most function that return objects contain all the fields outlined in the appropriate table in this database diagram: http://codex.wordpress.org/Database_Description. Note that almost all models will contain an ID field which comes in very handy. Most other columns are prefixed by the name of the table, and this prefix is also used in the object attributes.
Getting posts
When getting blog posts, the main function to think about is get_posts. This function has a plethora of configuration options, but usually, you will only need the numposts option, and maybe offset. In the case of the website I was developing, I wanted just the posts in a given category
foreach ( get_posts ( 'numberposts=7&category=4' ) as $post ) {
echo $post -> post_title;
}
This is a very simple example which only prints the title of each post, but you get the drift.
If you want a full version of a post given its ID, you would use the quite similar get_post (http://codex.wordpress.org/Function_Reference/get_post) function. This function takes a post ID, and returns an object representing that post. This object tells you nothing about the author or any attached images, so these will have to be fetched separately as such:
$post = get_post ( $_GET['p'] ); // This is probably quite insecure. Sanitize your input!
$author = get_userdata ( $post -> post_author ); // Here we should do some error checking on $post first
$images = get_children ( array(
'post_type' => 'attachment',
'post_parent' => $post -> ID,
'post_mime_type' => 'image'
) );
There is a bit of voodoo going on here, so let’s take it step by step.
The first line should be pretty straightforward, we simply get the appropriate post object by its ID (which we take from the query string).
The next line is also quite simple, we fetch the user data of the user with the ID matching that of the author of the post.
Now we get to the strange bit; get_children. You see, WordPress treats almost everything as posts. Even attachments, no matter the type, are considered posts, and are part of the page/post hierarchy. Thus, to get the attachments of a post or page, we are actually getting all the children of the given object of the type ‘attachment’. I have also added a filter on ‘post_mime_type’ to ensure we only get images. Notice how WordPress sometimes uses strings as arguments, and other times uses arrays? Turns out you can usually get away with both approaches… Someone should really write a wrapper class to sort out that mess, but until then, we’ll have to deal with it. The good part though is that the process for getting the images for a page is exactly the same, just replace get_post with get_page!
The most interesting part though is showing an image you’ve fetched. WordPress “conveniently” provides user-customizable thumbnails for all uploaded images. Unfortunately, these tend to be cropped in weird ways, and are very unpredictable and unlikely to look nice. When printing an image, you have a choice between several formats, amongst others ‘thumbnail’ (the default) and ‘full’. The only one that gives you an uncropped image is ‘full’, but this will give you the image in its original resolution. True, the users can edit and scale the images in the admin panel, but how many end-users can you expect to do that? Unfortunately there is no way around that at the moment AFAIK, but one happy day…
Anyway, until then, you have a choice of two functions for printing your images: wp_get_attachment_image and wp_get_attachment_image_src. They both take the same arguments, but the difference is that the first one prints a full ‘img’ HTML tag with the alt, title, width and height attributes already set, whereas the second one just returns the image url, the widht and the height as a numerically indexed array that you can decide what to do with. They both take the ID of the image as a first parameter, and the size you want as the second. Here, you can either give a predetermined size such as ‘thumbnail’, get the full image with ‘full’ or get a cropped thumbnail that fits inside a certain box by passing an array of two values, width and height as such: array ( 64, 64 ). If you want to get the image description and title yourself, those are stored in the object you used to get the ID for wp_get_attachment_image_*, i.e. in $images[$i].
Other attachments (mp3s for instance)
When it comes to getting other post attachments, this is actually quite trivial once you know how to fetch images. Instead of using ‘post_mime_type’ => ‘image’, you simply use another MIME type. On the site I am developing, I will use the MIME type for mp3 which is ‘audio/mpeg’ as far as WordPress can tell (you can see this in the WordPress admin panel -> Media). I would therefore substitute ’post_mime_type’ => ‘image’ with ‘post_mime_type’ => ‘audio/mpeg’. Simple as that!
To get the direct URL for a non-image attachment, you can use the wp_get_attachment_url function. As for getting the high quality version of a file, this is just a matter of selecting an attachment with the same title (i.e. the name of the file without the extension), but a different MIME type.
Dealing with pages/editable content boxes
Now, for the boxes on the about page which the administrators of the page should be allowed to edit. This is as easy as just creating two new pages in the WordPress admin and noting down the name you use. Back in your code, you can then use the following snippet to print the content of the box/page:
$page = get_page_by_title ( 'About box left' ); echo wpautop ( $page -> post_content );
By now this should look familiar. We are simply fetching the page by its title, and then passing the pages content through wpautop, and echoing the result.
Lists of links with descriptions
Our final challenge for this site will be to fetch the list of clients. We’ve already determined that we are going to use the WordPress Links library because this provides exactly the fields we need, a title, a URL and a short description. However, if you start looking through the WordPress API for anything related to links, you will come up empty handed. The reason for this is that in their wisdom, WordPress decided to call links “bookmarks” in their API for the sake of clarity. The function we are looking for here is called get_bookmarks, and again we may specify lots of parameters. In our case, however, we are only concerned with one of them; category. Since we may want to add other links later that should not show up in the clients list, we create a link category from the WordPress admin and note down the category ID. In my setup it was 3, and so my code to get the links/bookmarks becomes:
foreach ( get_bookmarks ( array ( 'category' => 3 ) ) as $link ) {
echo '<a href="' . $link -> link_url . '">' . $link -> link_name . '</a>';
echo '<blockquote><p>' . $link -> link_description . '</p></blockquote>';
}
Of course, this is a simplified version of the end result, but it should give you enough of an idea to get you on your way.
Final thoughts
As you have now seen, this entire page can now be administered fully through WordPress with its quite good admin panel, and the user won’t even think twice about WordPress really being a blogging tool. In fact, neither should you, because as you can see, it is more than flexible enough to be used for quite complex websites. Your users will be happy with a comfortable admin interface, and you won’t have to touch a single piece of admin code!
Developing for the modern web
Web development today is a constantly struggle between three major stakeholders: the customer, the designer and the developer. The customer tries to push through his or her (often distorted and silly) mental image of the website, the designer wants to be original, creative and fancy creating lots of intricate designs with fancy visual effects, and the developer who attempts desperately to explain to both the customer and the designer why what they’re doing is a bad idea (heavy background images, crammed pages, no whitespace, confusing visual effects…). The developers aren’t all good either though – They tend to put in as many fancy tricks and solutions in the final product as they can, often resulting in exotic bugs in various browsers and usually ungraceful downgrading™. In all of this, one stakeholder is often wholly forgotten, even though it is probably the most important one; the users.
Users often don’t know the first thing about how the web works. They don’t care whether the site is optimized for Firefox, Internet Explorer, Chrome or Safari (in fact, they probably don’t even know what a browser is…) The users want a site that is visually appealing, but not distracting – informative, but not cluttered – clear, but not over-simplified – and most importantly, one that is responsive. When a user does something, they should begin to see something happening within .1 seconds (http://www.useit.com/alertbox/timeframes.html) to feel as though they aren’t being slowed down by the site itself. Furthermore, the total loading time for whatever action the user initiates should be less than a second for the user not to fall out of his or her “flow”. Way to many websites violate these simple rules, causing the site to feel unresponsive to the user, and the users are likely to jump to the next site on their list.
In this post, I hope to show you how to make your website faster – mainly through optimizing the initial page load. In order to do this, there are three steps that need to be taken: Combine, Compress and Communicate. Repeat after me: Combine, Compress and Communicate.
Combine
Many developers seem to think (albeit erroneously) that many small files are better than few large ones. This might seem intuitive since a smaller file downloads faster than a large one, and you would think they could all be gotten out of the way quicker. The truth is quite different. Due to limitations of the HTTP protocol, the browser has to initiate a new request to the server for every single file, causing quite a bit of overhead when having to download several files. Also, modern browsers limit the amount of simultaneous downloads to 6, meaning downloading all of your small files will go even slower. Add to this the sequential nature of JavaScript, and the fact that the browser stops loading the page once it hits a JavaScript piece (external or not), and doesn’t continue loading until the JavaScript file is finished downloading and has been interpreted.
Therefore, you should work to combine as many of your files as possible. Don’t jump to put all your scripts and styles inline, however (you will understand why in Communicate). Instead, you should attempt to combine all your CSS files into one, all your JavaScript into another, and all your images into a third. Ideally, you should need no more than three external files on your site. So, how do you go about doing this?
CSS and JavaScript
Combining CSS and JS files shouldn’t itself be a problem.. Open up a text editor, copy-paste all of your CSS or JS into that file, save it and upload. You should probably still keep the separated files for readability though. Of course, modern web applications are usually a bit more complicated. For instance, you might have a stylesheet that is only included on sites with ads on them or a JavaScript file that is only needed on your frontpage. In these cases, your should look into using a combinator. One of the best sites describing the techniques of combining is this one. The mod_concat plugin for Apache2 provides several advantages over traditional scripting approaches especially with regards to communication (as will be discussed later)
Images
All your images should be done as sprites. Ideally, you should even be able to put every single image on your site into a single png image. Do this, and you will substantially reduce the loading time of your site. For an introduction to CSS sprites, have a look here.
Compress
All your CSS and JS files should be compressed to reduced overall download size. Again, it is usually a good idea to keep the original, uncompressed versions of the files, and re-compress the files whenever you change them. For CSS, I recommend the YUI compiler (http://www.refresh-sf.com/yui/). It does JavaScript as well, but Google’s recently released Closure Compiler seems to be even more effective at compressing it. You can find it at http://closure-compiler.appspot.com/home. With the Closure Compiler, you can also select the advanced compiler which will decrease the total file size even more, but will mess up your files’ external API. This means that any functions you define inside your files won’t be available from the outside by the same name. The internal workings of the file will be preserved though.
Apart from minimizing the files, you should also compress them using something like GZip which is natively supported by several browsers. To see how to do this automatically with Apache2, have a look at http://www.cyberciti.biz/tips/speed-up-apache-20-web-access-or-downloads-with-mod_deflate.html.
Communicate
OK, so all of your files are combined and compressed, and you’ve never seen the CSS and JavaScript download so quickly. How can it possibly go any faster? Quite simple – by preventing the browser from having to download the files at all. Modern browsers include a lot of caching technology to prevent them from downloading unnecessary data from the server. The problem is that many web servers do not communicate properly the states of the files, and the browsers can thus not determine if a file has changed or not; and therefore they download the file just to make sure. So, what should you do?
First of all, you need to tell your web server to send out as much data as possible about your file. This especially applies to dynamic files such as those created by PHP. Have a look here for a more thorough discussion of this topic.
Second, files that are GZipped by Apache don’t always get an expiration date, causing the browser to re-download the file on every page load. To overcome this problem, have a look at the first answer on this page
Final thoughts
In the course of this post, I hope I have given you an overview of what can be done to speed up the loading time of web pages, and enough pointers to keep you going in your quest for the best speed your website can achieve. This is an ever-expanding topic, and new techniques are always appearing, so you should attempt as best you can to keep up to speed (pun intended) on the newest advances in the field.
Happy speeding!