<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Command-Tab &#187; Programming</title>
	<atom:link href="http://www.command-tab.com/category/programming/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.command-tab.com</link>
	<description>Technology and Mac geekery. One part exuberance, two parts obsession.</description>
	<lastBuildDate>Sat, 07 Jan 2012 18:00:29 +0000</lastBuildDate>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.2.1</generator>
		<item>
		<title>True PHP Debugging with Nginx and PHP-FPM</title>
		<link>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/</link>
		<comments>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/#comments</comments>
		<pubDate>Mon, 20 Jun 2011 15:27:42 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=1165</guid>
		<description><![CDATA[Mac OS X is an increasingly popular platform for web developers, client-side and server-side alike. For doing intensive PHP development on OS X, you can use a full-blown IDE like Zend Studio or PhpStorm, but I like my toolkit to be much more lightweight. I prefer to code in TextMate, execute SQL queries in Querious, [...]]]></description>
			<content:encoded><![CDATA[<p>Mac OS X is an increasingly popular platform for web developers, client-side and server-side alike.  For doing intensive PHP development on OS X, you can use a full-blown IDE like <a href="http://www.zend.com/en/products/studio/">Zend Studio</a> or <a href="http://www.jetbrains.com/phpstorm/">PhpStorm</a>, but I like my toolkit to be much more lightweight.  I prefer to code in <a href="http://macromates.com/">TextMate</a>, execute SQL queries in <a href="http://www.araelium.com/querious/">Querious</a>, run code in Safari, and perform technical tasks in Terminal.  Absent from this agile team, though, is a true PHP debugger, leaving you with only rudimentary calls like <code>printf</code> and <code>var_dump</code> for debugging.  Worse still, you have to change your code just to debug it.  We can do better.</p>
<p>Recently, I discovered an excellent tool that filled the need for a lightweight PHP debugger.  <a href="http://www.bluestatic.org/software/macgdbp/">MacGDBp</a> communicates with PHP using the <a href="http://xdebug.org/">Xdebug</a> PHP extension, and offers variable inspection, stepping controls, breakpoints, and a call stack, all in a native Cocoa app &#8212; no bloated Java IDEs required:</p>
<p><img class="framed" src="http://static.command-tab.com/2011/php-debugging/macgdbp.jpg" alt="MacGDBp debugging a Zend Framework application" /></p>
<h4>What is Nginx?</h4>
<p><a href="http://nginx.org/en/">Nginx</a> is a web server similar to Apache, in that it&#8217;s capable of serving web content over HTTP and HTTPS to visitors.  While Apache is far and away the most common web server &#8212; currently serving up about 64% of all websites on the internet &#8212; it&#8217;s also about a decade older than Nginx.  Being newer, Nginx doesn&#8217;t have all the baggage that Apache has accumulated over that time, and it&#8217;s only gaining in usage, particularly on high-traffic sites.  In addition, Nginx&#8217;s config file format is much saner and less verbose than Apache&#8217;s, simplifying setup.</p>
<p>The only speed bump I&#8217;ve run into with Nginx is a lack of <code>.htaccess</code> support, requiring your URL rewrites to be done in your site&#8217;s configuration file, as opposed to read at runtime. It&#8217;s a different approach, but it helps you centralize your configurations instead of spreading them throughout your project.  This way, environment-related details are kept in the web server environment, and the application code base is all about the application.</p>
<h4>What is PHP-FPM?</h4>
<p><a href="http://php-fpm.org/">PHP-FPM</a> was originally a standalone source code patch that added independent process management to PHP, but is now included as part of the PHP project.  When Apache handles web requests, its PHP module gets loaded even if it&#8217;s not needed, wasting time and memory.  By contrast, under PHP-FPM, processes are launched as demand increases (up to limits we&#8217;ll set), increasing speed and reducing memory usage.</p>
<p>With the setup detailed below, you&#8217;ll be able to run PHP with Nginx and debug server-side code with the simplicity of a Mac application.  A build of MySQL 5.5 is also included, but you could, of course, substitute your preferred database if desired.</p>
<h4>Install Xcode</h4>
<p>Many of the following steps depend on a compiler and other programs that are included with Apple&#8217;s Xcode developer tools.  A version of Xcode is included on your Mac OS X Install DVD, and a more recent version is available on the <a href="http://itunes.apple.com/us/app/xcode/id422352214?mt=12">Mac App Store</a>. Registered Mac and iOS developers can download a copy through the <a href="http://developer.apple.com/">Apple Developer</a> site.  Any version that&#8217;s compatible with your Mac OS X version should suffice.  For this tutorial, I&#8217;m running Mac OS X 10.6.7 and Xcode 4.0.2.  The default install of Xcode should provide everything you need to complete this step.</p>
<h4>Install X11</h4>
<p>Some of the libraries we&#8217;ll use aren&#8217;t part of a default OS X install, but are provided by Apple in their optional X11 distribution.  Insert your Mac OS X Install DVD or USB drive and open the &#8220;Optional Installs&#8221; folder and run the &#8220;Optional Installs.mpkg&#8221; package.  When you get to the customization screen, open the Applications disclosure triangle, and check off X11 before performing the install.</p>
<p><img class="framed" src="http://static.command-tab.com/2011/php-debugging/x11.jpg" /></p>
<h4>Install Homebrew</h4>
<p><a href="http://mxcl.github.com/homebrew/">Homebrew</a> is a package manager for Mac OS X, similar to <code>yum</code> for Linux.  It&#8217;s a faster, lower-overhead alternative to other OS X package managers like MacPorts and Fink.  We&#8217;ll be using it to install a few dependencies.  To get things rolling, open a Terminal window, and run:</p>
<pre class="command">
ruby -e "$(curl -fsSL https://raw.github.com/gist/323731)"</code>
</pre>
<h4>Create a Place to Work</h4>
<p>We&#8217;ll need some easily-accessible place to download source code and build it, so a SourceCache folder in the your Home folder is as good a place as any.</p>
<pre class="command">
mkdir ~/SourceCache
</pre>
<h4>Download and Build Nginx</h4>
<p>Building and installing Nginx is fairly straightforward. We&#8217;ll download the code from the Nginx site, unpack it, install a single dependency using Homebrew, configure, compile, and install:</p>
<pre class="command">
cd ~/SourceCache
curl -O http://nginx.org/download/nginx-1.0.4.tar.gz
tar -xzf nginx-1.0.4.tar.gz
cd nginx-1.0.4
brew install pcre
./configure --prefix=/usr/local/nginx --pid-path=/usr/local/nginx/var/run/nginx.pid --with-http_ssl_module
make
sudo make install
</pre>
<p>Nginx is now installed and ready to run.  With the creation of a small file, you can even set Nginx to run at startup.  Mac OS X uses <a href="http://en.wikipedia.org/wiki/Launchd">launchd</a> to run scripts at the appropriate time, so we&#8217;ll create a simple launchd <a href="http://en.wikipedia.org/wiki/Property_list">plist</a> to start Nginx at boot.</p>
<p>I&#8217;ll be using TextMate&#8217;s built-in <code>mate</code> command to edit files here, but you can use vi, nano, or any other text editor that floats your boat.</p>
<pre class="command">
sudo mate /Library/LaunchDaemons/org.nginx.nginx.plist
</pre>
<p>Then paste in this plist content:</p>
<pre class="code">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;KeepAlive&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;org.nginx.nginx&lt;/string&gt;
    &lt;key&gt;LaunchOnlyOnce&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;NetworkState&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/local/nginx/sbin/nginx&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ServiceDescription&lt;/key&gt;
    &lt;string&gt;Nginx web server&lt;/string&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/var/log/system.log&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</pre>
<h4>Edit Nginx Config Files for PHP</h4>
<p>Nginx is now ready to run on its own, but it still needs to be told where to look for your sites on disk, and how to handle <code>.php</code> files once we install PHP.  We can create some config files now so that they work after the PHP install is complete.  This first config file is a basic Nginx config file.  You&#8217;ll want to replace &#8220;collin&#8221; towards the top of the file with your own OS X short username (which you can see by running <code>whoami</code>), so that Nginx runs as your user.  Or, if you prefer, you can add a new user and group dedicated for Nginx.  Since this is just a local development setup and not a production web server, I didn&#8217;t bother going that route.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/nginx.conf
</pre>
<p>Here is the content for the config file:</p>
<pre class="code">
user collin staff;
worker_processes 2;

events {
    worker_connections 1024;
}

http {
    include mime.types;

    default_type text/plain;
    server_tokens off;

    sendfile on;
    tcp_nopush on;
    keepalive_timeout 10;

    gzip on;
    gzip_comp_level 2;
    gzip_proxied any;
    gzip_types text/plain text/css text/javascript application/json application/x-javascript text/xml application/xml application/xml+rss;

    index index.html index.php;
    include sites-enabled/*.link;
}
</pre>
<p>After we install PHP, Nginx will need to know how to interact with it. Unlike running PHP as an Apache module, PHP-FPM runs its own separate set of processes, and Nginx has no idea they exist unless you tell it about them.  Nginx communicates over the FastCGI protocol, with the master process listening on a local port so it can handle PHP requests from Nginx.</p>
<p>Now we&#8217;ll create an Nginx config file that holds all the details about PHP-FPM.  Note that, at the bottom of this config file, we instruct FastCGI to listen on port 9001 instead of the default port 9000.  This will come into play later when we setup the debugging tools.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/php.conf
</pre>
<pre class="code">
fastcgi_intercept_errors on;

location ~ \.php$
{
    fastcgi_split_path_info ^(.+\.php)(/.+)$;

    fastcgi_param PATH_INFO         $fastcgi_path_info;
    fastcgi_param PATH_TRANSLATED   $document_root$fastcgi_path_info;
    fastcgi_param QUERY_STRING      $query_string;
    fastcgi_param REQUEST_METHOD    $request_method;
    fastcgi_param CONTENT_TYPE      $content_type;
    fastcgi_param CONTENT_LENGTH    $content_length;
    fastcgi_param SCRIPT_NAME       $fastcgi_script_name;
    fastcgi_param SCRIPT_FILENAME   $document_root$fastcgi_script_name;
    fastcgi_param REQUEST_URI       $request_uri;
    fastcgi_param DOCUMENT_URI      $document_uri;
    fastcgi_param DOCUMENT_ROOT     $document_root;
    fastcgi_param SERVER_PROTOCOL   $server_protocol;
    fastcgi_param GATEWAY_INTERFACE CGI/1.1;
    fastcgi_param SERVER_SOFTWARE   nginx;
    fastcgi_param REMOTE_ADDR       $remote_addr;
    fastcgi_param REMOTE_PORT       $remote_port;
    fastcgi_param SERVER_ADDR       $server_addr;
    fastcgi_param SERVER_PORT       $server_port;
    fastcgi_param SERVER_NAME       $server_name;

    fastcgi_read_timeout 600; # Set fairly high for debugging

    fastcgi_pass  127.0.0.1:9001; # Non-default port
    fastcgi_index index.php;
}
</pre>
<p>Nginx is now configured to talk to PHP, but only when we include this particular config file in a particular site&#8217;s config file.</p>
<h4>Configure Local Sites</h4>
<p>At the bottom of the main Nginx config file, we called <code>include sites-enabled/*.link</code>.  We&#8217;ll now create <code>sites-available</code> and <code>sites-enabled</code> folders to hold config files for each site you develop locally.  <code>sites-available</code> will hold all available site config files, and <code>sites-enabled</code> will contain only symbolic links to the config files of enabled sites, allowing you to turn local sites on and off just by linking or unlinking their config files and restarting Nginx.</p>
<pre class="command">
sudo mkdir /usr/local/nginx/conf/sites-available
sudo mkdir /usr/local/nginx/conf/sites-enabled
</pre>
<p>With those two folders available, we&#8217;ll set up an example site that will make use of the PHP config file above. Again, you&#8217;ll want to replace &#8220;collin&#8221; with your own username so Nginx looks in the correct folder for website content.</p>
<pre class="command">
sudo mate /usr/local/nginx/conf/sites-available/example.conf
</pre>
<pre class="code">
server
{
    listen 80;
    server_name example.local;
    root /Users/collin/Sites/example/public;

    access_log /Users/collin/Sites/example/logs/access_log.txt;
    error_log /Users/collin/Sites/example/logs/error_log.txt;

    location /
    {
        index index.php;
        try_files $uri $uri/ /index.php?q=$uri&$args;
    }

    include php.conf;
}
</pre>
<p>Now we can enable the site by symlinking the config file from the sites-available folder into the sites-enabled folder:</p>
<pre class="command">
sudo ln -s /usr/local/nginx/conf/sites-available/example.conf /usr/local/nginx/conf/sites-enabled/example.link
</pre>
<p>While we&#8217;re configuring this site, we should also create the actual folder structure on disk.  The <code>public</code> folder will be where Nginx considers the web-accessible root to be when visited in a web browser, and <code>logs</code> will be where Nginx (and possibly your web application) puts log files.</p>
<pre class="command">
mkdir -p ~/Sites/example/public
mkdir -p ~/Sites/example/logs
</pre>
<p>Finally, we need to make sure that visiting <code>example.local</code> in a browser actually routes to your computer (if you were to visit it right now, more than likely nothing would happen):</p>
<pre class="command">
sudo mate /etc/hosts
</pre>
<p>Add the following line to the <em>end</em> of the file:</p>
<pre class="code">
127.0.0.1    example.local
</pre>
<p>And with that, we&#8217;ve configured a local website for Nginx.</p>
<h4>Install MySQL</h4>
<p>With Homebrew, installing MySQL is the easiest of all the installs we&#8217;ll perform.  This build of MySQL via Homebrew includes a launchd script, which we&#8217;ll copy into the LaunchDaemons folder just like we did with Nginx.</p>
<pre class="command">
brew install mysql
unset TMPDIR
mysql_install_db --verbose --user=`whoami` --basedir="$(brew --prefix mysql)" --datadir=/usr/local/var/mysql --tmpdir=/tmp
sudo cp /usr/local/Cellar/mysql/5.5.10/com.mysql.mysqld.plist /Library/LaunchDaemons/
</pre>
<h4>Install PHP Dependencies</h4>
<p>Unlike Nginx and MySQL, PHP requires quite a few other software packages depending on how you build it. We&#8217;ll install some common ones before proceeding with with PHP build and install.</p>
<pre class="command">
brew install libjpeg mcrypt
</pre>
<pre class="command">
cd ~/SourceCache
curl -O http://download.icu-project.org/files/icu4c/4.6.1/icu4c-4_6_1-src.tgz
tar -xzf icu4c-4_6_1-src.tgz
cd icu
sh source/configure --prefix=/usr/local
gnumake
sudo make install
</pre>
<pre class="command">
cd /usr/local
curl -O ftp://ftp.cac.washington.edu/mail/imap.tar.Z
tar -xzf imap.tar.Z
cd imap-2007e
make osx
mkdir include
ln -s c-client include
mkdir lib
cd lib
ln -s ../c-client/c-client.a libc-client.a
rm /usr/local/imap.tar.Z
</pre>
<h4>Download and Build PHP with PHP-FPM</h4>
<pre class="command">
cd ~/SourceCache
curl -O http://us2.php.net/distributions/php-5.3.6.tar.gz
tar -xzf php-5.3.6.tar.gz
cd php-5.3.6
</pre>
<p>This next configure line is escaped with backslashes and should be run as one giant, single command:</p>
<pre class="command">
./configure --prefix=/usr/local/php \
--mandir=/usr/share/man \
--infodir=/usr/share/info \
--sysconfdir=/private/etc \
--enable-cli \
--with-config-file-path=/usr/local/php/etc \
--with-libxml-dir=/usr \
--enable-xml \
--with-openssl=/usr \
--with-kerberos=/usr \
--with-zlib=/usr \
--enable-bcmath \
--with-bz2=/usr \
--enable-calendar \
--with-curl=/usr \
--enable-exif \
--enable-ftp \
--with-gd \
--with-jpeg-dir=/usr/local/Cellar/jpeg/8c/lib \
--with-png-dir=/usr/X11 \
--enable-gd-native-ttf \
--with-imap=/usr/local/imap-2007e \
--with-imap-ssl \
--with-ldap=/usr \
--with-ldap-sasl=/usr \
--enable-magic-quotes \
--enable-mbstring \
--enable-mbregex \
--enable-json \
--with-mysql=mysqlnd \
--with-mysqli=mysqlnd \
--with-pdo-mysql=mysqlnd \
--with-mysql-sock=/tmp/mysql.sock \
--with-iodbc=/usr \
--enable-shmop \
--with-snmp=/usr \
--enable-soap \
--enable-sockets \
--with-sqlite \
--enable-sysvmsg \
--enable-sysvsem \
--enable-sysvshm \
--enable-wddx \
--enable-fpm \
--with-mhash \
--with-mcrypt \
--with-xmlrpc \
--enable-xmlwriter \
--enable-xmlreader \
--with-iconv-dir=/usr \
--with-xsl=/usr \
--enable-zend-multibyte \
--enable-zip \
--with-pcre-regex=/usr \
--with-pdo-sqlite \
--enable-pdo \
--with-pdo-mysql \
--enable-dba \
--with-freetype-dir=/usr/X11 \
--enable-dom \
--enable-gd-native-ttf \
--enable-posix \
--enable-fileinfo
</pre>
<p>After PHP is done configuring, it&#8217;s time to build it.  This will take some time, so you might consider going and making a sandwich.</p>
<pre class="command">
make
</pre>
<p>Once compiled, PHP can be installed, and default/example config files can be copied to their actual destinations:</p>
<pre class="command">
sudo make install
sudo cp /private/etc/php-fpm.conf.default /private/etc/php-fpm.conf
sudo mkdir /usr/local/php/etc
sudo cp /private/etc/php.ini.default /usr/local/php/etc/php.ini
</pre>
<p>Like Nginx and MySQL, PHP-FPM won&#8217;t start up on its own, so we&#8217;ll again make use of a launchd plist:</p>
<pre class="command">
sudo mate /Library/LaunchDaemons/net.php.php-fpm.plist
</pre>
<p>Here is the content for the PHP-FPM launchd plist:</p>
<pre class="code">
&lt;?xml version="1.0" encoding="UTF-8"?&gt;
&lt;!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"&gt;
&lt;plist version="1.0"&gt;
&lt;dict&gt;
    &lt;key&gt;KeepAlive&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;Label&lt;/key&gt;
    &lt;string&gt;net.php.php-fpm&lt;/string&gt;
    &lt;key&gt;LaunchOnlyOnce&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;NetworkState&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ProgramArguments&lt;/key&gt;
    &lt;array&gt;
        &lt;string&gt;/usr/local/php/sbin/php-fpm&lt;/string&gt;
    &lt;/array&gt;
    &lt;key&gt;RunAtLoad&lt;/key&gt;
    &lt;true/&gt;
    &lt;key&gt;ServiceDescription&lt;/key&gt;
    &lt;string&gt;PHP FastCGI Process Manager&lt;/string&gt;
    &lt;key&gt;StandardErrorPath&lt;/key&gt;
    &lt;string&gt;/var/log/system.log&lt;/string&gt;
&lt;/dict&gt;
&lt;/plist&gt;
</pre>
<h4>Edit PHP-FPM Config File</h4>
<p>We&#8217;ve configured Nginx to communicate with PHP on port 9001, so now we need to configure PHP-FPM to listen for Nginx&#8217;s call.  At the same time, there are a few other options that can be configured such as the number of PHP-FPM processes to run simultaneously.</p>
<pre class="command">
sudo mate /private/etc/php-fpm.conf
</pre>
<p>Here is the content for a basic PHP-FPM config file that, among other things, tells PHP-FPM to listen on port 9001. Again, my username is in the config file, so you&#8217;ll want to replace that with your own.</p>
<pre class="code">
[global]
pid = /usr/local/php/var/run/php-fpm.pid
daemonize = yes

[www]
listen = 127.0.0.1:9001
user = collin
group = staff
pm = dynamic
pm.max_children = 10
pm.start_servers = 5
pm.min_spare_servers = 5
pm.max_spare_servers = 10
pm.max_requests = 500
</pre>
<p>With the config file saved, PHP-FPM is ready to run several worker processes at startup.</p>
<h4>Download and Build Xdebug</h4>
<p>The real key to the PHP debugging puzzle is the Xdebug extension, which is delightfully easy to build:</p>
<pre class="command">
cd ~/SourceCache
curl -O http://www.xdebug.org/files/xdebug-2.1.1.tgz
tar -xzf xdebug-2.1.1.tgz
cd xdebug-2.1.1
/usr/local/php/bin/phpize
/usr/local/php/bin/php-config
./configure --enable-xdebug
make
sudo make install
</pre>
<p>After installing Xdebug, we need to inform PHP that the extension is available and set a few basic options.  We can do this by editing the <code>php.ini</code> file we copied earlier, which contains a myriad of settings for PHP&#8217;s operation.</p>
<pre class="command">
sudo mate /usr/local/php/etc/php.ini
</pre>
<p>Add the following to the end of the file:</p>
<pre class="code">
zend_extension=/usr/lib/php/extensions/no-debug-non-zts-20090626/xdebug.so
xdebug.remote_enable=1
xdebug.remote_host=localhost
xdebug.remote_port=9000
xdebug.remote_autostart=1
</pre>
<h4>Start Everything Up</h4>
<p>One by one, start up each of the services we&#8217;ve installed:</p>
<pre class="command">
sudo launchctl load -F /Library/LaunchDaemons/com.mysql.mysqld.plist
sudo launchctl load -F /Library/LaunchDaemons/net.php.php-fpm.plist
sudo launchctl load -F /Library/LaunchDaemons/org.nginx.nginx.plist
</pre>
<h4>Write a PHP Script</h4>
<p>Just to make sure everything works, create a simple PHP script:</p>
<pre class="command">
mate ~/Sites/example/public/index.php
</pre>
<pre class="code">
&lt;?php

$animals = array('dog', 'cat', 'rabbit');
foreach ($animals as $animal)
{
    print "&lt;p&gt;Hello, $animal&lt;/p&gt;";
}
</pre>
<p>Visit <a href="http://example.local">http://example.local</a> in a browser to see the result.  It&#8217;s not Facebook or Twitter yet, but it&#8217;s enough to step into with a debugger.</p>
<h4>Install an Xdebug Browser Extension</h4>
<p>By default, Xdebug does not automatically debug PHP requests.  It needs to be triggered by a GET or POST parameter of <code>XDEBUG_SESSION_START</code>, or a cookie of the same name, but there is an even easier way.  Install an Xdebug extension for <a href="https://github.com/benmatselby/xdebug-toggler">Safari</a>, <a href="https://addons.mozilla.org/en-US/firefox/addon/58688">Firefox</a>, or <a href="https://chrome.google.com/extensions/detail/eadndfjplgieldjbigjakmdgkmoaaaoc">Chrome</a> to automatically set the Xdebug cookie when you need to debug code.</p>
<h4>Launch MacGDBp</h4>
<p>Now that we have all the tools installed, a PHP debug extension ready, and a browser extension to trigger it all, it&#8217;s time to debug that awesome script.</p>
<p>Launch MacGDBp, and note that it has a main debug window, a Breakpoints window, and a variable inspector.  Take a peek at the Preferences for MacGDBp, and you&#8217;ll note that you can choose to break on the first line of PHP (or wait until a breakpoint is hit).  I like to uncheck that checkbox because some applications have a fair bit of setup code that needs to be skipped each time.  You&#8217;ll also find that the default Xdebug port is set to 9000.  Earlier, we configured PHP-FPM to listen on port 9001, and this is why we made that change &#8212; both tools default to running on port 9000.  And just like in Ghostbusters, it&#8217;s best not to cross the streams.  It would be bad.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/macdbgp-port.jpg" class="framed" /></p>
<p>In MacGDBp&#8217;s Breakpoints window, hit the little &#8220;+&#8221; button in the lower-left to add a new breakpoint, and navigate to the <code>index.php</code> we created above.  Once added, you&#8217;ll see the source code for that script in the upper half of the window.  Click on a line number to add a breakpoint.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/breakpoint.jpg" class="framed" /></p>
<p>With the breakpoint set, flip back to your browser and toggle Xdebug using the installed extension, and reload the page.  You&#8217;ll see your browser appear to hang while loading, as if the page is taking a while to load.  Under the hood, Xdebug has actually paused PHP&#8217;s script execution and started a debug session, ready for you to see what&#8217;s going on.</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/browser-hang.jpg" class="framed" /></p>
<p>Behind the browser window, MacDBGp should have hit the breakpoint, ready to inspect variables or step through code:</p>
<p><img src="http://static.command-tab.com/2011/php-debugging/stepping.jpg" class="framed" /></p>
<p>This works for everything from the simplest scripts like we did here, up through complex web apps with deep frameworks.  Just set a breakpoint, start the code, and step through to see where the execution deviates from your expectations.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2011/06/20/true-php-debugging-with-nginx-and-php-fpm/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Widerbug 1.3.3 Available</title>
		<link>http://www.command-tab.com/2009/05/25/widerbug-133-available/</link>
		<comments>http://www.command-tab.com/2009/05/25/widerbug-133-available/#comments</comments>
		<pubDate>Mon, 25 May 2009 17:56:08 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Hacks]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=482</guid>
		<description><![CDATA[After a long wait, Widerbug 1.3.3 is now available! Thanks to an excellent tutorial, it includes automatic update abilities to keep up with widescreen revisions, as well as the latest Firebug changes. Install it now, or visit the Widerbug page.]]></description>
			<content:encoded><![CDATA[<p>After a long wait, Widerbug 1.3.3 is now available!  Thanks to an <a href="http://www.borngeek.com/firefox/automatic-firefox-extension-updates/">excellent tutorial</a>, it includes automatic update abilities to keep up with widescreen revisions, as well as the latest Firebug changes.  <a href="http://static.command-tab.com/2008/widerbug/widerbug133.xpi">Install it now</a>, or visit the <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug page</a>.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2009/05/25/widerbug-133-available/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Widerbug 1.3.0 for Firefox 3</title>
		<link>http://www.command-tab.com/2009/01/08/widerbug-130-for-firefox-3/</link>
		<comments>http://www.command-tab.com/2009/01/08/widerbug-130-for-firefox-3/#comments</comments>
		<pubDate>Fri, 09 Jan 2009 01:46:27 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=471</guid>
		<description><![CDATA[The Firebug team has been hard at work squashing bugs and making Firefox 3 related improvements, culminating in the release of Firebug 1.3.0 yesterday. Some of the notable changes include: Better debugging performance when dealing with large JavaScript files More reliable &#8216;console&#8217; object for logging Alphabetized DOM properties Added localizations Over 50 bug fixes After [...]]]></description>
			<content:encoded><![CDATA[<p>The Firebug team has been hard at work squashing bugs and making Firefox 3 related improvements, culminating in the release of Firebug 1.3.0 yesterday.  Some of the notable changes include:</p>
<ul>
<li>Better debugging performance when dealing with large JavaScript files</li>
<li>More reliable &#8216;console&#8217; object for logging</li>
<li>Alphabetized DOM properties</li>
<li>Added localizations</li>
<li>Over 50 bug fixes</li>
</ul>
<p>After some minor modifications, Widerbug 1.3.0 is ready for use on your widescreen display in its signature 2-up layout, complete with all the changes from above.  As usual, head over to the <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug</a> page to grab the latest version (please leave comments and note any bugs on that page).</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2009/01/08/widerbug-130-for-firefox-3/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>Learning Cocoa for the iPhone</title>
		<link>http://www.command-tab.com/2008/12/21/learning-cocoa-for-the-iphone/</link>
		<comments>http://www.command-tab.com/2008/12/21/learning-cocoa-for-the-iphone/#comments</comments>
		<pubDate>Sun, 21 Dec 2008 22:50:26 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Apps]]></category>
		<category><![CDATA[Mac]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=467</guid>
		<description><![CDATA[These last few weeks, I&#8217;ve been teaching myself Cocoa to learn what makes Mac OS X and iPhone OS apps tick. While Objective-C is quite a departure from my usual web development world, Cocoa has quickly become one of my favorite languages, as it takes care of much of the drudgery of pure C and [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.command-tab.com/2008/app_xcode.png" class="right" />These last few weeks, I&#8217;ve been teaching myself Cocoa to learn what makes Mac OS X and iPhone OS apps tick.  While Objective-C is quite a departure from my usual web development world, Cocoa has quickly become one of my favorite languages, as it takes care of much of the drudgery of pure C and has plenty of useful frameworks to get your application up and running quickly.  Here are some of the best resources I&#8217;ve found so far:</p>
<ul>
<li><a href="http://cocoadevcentral.com/">Cocoa Dev Central</a> and <a href="http://www.cocoalab.com/?q=becomeanxcoder">Become an Xcoder</a> are both excellent tutorials for beginners, written in a clear, straightforward manner.  They also explain the ins and outs of memory management, which is critical on platforms like the iPhone and iPod touch.</li>
<li>Stanford&#8217;s <a href="http://www.stanford.edu/class/cs193p/cgi-bin/index.php">CS193P lecture notes</a> and examples have proven to be one of the best resources for learning Cocoa, particularly for the iPhone.  These notes and tests offer Cocoa Touch in bite-size chunks, with a little bit of &#8220;on your own&#8221; work to ensure you know your stuff before moving on.</li>
<li><a href="http://www.google.com/codesearch/">Google Code Search</a> is a good last resort for examples of how others are using a small bit of code or a particular class.  For more accurate results, append &#8220;lang:objectivec&#8221; to your search string to narrow results to only Objective-C code.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/12/21/learning-cocoa-for-the-iphone/feed/</wfw:commentRss>
		<slash:comments>6</slash:comments>
		</item>
		<item>
		<title>Consolas Cursor Fix</title>
		<link>http://www.command-tab.com/2008/12/16/consolas-cursor-fix/</link>
		<comments>http://www.command-tab.com/2008/12/16/consolas-cursor-fix/#comments</comments>
		<pubDate>Tue, 16 Dec 2008 19:35:08 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Tips]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=466</guid>
		<description><![CDATA[If you&#8217;ve attempted to use Consolas as your choice programming font on the Mac, you may have noticed (as I did) an odd issue with the font, where your blinking cursor hangs much lower than the current line. Oddly enough, this little issue only seems to affect Mac OS X. Even the Consolas set that [...]]]></description>
			<content:encoded><![CDATA[<p><img src="http://static.command-tab.com/2008/consolas_diff.gif" class="framed right" />If you&#8217;ve attempted to use Consolas as your choice programming font on the Mac, you may have noticed (<a href="/2008/02/19/finding-the-perfect-programming-font/">as I did</a>) an odd issue with the font, where your blinking cursor hangs much lower than the current line.  Oddly enough, this little issue only seems to affect Mac OS X.  Even the Consolas set that ships with Microsoft Office 2008 has the same problem!  Yet, when the same exact font file is used under Windows, the cursor position is correct.</p>
<p>John Gruber <a href="http://daringfireball.net/linked/2008/12/15/bbedit-91" title="Daring Fireball: BBEdit 9.1">mentioned</a> that <a href="http://www.barebones.com/products/bbedit/demo.html">BBEdit 9.1</a> now ships with Consolas as its default font, so I decided to see if it had the same cursor problem I had experienced in the past.  As it turns out, BBEdit&#8217;s version of Consolas works just fine, as seen in the image above.  However, it doesn&#8217;t include the other styles like Consolas Bold, Italic, and Bold Italic.</p>
<p>Through one way or another, the copy of Consolas that ships with BBEdit 9.1 is different than the one that ships with Microsoft Office 2008.  To make system-wide use of the working version, <a href="http://www.barebones.com/products/bbedit/demo.html">download BBEdit 9.1</a>, mount and open the .dmg, and navigate to:</p>
<p>(Control-click BBEdit, and choose &#8220;Show Package Contents&#8221; to get inside the application bundle): <code>BBEdit.app/Contents/Resources/Fonts/consola.ttf</code></p>
<p>Copy consola.ttf from BBEdit&#8217;s &#8220;Fonts&#8221; folder to your own Fonts folder at /Users/you/Library/Fonts, or /Library/Fonts if you want to make it available to everyone who has an account on your computer.  Then, fire up your favorite editor, set Consolas as your preferred fixed-width font, and get coding!</p>
<p><strong>Update:</strong> Bare Bones has apparently changed the version of Consolas that ships with BBEdit versions later than 9.1, and they now have the cursor problem as well.  You can still get the 9.1 demo <a href="http://static.command-tab.com/2009/BBEdit_9.1_Demo.dmg">here</a>, which contains the working font.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/12/16/consolas-cursor-fix/feed/</wfw:commentRss>
		<slash:comments>5</slash:comments>
		</item>
		<item>
		<title>iPhone NDA Dropped</title>
		<link>http://www.command-tab.com/2008/10/01/iphone-nda-dropped/</link>
		<comments>http://www.command-tab.com/2008/10/01/iphone-nda-dropped/#comments</comments>
		<pubDate>Wed, 01 Oct 2008 17:19:08 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Apps]]></category>
		<category><![CDATA[iPod]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=457</guid>
		<description><![CDATA[After hearing the cries of thousands of upset iPhone app developers, Apple has lifted the non-disclosure agreement covering (released) iPhone software. Developers can now freely talk about the inner workings of their applications, write books, publish blog entries, etc. Communicating developers means solutions to common problems get solved and shared, resulting in better software, making [...]]]></description>
			<content:encoded><![CDATA[<p>After hearing the cries of thousands of upset iPhone app developers, Apple has <a href="http://developer.apple.com/iphone/program/">lifted the non-disclosure agreement</a> covering (released) iPhone software.  Developers can now freely talk about the inner workings of their applications, <a href="http://www.pragprog.com/titles/amiphd/iphone-sdk-development">write</a> <a href="http://www.amazon.com/iPhone-Developers-Cookbook-Building-Applications/dp/0321555457/ref=pd_bbs_sr_1?ie=UTF8&#038;s=books&#038;qid=1222881181&#038;sr=8-1">books</a>, publish blog entries, etc.  Communicating developers means solutions to common problems get solved and <a href="http://furbo.org/2008/10/01/redacted/">shared</a>, resulting in better software, making the iPhone and iPod Touch platform better as a whole.</p>
<p>For some time I&#8217;ve been worried that the NDA was going to remain in place indefinitely, silencing those who Apple needs the most, but it appears Apple has finally taken a positive action to help their App Store environment grow further.  If you thought there was some cool stuff on the App Store now, just give it time&#8230;</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/10/01/iphone-nda-dropped/feed/</wfw:commentRss>
		<slash:comments>1</slash:comments>
		</item>
		<item>
		<title>Widerbug 1.2.1 for Firefox 3</title>
		<link>http://www.command-tab.com/2008/09/13/widerbug-121-for-firefox-3/</link>
		<comments>http://www.command-tab.com/2008/09/13/widerbug-121-for-firefox-3/#comments</comments>
		<pubDate>Sat, 13 Sep 2008 21:40:41 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=452</guid>
		<description><![CDATA[For those eagerly anticipating Widerbug: Widescreen Firebug for Firefox 3, the wait is over. Firebug 1.2.1 was just recently released, and I&#8217;ve merged the Widerbug modifications into the latest version and tested them under Windows XP and Mac OS X on Firefox 3.0.1. Head on over to the Widerbug page to grab the latest version [...]]]></description>
			<content:encoded><![CDATA[<p>For those eagerly anticipating <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug: Widescreen Firebug for Firefox 3</a>, the wait is over.  Firebug 1.2.1 was just recently released, and I&#8217;ve merged the Widerbug modifications into the latest version and tested them under Windows XP and Mac OS X on Firefox 3.0.1.</p>
<p>Head on over to the <a href="/2008/01/19/widerbug-widescreen-firebug/">Widerbug</a> page to grab the latest version and get coding, widescreen style!</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/09/13/widerbug-121-for-firefox-3/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>fmTuner: A Last.fm Plugin for WordPress</title>
		<link>http://www.command-tab.com/2008/09/06/fmtuner-a-lastfm-plugin-for-wordpress/</link>
		<comments>http://www.command-tab.com/2008/09/06/fmtuner-a-lastfm-plugin-for-wordpress/#comments</comments>
		<pubDate>Sun, 07 Sep 2008 04:43:16 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Programming]]></category>
		<category><![CDATA[Projects]]></category>
		<category><![CDATA[WordPress]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=448</guid>
		<description><![CDATA[fmTuner is a WordPress plugin for retrieving song details from your Last.fm profile and publishing them anywhere in your WordPress theme. It provides options for choosing among your Recent, Loved, or Top tracks, as well as tools to adjust the update frequency and appearance: Of particular note is the customizable Display Format option. Using simple [...]]]></description>
			<content:encoded><![CDATA[<p>fmTuner is a WordPress plugin for retrieving song details from your <a href="http://www.last.fm">Last.fm</a> profile and publishing them anywhere in your WordPress theme.  It provides options for choosing among your Recent, Loved, or Top tracks, as well as tools to adjust the update frequency and appearance:</p>
<p><img src="http://static.command-tab.com/2008/fmtuner_settings.gif" alt="Settings - fmTuner: A Last.fm Plugin for WordPress" class="framed" /></p>
<p>Of particular note is the customizable Display Format option.  Using simple tags like <code>[::artist::]</code> and <code>[::image::]</code> intermixed with regular HTML, you can tweak your Last.fm tracks exactly how you like, or however your WordPress theme requires.  You have full control!  </p>
<h4>Download</h4>
<p><a href="http://wordpress.org/extend/plugins/fmtuner/">Download the latest fmTuner from WordPress.org</a></p>
<h4>Requirements</h4>
<ul>
<li>WordPress 2.7 or newer.</li>
<li>PHP 5 or newer</li>
<li>Basic knowledge of PHP, HTML, and WordPress.</li>
</ul>
<h4>Installation</h4>
<ul>
<li>Upload fmtuner.php to a directory inside <code>/wp-content/plugins/</code> directory.  For example: <code>/wp-content/plugins/fmtuner/fmtuner.php</code></li>
<li>Ensure <code>/wp-content/plugins/fmtuner/</code> is writable by your webserver.</li>
<li>Activate the plugin through the &#8220;Plugins&#8221; menu in WordPress.</li>
<li>Set up options in the &#8220;Settings&#8221; menu in WordPress.</li>
<li>Place the PHP code <code>if(function_exists('fmtuner')) { fmtuner(); }</code> in your templates, to call up fmTuner.</li>
</ul>
<h4>Release History</h4>
<ul>
<li><strong>fmTuner 1.1</strong><br />Released on Feb. 1, 2010<br />Added a placeholder image field to the fmTuner Settings page, which will be substituted when tracks have no artwork.<br />Tested under WordPress 2.9.1.</li>
<li><strong>fmTuner 1.0.8</strong><br />Released on Nov. 3, 2009<br />Fixed a bug with the [::url::] fmTuner tag that caused Last.fm links to appear incorrectly.</li>
<li><strong>fmTuner 1.0.7</strong><br />Released on Apr. 23, 2009<br />Tracks with foreign character sets now display more accurately.</li>
<li><strong>fmTuner 1.0.6</strong><br />Released on Mar. 29, 2009<br />You can now display more than 10 Recent Tracks, and you should get fewer tracks without artwork.</li>
<li><strong>fmTuner 1.0.5</strong><br />Released on Mar. 22, 2009<br />Track information is now properly escaped to handle $ signs, quotes, and other non-alphanumeric characters.</li>
<li><strong>fmTuner 1.0.4</strong><br />Released on Dec. 14, 2008<br />Made minor tweaks for fmTuner Settings page under WordPress 2.7.</li>
<li><strong>fmTuner 1.0.3</strong><br />Released on Nov. 15, 2008<br />By request, a [::number::] fmTuner tag has been added, which emits a sequential number for each track (starting at 1).  This is particularly useful for CSS and JavaScript display purposes.</li>
<li><strong>fmTuner 1.0.2</strong><br />Released on Oct. 5, 2008<br />Added a cURL-based alternative to file_get_contents to hopefully resolve &#8220;URL file-access is disabled&#8221; issues.  If allow_url_fopen is disabled in the php.ini, cURL will be used to fetch the Last.fm feed instead.</li>
<li><strong>fmTuner 1.0.1</strong><br />Released on Sept. 9, 2008<br />Added better failure checking and informational messages, removed development code, and updated instructions.</li>
<li><strong>fmTuner 1.0</strong><br />Released on Sept. 6, 2008<br />Initial release.</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/09/06/fmtuner-a-lastfm-plugin-for-wordpress/feed/</wfw:commentRss>
		<slash:comments>93</slash:comments>
		</item>
		<item>
		<title>Form Jig 1.0</title>
		<link>http://www.command-tab.com/2008/06/05/form-jig-1-0/</link>
		<comments>http://www.command-tab.com/2008/06/05/form-jig-1-0/#comments</comments>
		<pubDate>Fri, 06 Jun 2008 04:41:49 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[Misc]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/?p=422</guid>
		<description><![CDATA[In woodworking, metalworking, and other crafts where exact reproduction of a given piece is crucial, a common tool is a &#8220;jig.&#8221; A jig is effectively a template for creating a copy. For example, when a door key is duplicated, the cutting machine uses the existing key as a jig, tracing the hills and valleys on [...]]]></description>
			<content:encoded><![CDATA[<p>In woodworking, metalworking, and other crafts where exact reproduction of a given piece is crucial, a common tool is a &#8220;jig.&#8221;  A jig is effectively a template for creating a copy.  For example, when a door key is duplicated, the cutting machine uses the existing key as a jig, tracing the hills and valleys on its edge to produce an identical version.</p>
<p>Along the same line, when developing a web application or just a simple page, HTML forms require that data be typed in and submitted.  This process will repeat as the server-side code is refined, and typing the same data over and over gets old as soon as the second iteration.  &#8220;Don&#8217;t Repeat Yourself&#8221;, or &#8220;DRY&#8221;, is a common philosophy for writing better code, and should extend to testing your forms, as well.  Save your typing for code.</p>
<p>Form Jig is a small Firefox extension for replicating HTML form data and server-side code.  To use it, fill out a form on a page, click the red Capture button in your Firefox status bar, then submit the form.  Upon returning for further testing, click the green Replay triangle to populate the form just as you left it.  Form data is kept around until the current Firefox window is closed, and can be used between tabs. <a href="https://addons.mozilla.org/en-US/firefox/addon/7497">Install Form Jig from Mozilla Addons</a>.</p>
<p>Suggestions are welcomed, and bug reports will be attended to.</p>
<p><strong>Update:</strong> Version 1.0.1 fixes a bug related to checkboxes and radio buttons.  The updated plugin should appear on addons.mozilla.org shortly (linked via the above button), but still hasn&#8217;t passed Mozilla&#8217;s &#8220;nomination&#8221; for public consumption.</p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/06/05/form-jig-1-0/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>jQueryize Bookmarklet</title>
		<link>http://www.command-tab.com/2008/03/13/jqueryize-bookmarklet/</link>
		<comments>http://www.command-tab.com/2008/03/13/jqueryize-bookmarklet/#comments</comments>
		<pubDate>Fri, 14 Mar 2008 03:45:20 +0000</pubDate>
		<dc:creator>Collin</dc:creator>
				<category><![CDATA[NerdLab]]></category>
		<category><![CDATA[Programming]]></category>

		<guid isPermaLink="false">http://www.command-tab.com/2008/03/13/jqueryize-bookmarklet/</guid>
		<description><![CDATA[While developing web applications at my day job, I've come to rely quite heavily on the jQuery JavaScript library. In fact, it's the client-side backbone upon which our company software is built. It comes as no surprise, then, that I sometimes find myself poking around in others' web application code with Firebug (or Widerbug) and [...]]]></description>
			<content:encoded><![CDATA[<p>While developing web applications at my day job, I've come to rely quite heavily on the <a href="http://jquery.com/">jQuery</a> JavaScript library.  In fact, it's the client-side backbone upon which our company software is built.  It comes as no surprise, then, that I sometimes find myself poking around in others' web application code with <a href="https://addons.mozilla.org/en-US/firefox/addon/1843">Firebug</a> (or <a href="http://www.command-tab.com/2008/01/19/widerbug-widescreen-firebug/">Widerbug</a>) and wishing I had jQuery at my immediate disposal to perform manipulations with its succinct syntax and practical API.</p>
<p>A day ago, I stumbled upon the answer I was looking for on the <a href="http://www.learningjquery.com/2006/12/jquerify-bookmarklet">Learning jQuery</a> blog: a browser-ready jQuery-loading bookmarklet.  For the uninitiated, a bookmarklet is a standard bookmark placed in your Bookmarks Bar, except it runs some JavaScript code instead of pointing your browser at a web destination.  In this case, the bookmarklet manually fetches and inserts jQuery into the current page.  I've modified the following version slightly to flash "jQuery Loaded" on the page when the load is complete, using the just-loaded jQuery, naturally.</p>
<p>To install the tool, just drag the following link to your Bookmarks Bar, and click it to temporarily install jQuery on whatever page you're visiting: <b><a href="javascript:void(function(){var s=document.createElement('script');s.src='http://code.jquery.com/jquery-latest.js';s.onload=function(){var h=$('<span>jQuery Loaded</span>');h.css({backgroundColor:'red',border:'5px solid white',color:'white', fontSize:'24px',fontWeight:'bold',fontFamily:'Verdana, sans-serif',position:'fixed',top:'100px',left:'100px;', padding:'10px'});$('body').append(h);h.fadeOut(1000,function(){h.remove();});}; document.getElementsByTagName('head')[0].appendChild(s);}())">jQueryize</a></b></p>
]]></content:encoded>
			<wfw:commentRss>http://www.command-tab.com/2008/03/13/jqueryize-bookmarklet/feed/</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
	</channel>
</rss>

