Setting up Debugging in MAMP Pro 3.3 and PHPStorm 9

First off, make sure that you have the latest versions of MAMP Pro and PHPStorm installed. At the time of this writing, that is MAMP 3.3 and PHPStorm 9.

  1. In MAMP’s PHP tab, check the option for debugger.
  2. Edit /Applications/MAMP/bin/php/php<version>/conf/php.ini. I am currently using 5.4.42.
    1. In the “; Extensions” section, add:
    2. Toward the bottom, in the [xdebug] section, add:
  3. Restart your web server in MAMP Pro.
  4. In PHPStorm, go to File → Default Settings…
  5. Go to Languages & Frameworks → PHP.
  6. Under “Interpreter:”, click …
  7. Click + to add a new interpreter, and for PHP executable, find the location to the PHP binary you’re using in MAMP.
  8. Click OK, then select that as the interpreter.
  9. Make sure “PHP language level” is set appropriately (in this case, 5.4), and click OK.
  10. Expand the PHP section in the “Default Preferences” window, click on Debug, make sure the Xdebug port is set to 9000, and click OK.
  11. Back in the main PHPStorm window, go to Run → Edit Configurations…
  12. Click the + button in the upper-left, then click “PHP Web Application”
  13. Under Server, click the ellipsis.
  14. Click the + in the upper-left of the Servers dialog to add a new server.
  15. Name it whatever you wish, and for Host use localhost, and make sure port is set to 80 (or whatever your MAMP port is set to).
  16. Click OK, and select that as your Server on the “Run/Debug Configurations” screen.
  17. Make sure the Browser is set to your browser of choice, and click OK.

Now you should be good to go. Here is an example video of how to debug in PHPStorm.

Posted in Tools Tagged , ,

Getting Composer Working in OSX with MAMP

I just had a bit of a run-around trying to get Composer working in my local MAMP environment, so I thought I’d share a few of the extra steps I had to go through.

First off, you need to get your command-line interpreter (CLI) to recognize MAMP’s version of PHP, not the built-in. So open a Terminal window, type “sudo nano ./bash_profile” and there should be a line that looks something like this:

export PATH=/opt/local/bin:/opt/local/sbin:$PATH

You need to edit that to add the MAMP version of PHP before /opt/local/bin, like so (this is for PHP 5.3.14):

export PATH=/Applications/MAMP/bin/php/php5.3.14/bin:/opt/local/bin:/opt/local/sbin:$PATH

You can confirm which PHP install is running on the CLI by executing “which php” (you may need to open a new terminal window). Then when installing Composer you need to make sure to set detect_unicode to Off. You can do that and install Composer all at once like this:

$ curl -sS | php -d detect_unicode=Off

That will download Composer to your current directory. After that, we’ll want to move it to a more readily accessible location and set up an alias for it so that you can just use “composer <foo>” from the CLI:

$ sudo mv composer.phar /usr/bin/
$ nano ~/.bash_profile

Then add the following line to your .bash_profile file:

$ alias composer="php /usr/bin/composer.phar"

After that, you should be all set!

Before figuring this out, I was trying to install Laravel, which involved installing Composer, and running into problems like “openssl extension is missing” and “The detect_unicode setting must be disabled.” So hopefully if you’re running into those problems in an OSX/MAMP environment, this will help you.

Posted in Tools Tagged , , ,

Git Auto-Pull Broken, Fix Found

