Chili Pepper Design

Web development relleno

Adding the “Rel” and “Title” Attributes to Image Links in CKEditor 3

| Comments

CKEditor is the new and improved successor to the venerable FCKeditor JavaScript WYSIWYG editor. I’ve used TinyMCE and FCKeditor before, but this was my first time trying out the new CKEditor 3.1. I am using it on a new Drupal website via the Drupal CKEditor module. The problem I ran into, however, is using Lightbox2 on images inserted via CKEditor. CK does not provide a way to add the “rel” attribute to image links (or any links for that matter). CK also doesn’t allow adding the “title” attribute to image links. Lightbox uses both of these to determine which images to display, group together in galleries, provide a caption, etc. I found a patch for FCKeditor which allows adding a “rel” attribute to image links, but I couldn’t find one for the new CKEditor. So here we are. :)

This is a total hack, since I have not looked in to how to properly make a plugin for the new CKEditor, but it works pretty well. Maybe someone who knows how to make plugins to CKEditor can show me the way.

Configuring and Compiling Nginx and PHP-FPM on Ubuntu for Magento, Part 3

| Comments

This is the 3rd and final article about installing Magento on Nginx with PHP-FPM. Part 1 is here, and Part 2 is here.

This part explains how I set up my public web directories, and how I did the Nginx configuration files for a Magento site. One of the tricky things about switching to Nginx from Apache is that Nginx does not use .htaccess files or the usual Apache mod_rewrite rules for pretty/SEO URLs. You can replicate all of Magento’s mod_rewrite rules with Nginx’s own rewrite module, but it takes some getting used to and Magento doesn’t come with them pre-written (like the mod_rewrite rules in the .htaccess files).

Here are some of the resources I used:

First we’ll set up the directory structure like we are used to with Apache:

# mkdir /usr/local/nginx/sites-available
# mkdir /usr/local/nginx/sites-enabled
# mkdir /var/www/
# mkdir /var/www/
# cp  /usr/local/nginx/conf/nginx.conf /usr/local/nginx/conf/nginx.conf-original

Then set up the base nginx conf file /usr/local/nginx/conf/nginx.conf:

user www-data;
worker_processes 1;