At my work, we have a Git auto-pull script set up for development branches, so that whenever a developer pushes a commit, the development server will automatically pull in those changes.  Here is a basic example of that sort of script:


 function syscall ($cmd, $cwd) {
    $descriptorspec = array(
            1 => array('pipe', 'w') // stdout is a pipe that the child will write to
    $resource = proc_open($cmd, $descriptorspec, $pipes, $cwd);
    if (is_resource($resource)) {
            $output = stream_get_contents($pipes[1]);
            return $output;

// GitHub will hit us with POST (
if (!empty($_POST['payload'])) {
	// pull from origin
	$result = syscall('git pull 2>&1', getcwd());
	// send us the output
	mail('', 'Git auto-pull', $result);

However, sometime earlier this week, that started failing.  I added some debugging code to have it email me the result of syscall, but that was empty.

The Fix

The fix was as simple as adding the following line of code near the top:


It was also useful to change the Git command like so, to have errors go to stdout so that they would also be included in the $result output:

$result = syscall('git pull origin master 2>&1', '/var/www/website/directory');

How I Investigated

First, I went to the command line and executed “sudo -u apache _git_pull.php”.  That gave the error, “Result: fatal: unable to access ‘/root/.config/git/config’: Permission denied.”  Doing a bit of Google searching, I found out that is because the HOME environment variable wasn’t set correctly for the Apache user.  So to correct this, I just added putenv(“HOME=”.getcwd()); to the top of the script.

Posted in Code Snippets, Tools, Web Design Tagged , , , ,

How to Correctly Revert a Bad Merge in Git

Let’s say we have this situation:

--o---o---o---M---x---x        master
      --A---B                  my-dev-branch

A and B are on development branch “my-dev-branch,” which actually had some bugs in it. M is the merge that brings these premature changes into master, x are changes unrelated to what the side branch did (so maybe some bug fixes, other merges, or whatever).

So we need to get rid of M. On your local development environment, you need to first pull in all changes from origin (Bitbucket, or wherever your remote repo is), make sure you are on master, then execute the following:

$ git revert -m 1 <M>

Where <M> is the SHA hash of merge M. Then commit and push that. At this point, we have:

--o---o---o---M---x---x---M^          master
      --A---B                         my-dev-branch

We’re all good now — disaster averted!

However, when we make fixes to my-dev-branch and want to merge back in, we can’t just re-merge the branch. This is because M^ undoes the code changes from the other branch, but the history remains intact — git still knows that my-dev-branch was merged into master at some point. So if you make changes C and D like so:

--o---o---o---M---x---x---M^---x---x   master
      --A---B---------------C---D      my-dev-branch

And then try to merge back into master, only C and D will come over.

So how do we merge the branch back in? We have to first undo M^ (basically, revert the revert), and then merge our branch in, like so:

$ git revert <M^>
$ git merge my-dev-branch


This post was a distilled version of this post by Linus Torvalds on how to revert a faulty merge.

Posted in Tools Tagged , ,

Improving PHP Development Workflow Efficiency With Sublime Text 2

I’ve recently been turned on to Sublime Text 2, and I’m loving it.  Jeffrey Way has done an excellent job of detailing exactly how you can improve your workflow with it, here. However, that link has a lot of videos, and they take a while to watch, so I will give a minimal crash-course in using Sublime Text 2 to develop PHP.

Why Is It Awesome?

It’s a very light editor, it’s incredibly fast (seriously, I have never used a more responsive editor), and… yadda yadda. You’ve heard it all before with the alternatives. Here are the two real killer features of this editor that make it shine, in my opinion:

  1. “Goto anything.” By pressing Ctrl+P (Mac: ⌘+P), you get a quick search box that allows you to look for anything — settings, files in the current project, etc. It does this via ultra-quick “fuzzy search,” and I can’t tell you how useful I find this. Now instead of having to go to the file pane, clicking to open /includes, then /modules, then foo.php, I can just Ctrl+P, type foo (maybe even just “fo”), and press enter. Think of how many files you open every day, and how much focus you waste trying to remember where they are; focus that could better be spent on your code.
  2. Snippets. Basically, if you type “if”, an option will pop up to create an if {} block for you. Other IDEs have this sort of thing, but Sublime does it one better. After you have it enter a snippet, it automatically puts your cursor where the first parameter/entrypoint/whatever is, and then if you press Tab it will go to the next. This is best shown in this video. Once you get accustomed to using snippets (and even creating your own), this will save you so much time.

It also has lots of extensions, which you can take a look into as well. Sublime Package Control is absolutely a must-have — with it, you can look up and install other extensions in about 2 seconds time (that is not an exaggeration). I also suggest SublimeCodeIntel which allows for better autocomplete (e.g. your own project’s functions can be autocompleted), as well as some other things, but the expanded autocomplete is what I use it for. I also use Sublime Tortoise, a TortoiseSVN plugin for Sublime, but due to one of the below peeves, it actually isn’t that useful.

What’s It Missing?

Let’s not kid ourselves: Sublime Text 2 is not a full IDE. It can’t (reliably) got to the definition of a function defined in a different file than you are currently looking at, and it doesn’t show function parameter hints. You can’t do step debugging. And so forth. If you want an IDE that does all of that, I suggest NetBeans (also cross-platform compatible).

One big pet peeve of mine is that when editing a file, the folder view on the left doesn’t highlight the file you’re editing. This is mainly annoying because when I want to perform a commit (via Sublime Tortoise), that means I have to go through the trouble of finding the file in the left pane, right-clicking, and committing. This seriously interrupts my workflow, to the point where I generally just keep a file browser window open and use TortoiseSVN for anything SVN-related.

How To Set It Up

  1. Download it and install it.
  2. Go to Sublime Package Control and follow the (very brief, very easy) instructions there. Bonus: nothing to download, just copy and paste some text! Honestly, I’m not sure why they don’t just include Package Control by default in Sublime.
  3. Install whatever other plugins you want through Package Control. I pointed out a few I like above. I suggest only installing one or two to begin with, then play around with Sublime a little before delving into more.

Other Resources

Here are a few links that can help you dig deeper into Sublime.

  • Perfect Workflow in Sublime Text 2 — Linked in the top of this post. Lots of videos showing you exactly how to do various things with Sublime, by Jeffrey Way. Of particular note is the snippets tutorial.  I definitely recommend checking out these tutorials when you’ve got the time to do so; they also include lots of little tips for Sublime to help you save a second here or there. And that’s what workflow optimization is all about.
  • Setting Up Sublime Text 2 for PHP Development — Stuart Herbert’s take on how to set up Sublime for good PHP development workflow.

Posted in Tools Tagged , , , , , , ,

Tutorial: AJAX Through PHP and jQuery

Here is a simple example of using AJAX with PHP and jQuery. The AJAX just outputs the GET variables that were sent back to the page, and the jQuery handler adds that to the div with id of “content”. You might also want to check out the jQuery.ajax() documentation after looking over this example.

Caveat 1: Normally when doing AJAX, I’d recommend having the “server” page (that accepts AJAX requests and returns a response) be a separate PHP file, but for ease of explanation I’ve included everything in one big file here.

Caveat 2: In production you’ll also probably want to use POST instead of GET, and send data over an https connection for security. The GET data itself is still encrypted when it goes over https, but it is kept in plaintext in server logs, and your browser’s history, so the data in there is not actually all that secure.

  * This page just demonstrates a simple AJAX call using jQuery.
  * by: Mike Todd (

// Check to see if we are doing something AJAX-y
if ($_GET['ajax_call'] == 1) {
 	// Connect to database
 	try {
		$db = new PDO("mysql:host=localhost;dbname=db_here", "db_user", "db_pass");
	} catch (PDOException $e) {
		die(json_encode(array('status'=>'fail', 'message'=>'Could not connect to database: '.$e->getMessage())));

	// Do some database stuff -- insert, select, or whatever...

	sleep(1); // DEBUG: Add in a delay, just for testing purposes so you can see the "loading" icon

	// Return some JSON data
	$ret = array('status'=>'success', 'message'=>'GET variables sent: '.print_r($_GET, true));
	echo json_encode($ret); // Have PHP encode the result as JSON, which jQuery is expecting due to dataType parameter
	die(); // Stop output here since we've handled the AJAX response

    <script type="text/javascript" src=""></script>
    <script type="text/javascript">
    function doAjax() {
        //generate the parameters for the AJAX call
        var send_data = 'ajax_call=1&text=' + encodeURIComponent($('#send_message').val());

            url: "<?php echo basename($PHP_SELF); ?>", // Post to the current page (in production you should send to another page)
            type: "GET",
            data: send_data,
            dataType: "json",  // Return data type
            cache: false,
            success: function (data) {

                $('#loading').hide();  // We've got the result, so hide the "loading" icon

                if (data['status'] == 'success') {
                    // Add the content retrieved from ajax and put it in the #content section
                    $('#content').append('<br />'+data['message']);
                } else {
                    // Maybe add some error handling here
                    $('#content').append('<br /><font color="red">Failure:</b> '+data['message']);


 Some text: <input id="send_message" type="text_field" value="test" />
 <button id="submit_input" onclick="$('#loading').show(); doAjax();">Click me</button>
 <img id="loading" style="display: none;" src="" alt="" />
 <span style="text-decoration: underline;">Messages</span>


Posted in Code Snippets, Web Design Tagged , , ,

Nearly-Free Cell Phone Service?

This isn’t really related to coding or development, but what the hell — thought I’d write about it anyway.

One of the founders of Skype is starting a company called  It’s a $99 sleeve for your iPhone 4/4S which provides some extra battery life and an Internet connection.  You get the first 500 MB per month for free, and pay $10 for every gigabyte after that.

So my first thought was: could I just cut off my cell service entirely, and use Skype for phone service over the data connection? I hardly ever use the actual phone anyway, and when I do I’m almost always at home where I have WiFi.  Looking at my last month’s data plan usage, I was only around 350 MB (since again, I’m almost always near a WiFi connection).  So theoretically, I could have just canceled my cell phone plan.  Even if I used triple the data and made a fair number more phone calls, I’d still be looking at $10 for the data, plus $3/mo for unlimited calling to US and Canada through Skype.

That’s almost $100/month savings, so the FreedomPop sleeve would nearly pay for itself in the very first month, and I’d be saving $1200 per year.  If a new contract-less phone costs $600 and you want to upgrade once every 2 years, that’s still an average savings of $1000/year (assuming that same phone would cost $200 with a 2-year contract).

FreedomPop is not yet out, but when it comes out, I am seriously considering doing this.  I think this is where cell phones are going anyway — in fact, I’ve heard that some cell providers are going to experiment with offering data-only plans.

I’ve actually considered doing something like this before — ditching my phone in favor of my iPad and just using Skype with that.  I actually tested this last year in Costa Rica. The house I stayed in had WiFi, so I just used Skype there instead of getting an international call plan, and it worked like a charm.  However, the iPad isn’t handy to carry around like a phone is, so I never made that leap.  But with things like the FreedomPop sleeve coming out… I am very tempted.

As another note, Google Voice and Skype still don’t handle picture messages, so one downside of this plan would be that there is no good way (yet) to get SMS messages, unless you’re on an iOS device and sending to another iOS device (in which case you will be using iMessage).

Update (2013-05-17): FreedomPop has partnered with Sprint for 4G service.  This does cost a bit extra ($4/mo), but it has coverage wherever Sprint has coverage. The mobile hotspots that allow for this are back-ordered, but I have placed myself in queue for one.  The FreedomPop sleeve is still currently tied up in FCC approval, but the hotspots have been available for a while now.

Posted in Technology Tagged , , ,

Machine Learning for Automated A/B Testing

Steve Hanov posted this interesting article about automated A/B testing. Normally in A/B testing, you create two (or more) variations of something — whether that be button color, placement, text, or even two completely different versions of a page (though it’s usually done for smaller/subtler variations than that) — and record how well each version performs 1.  After letting the test run for a while, you look at your metrics and determine which version was best, and you update your code to use that on the live site.

Well, Steve took that idea and added some machine learning to it. The article describes the details, but the basic concept is that as your site is collecting data, it starts showing the “best” version to customers more often, so there is no code updating necessary. It provides for a nearly-instantaneous feedback loop, and no coding changes are required to switch to the “best” version. I imagine that at some point you might want to get rid of the A/B component (otherwise some percent of your users will be seeing a non-standard version of the site), but I can see an argument being made to never get rid of it, too.

I like this methodology, and I believe we will be trying it out some at work.


  1. “Performs” can have different meanings, depending on what you’re looking for.  It can mean how often the link gets clicked, how many sales result from each variation, how long people look at a page, or whatever other metric you choose to use.
Posted in Web Design Tagged ,

Post the First: Turbocharging MySQL Queries With Memcached

This is a function which I created that leverages memcached to perform automatic caching of MySQL queries. This assumes that you have created functions memcache_get, memcache_set, and memcache_delete — personally, I just have these as wrapper functions for the native memcached functions, with some extra bells and whistles (attempts to connect to memcached server if not already connected, that sort of thing).

This is not quite a drop-in replacement for mysql_query, but it’s close — instead of using mysql_query() and then while (mysql_fetch_array()), you can use memcached_query() and then a foreach(). There are, however, a few other caveats:

Caveat 1: The “is this query currently being re-cached by someone else?” check and set operations are separate. In a very high-concurrency environment, this means that multiple threads could attempt to regenerate the same query simultaneously. I believe there is a way to resolve this using Memcached::cas(), but I found the documentation for that function a bit confusing, and it’s not that important for our environment anyway. If you know a way to do this more properly, let me know!

Caveat 2: This function assumes that queries will take no longer than 5 seconds. This should be a fairly safe assumption, but if not, then the function would need to be modified.

Caveat 3: There is no way to manually invalidate the cache for a given query. If you need to do this, I suggest making a separate function to get the hash for a given query.

* Looks for results of given query in cache, or runs query if not in cache.
* Stores 500 rows max (since these results are being stored in memory, we don't
* want to be storing thousands of rows).
* Has mechanism to prevent cache stampedes -- detects if another thread is
* already regenerating this query, and if so waits a bit for it to finish.
* @param string $sql_select_query The SELECT query to perform.
* @param int $cache_length Length to keep query results in cache (seconds)
* @param string $custom_key Custom memcache key to use for this query; will
* default to 'query-'.md5($sql_select_query) if not specified.
* @param int $max_timeout_ms In case of cache contention, max time to wait for
* other "thread" to finish executing
* @param string $memcache_var_name Name of the global Memcached object to use for this
* operation.
* @param string $db_link Name of the variable to pass to tep_db_query.
* @return Array of results (or -1 if not cached and timed out waiting for
* another thread to generate cache)
function memcached_query($sql_select_query, $cache_length = 3600,
        $custom_key = NULL, $max_timeout_ms = 1000, $limit_results = 500,
        $memcache_var_name = 'memcache', $db_link = 'db_link') {
    global $$memcache_var_name;
    // Make sure this is a select statement; cannot cache updates/inserts
    if (strtolower(substr($sql_select_query, 0, 6)) != 'select') {
        return -1;
    // Limit to 500 results if no limit specified
    // TODO: Account for "limit" happening to be in query string somewhere else.
    if (!stristr($sql_select_query, 'LIMIT')) {
        $sql_select_query .= ' LIMIT '.(int)$limit_results;
    $key = $custom_key;
    if ($key === NULL) {
        $key = 'query-'.md5($sql_select_query);
    $ret_array = memcache_get($key, true, $memcache_var);
    if ($ret_array !== false) {
        return $ret_array;
    } else {        
        // Check and see if anyone else is caching this
        $caching = memcache_get('query-running-'.md5($sql_select_query), true, $memcache_var);
        // If query not already running, or memcached disabled, run query again
        if (!is_object($$memcache_var)
            || $$memcache_var->getResultCode() == Memcached::RES_NOTFOUND
            || ($_GET['force_recache'] == 1 && customer_is_admin())
            ) {           
            // Set 'caching' flag, but it expires after 5s, in case this process
            // is interrupted mid-regen
            memcache_set('query-running-'.md5($sql_select_query), '1', 5);
            $query = tep_db_query($sql_select_query, $db_link);
            $rows = tep_db_num_rows($query);
            $ret_array = array();
            $count = 0;
            if ($rows > 0) {
                while ($count < $limit_results && $value = tep_db_fetch_array($query)) {
                    $ret_array[] = $value;
            // Store result in cache
            memcache_set($key, $ret_array, $cache_length, true, $memcache_var);
            // Un-set "regenerating cache" flag
            memcache_delete('query-running-'.md5($sql_select_query), true, $memcache_var);
        } else {
            // Someone else already caching; retry for a bit
            $retry_count = 0;
            $step = 100000; // Try another read every 0.1s (100,000 milliseconds)
            do {
                $ret_array = memcache_get($key, true, $memcache_var);

            while ($$memcache_var->getResultCode() == Memcached::RES_NOTFOUND && $retry_count*$step/1000 < $max_timeout_ms) {};
            if ($$memcache_var->getResultCode() == Memcached::RES_NOTFOUND) {
                return -1;
        return $ret_array;

Posted in Code Snippets Tagged , , , ,