events {
    worker_connections 1024;

http {
    include mime.types;
    default_type application/octet-stream;
    sendfile on;
    keepalive_timeout 65;
    gzip on;
    include /usr/local/nginx/sites-enabled/*;

Then set up the Nginx conf file for your website. I am using the default site in this example /usr/local/nginx/sites-available/default, but if you have multiple sites instead of default you would create files called,, etc.

This file is where all of the rewrite magic is. The url in this example is, which you should replace with your own. The document root is /var/www/ which, again, you will need to change to match your own configuration.

# fastcgi nodes
upstream  backend  {
    server unix:/tmp/fcgi.sock;

# redirect all non-www requests to www requests (it would be easy to reverse this)
server {
    listen   80;
    rewrite ^/(.*)$1 permanent;

server {
    listen       80;

    # protection (we have no .htaccess)
    location ~ (/(app/|includes/|lib/|/pkginfo/|var/|report/config.xml)|/\.svn/|/.hta.+) {
        deny all;
   # pass php files over to PHP-FPM via the socket
    location ~ (\.php)$ {
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
        if (-e $request_filename) { # check if requested path exists
            fastcgi_pass backend;
    # the javascript compressor
    location ^~ /js/index.php {
        fastcgi_pass   backend;
        fastcgi_index index.php;
        fastcgi_param  SCRIPT_NAME $fastcgi_script_name;
        fastcgi_param  SCRIPT_FILENAME  /var/www/$fastcgi_script_name;
        include /etc/nginx/fastcgi_params;
        access_log off;
        expires 30d;
   # special case for the error "report" pages
    location /report/ {
        fastcgi_index index.php;
        include /etc/nginx/fastcgi_params;
        fastcgi_param  SCRIPT_NAME /report/index.php;
        fastcgi_param  SCRIPT_FILENAME  /var/www/;
        if (!-f $request_filename) {
            fastcgi_pass backend;
    # pass everything else over to PHP-FPM via the socket
    location / {
        root /var/www/; # absolute path doc root
        index index.php index.html index.htm;

        # set expire headers
        if ($request_uri ~* "\.(ico|css|js|gif|jpe?g|png)$") {
            expires max;
        # set fastcgi settings, not allowed in the "if" block
        include /etc/nginx/fastcgi_params;
        fastcgi_param SCRIPT_FILENAME $document_root/index.php;
        fastcgi_param SCRIPT_NAME /index.php;
        # rewrite - if file not found, pass it to the backend
        if (!-f $request_filename) {
            fastcgi_pass backend;
        error_page 404 index.php;
    access_log /var/www/;
    error_log /var/www/;

I am no expert with Nginx, but a lot of Google searching and trial and error gave me the file above, and it seems to work. I hope it is helpful, even if this exact code doesn’t work for you.

Finally, activate the site by creating a symbolic link to it and restarting the server:

# ln -s /usr/local/nginx/sites-available/default /usr/local/nginx/sites-enabled/default
# ln -s /usr/local/nginx/sites-enabled /etc/sites
# /etc/init.d/nginx restart

And that’s it! You should now have Magento running on Nginx! (After, of course, also installing mysql and a sendmail program, and probably an FTP server, and who knows what else :)

Now, how to make it actually go faster than Apache? There are many settings you can tweak. Look in fastcgi_params to change PHP-FPM settings, php.ini to change APC settings, my.cnf to change mysql settings, nginx.conf to adjust the number of worker processes and the keepalive timeouts… the list goes on. Good luck!

Configuring and Compiling Nginx and PHP-FPM on Ubuntu for Magento, Part 1

| Comments

So, Magento is a huge piece of modular and extensible PHP code. Each request takes a lot of CPU cycles and memory to kick out a Magento page. This means it is slow. The performance of Magento is a frequent complaint, and rightfully so: consumers won’t wait around all day for an ecommerce store to load. They will bail out and try another store if a page doesn’t load in just a few seconds. A default Magento 1.3 install on budget web hosting can have page load times of up to 10secs, which is unacceptable.

So what can be done to speed up Magento?

There are a number of things. I have tried almost all of them at this point. And I did reduce the page load time greatly, at least on the front end. But all of the AJAXy scripts on the backend (which has no caching, as far as I know) meant store maintenance and order fulfillment remained a tedious process. So I decided to try one final thing: make the switch from trusty old Apache to Nginx.

Book Review: Magento Beginner’s Guide

| Comments

I was recently approached by [packt] Publishing to do a review of their book, the Magento Beginner’s Guide (by William Rice). I’ve been working with Magento a lot over the past year and blog about it here from time to time, so they figured I would be good to review it. After setting up, modifying and maintaining four Magento stores in the last 10 months I don’t feel I have much to learn from a “beginners guide”, but I figured I could use my experience of what a beginner actually needs to know and see if this book covers all the bases.

I have read parts of the official Magento User Guide (and php/architect’s Guide to E-Commerce Programming with Magento) but this book fills a different gap than the others. The User Guide covers all of the features, but it is not a practical guide. (The programming book was great, but did not cover how to actually use Magento). My favorite thing about the Beginner’s Guide is that it showed how to use Magento in a practical, day-to-day way. Being just a “beginner’s guide” it does not cover all of the features, but it covers a wide swath of the important ones. What really impressed me was the way it provided tips on how to deal with and overcome some of Magento’s serious (and occasionally deal-breaking) problems that make the day-to-day administration of an online store difficult.

A Simple FBJS Image Carousel (or Slideshow) for Facebook Page Tabs

| Comments

(Plug: Looking for an easy, fast, affordable way to create custom Facebook landing tabs? Check out my new product: Thanks!)

This little code snippet is really basic, and not actually that good or clever. You can make a much nicer slideshow or carousel if you put a little time into it. But I just want to demonstrate how many of the nice JavaScript effects we are used to on the “Web 2.0” are also possible on a Facebook Page via Facebook’s Animate library. It’s not as robust as jQuery or Scriptaculous, but since you can’t import those libraries to a Tab the Animate library will have to do. :)

The final result looks like this:
Screenshot of the Chili Pepper Design Facebook image carousel

And you can view a live demo on the CPD Facebook Page

For instructions on how to create your own custom Facebook tabs, read my tutorial here.

To begin, here is the simple FBJS <script> code:

How to Make Custom Facebook Fan Page Tabs With FBML, Part 2

| Comments

UPDATE 2-14-2011: FBML is going away – learn about Facebook iframe tabs on Facebook Pages here

UPDATE 3-10-2011: Easily create and manage custom Facebook Page Tabs with SplashLab Social – Now available!

Quick and Dirty Custom Facebook Page Tabs and Boxes

The fastest and easiest way to add custom Tabs to a Page is with the Static FBML application. A nice visual tutorial of this method is posted on I will also quickly outline the process here:

How to Make Custom Facebook Fan Page Tabs With FBML, Part 1

| Comments

UPDATE 2-14-2011: FBML is going away – learn about Facebook iframe tabs on Facebook Pages here

UPDATE 3-10-2011: Easily create and manage custom Facebook Page Tabs with SplashLab Social – Now available!

If you have started to dabble in the new wave of “social media marketing” you probably made your business/brand/company/band/etc a Facebook Fan Page. These are basically just like regular Facebook user profiles except instead of a business having “friends”, they have what are (more accurately) called “fans”. This seems like a good idea since Pages provide a great way for companies to interact with their customers. That part of Fan Pages is a good idea, and everyone seems to have a link to “find us on facebook!” now because of it! But there are challenges.

It’s hard to brand a Facebook Page. You can change the Profile Picture and upload photos and videos, etc, but it all feels very much like Facebook still. This consistent visual look is one of the great things about Facebook, but if someone finds your company on Facebook before ever visiting your regular website, your ability to educate the visitor about your products or services is extremely limited. And if you send someone to your Facebook Page from your regular website, there is no clear way to route them back to where the sale will actually be made. It can be a problem. Once they hit Facebook you are at the mercy of whatever users post on the Wall or write in the Reviews tab.

Custom Loops for Custom Taxonomies in WordPress 2.8

| Comments

WordPress 2.8 saw a big expansion and enhancement of it’s Taxonomy API, allowing for easy creation of custom taxonomies. The default WordPress “category” and “tag” taxonomies are sufficient for most blogs, but the ability to define additional sets of terms (“vocabularies”) makes the platform a much more flexible and powerful Content Management System than it was before. Ever since Justin Tadlock opened my eyes to how to create and use additional taxonomies, it seems like every WordPress project I work on needs one or two extra vocabularies. :)

Working with Drupal as much as I have, I became very accustomed to having multiple taxonomies. It’s incredibly useful. A classic example is Movies: each movie has a director, some actors, a year it was made, etc. You could just lump all these together with a bunch of “tags” in WordPress, but grouping “Actor” and “Year” tags together into taxonomies makes site organization and navigation much simpler (and more sensible).

But there are some challenges still to using WordPress taxonomies. While there is some support in the new API word making queries based on specific taxonomies, there is not a lot. You can filter your Loop by a term in a single taxonomy via the query_posts(), as Justin shows in this example:

WordPress: A Loop Inside of a Loop With Working Comments

| Comments

I was faced with a problem while creating a WordPress theme the other day. I was grouping posts together using a 2.8 custom taxonomy (which is my new favorite thing in WordPress), and wanted to display a list of all related posts above the Comments template. Basically wanted a small Loop inside of the main Loop – a loop within a loop.

I found a few pages online which address this, such as WordPress Loop Inside of a Loop and Calling a WordPress Loop from inside a WordPress Loop. The idea is pretty simple, and these techniques work fine most of the time.

Everything looked fine to me, as well, until I hit “Submit Comment” to test it… and the comment appeared on the wrong post.

The problem is that inner loop sets the global $post object to the last item in that loop. The methods the_post() and setup_postdata($post) set up the global variables which are needed by the_permalink(), the_title(), comments_template(), etc. So if you call any of these usual “Loop” methods again AFTER the inner loop, they are operating on the last post in the inner loop instead of the current post in the main loop.

The trick is to save the $post objects before the inner loop and to reset them again after the inner loop. To do this, change the Loop structure to follow this template:

$posts = get_posts($wp_query->query);  //get the posts
foreach($posts as $post) :   // cycle through them in the main loop
	$currentPost = $post;  // save the current "main loop" post 
	setup_postdata($post);  // instantiate the global post variables to the main loop post
	the_title();    // use your usual Loop methods 

$innerposts = get_posts('order=asc&mytaxonomy=mycustomerterm);  //get the posts from my custom taxonomy
	foreach($innerposts as $post) :   // cycle through them in the main loop
		setup_postdata($post);  // instantiate the global post variables to the inner loop post
		the_title();    // the inner loop post's title
	endforeach;  // end of inner loop

$post = $currentPost;  // reset the post from the main loop
	$id = $post->ID;  // reset the post from the main loop
	comments_template();  // now, the comments for the post in the main loop
endforeach;  // end of main loop

Another way to do this might be to NOT set the global variables in the inner loop, thus avoiding this issue with the comments entirely. You would just have to directly access the post variables in the inner loop, i.e. $rel_post→post_title instead of the_title(). It would work for simple things, like the title and slug. Check out custom select querySelectQuery in the WordPress Codex to figure out how to get all of the fields you need from the DB to use this method.