Grace Hopper UNIVAC

Brogrammers: Women Invented Your Job

Originally appeared as “An Open Letter to Brogrammers” in Franklin Veaux’s Journal. I wanted to share it, but it wasn’t PG-13, so I’m reposting here with edits.

Computer programming is a tough job. It’s not for the faint of heart or the fair of sex. It’s grueling, high-stress work, demanding that you sit on a comfortable chair in an air-conditioned office for hours on end, typing on a keyboard while looking at a monitor. Women just aren’t rugged enough for that.

Plus, as everyone knows, women can’t code. At best, they can maybe contribute in their small way to large open-source projects, but really, they’re much better suited for accessorizing PowerPoint presentations written by real coders–manly coders.

If this is the world you live in, bro, I’m afraid I have some really bad news for you. Continue reading

Deep linking into an iframe, cross-domain

Why would you want to do this? My use case was a gallery application where we needed to deep-link to a specific gallery entry. Alas, the gallery would be iframed. Yes, iframes should be avoided, but sometimes in real-life you have to just deal with it.

Imagine my surprise when I discovered that passing the parent window.location object into an iframe across domains is not only possible, but is easy and works in most browsers, down to IE8. Continue reading

Video: Estimation Protips

Video from my Estimation Protips talk to the Atlanta PHP User Group in September. Slides and links here.

Software Estimation Pro Tips from Atlanta PHP User Group on Vimeo.

You’re an expert developer, peacefully composing code into a profoundly elegant masterpiece, when suddenly your boss rushes in with the Next Big Idea that will Revolutionize The Way People Use The Internet. He’s on his way to pitch to a VC, and stops by to describe the Idea in excited terms. After a 30 second elevator pitch, he pops the question: “So, Ricky, how long do you think it will take to build this thing-a-ma-bob?”

What do you say?

In this September 5, 2013 presentation, Jonathon Hill (@compwright) presents ten Pro Tips that will cover your back, save your job, and keep your boss’s shirt. Jonathon is the Director of Development at Brandmovers (www.brandmovers.com), and a steering committee member of the Atlanta PHP User Group.

Installing the CodeIgniter plugin for PHP_CodeSniffer

Since reading Phil Sturgeon’s post on PHP Static Analysis in the Sublime text editor, I have been experimenting with using phpcs and Sublime in general. Since I am currently used to the CodeIgniter coding standard, the time finally came today to try and configure my setup for that standard instead of PSR-2.

(A downgrade? Perhaps, but it’s what we use at work and it fits better into my workflow at the moment. Besides, the PSR-2 bracket rules annoy me to no end.)

After installing phpcs on top of my homebrewed php54 installation, adding the CodeIgniter standard to PHP_CodeSniffer was a little more tricky than expected. The catch is to specify the correct path to the PEAR module in the ant build script, which is NOT the same thing as the path to the phpcs command:

sudo ant -Dphpcs.dir=/usr/local/Cellar/php54/5.4.19/lib/php/PHP/CodeSniffer/

After that, we’re off to the races. Verifying that the install works:

$ /usr/local/Cellar/php54/5.4.19/bin/phpcs -iThe installed coding standards are CodeIgniter, MySource, PEAR, PHPCS, PSR1, PSR2, Squiz and Zend

Great! Now just change the phpcs settings in the Sublime PHP Code Sniffer config file to CodeIgniter, and we’re done.

"phpcs_additional_args": {
 "--standard": "CodeIgniter",
 "-n": ""
 },

Presentation: Estimation Protips

Estimation is a topic which is extremely important to running a successful software development company, whether you are a digital agency (like Brandmovers) or a freelancer working solo.

I was honored to be the featured speaker for the September 2013 meeting of the Atlanta PHP User Group. The slides are below in case you missed it. If you are interested in the topic, there is supporting documentation below for reference.

Description

You’re an expert developer, peacefully composing code into a profoundly elegant masterpiece, when suddenly your boss rushes in with the Next Big Idea that will Revolutionize The Way People Use The Internet. He’s on his way to pitch to a VC, and stops by to describe the Idea in excited terms. After a 30 second elevator pitch, he pops the question: “So, Peter, how long do you think it will take to build this thing-a-ma-bob?”

What do you say?

These eight Protips will cover your back, save your job, and keep your boss’s shirt.

Supporting Documentation

I drew heavily from these resources for this presentation, and highly recommend them for anyone wishing to get better at estimating projects:

Books:

Blog posts:

Tilde expansion in PHP

If you have ever written a PHP command line script and tried to pass a file to it using the POSIX tilde (~) shortcut to reference your home directory, you may have been surprised to learn that the operating system does not automatically expand tildes in paths.

You’ll get an error like this:

Warning: fopen(~/file.csv): failed to open stream: No such file or directory

Fortunately, it is an easy matter to perform tilde expansion, once you know you need to.

function expand_tilde($path)
{
    if (function_exists('posix_getuid') && strpos($path, '~') !== false) {
        $info = posix_getpwuid(posix_getuid());
        $path = str_replace('~', $info['dir'], $path);
    }

    return $path;
}

H/T to Ernest Friedman-Hill for cluing me into the solution.

Disqus guest posting via API

While evaluating the Disqus API for things like posting and flagging as a guest, I was baffled by this non-descript error:

{"code":12,"response":"This application cannot create posts on the chosen forum"}

After checking the obvious things (like enabling guest posting and checking my domain settings for my forum and application), I was finally able to solve this using the disqus-php library:

require __DIR__ . '/disqus-php-master/disqusapi/disqusapi.php';

$disqus = new DisqusAPI($secret_key);

print_r($disqus->posts->create(array(
    'thread' => $thread_id,
    'message' => $message,
    'author_name' => $author_name,
    'author_email' => $author_email,
    'api_key' => $api_key,
)));

The catch is that the api_key is NOT the same thing as the public key shown in your Disqus application settings. I actually had to inspect one of the AJAX calls from the Disqus Javascript widget to get the correct api_key:

Disqus AJAX call headers showing the api_key

Send mail() using PHP on Mac OS X

Thanks to Benjamin Rojas, Andy Stratton, and a tip from Jasper, I was able to successfully send email from my home-brewed MAMP environment. Here’s the summary.

  1. Add the following to your /etc/postfix/sasl_passwd file:
    smtp.gmail.com:587 username@gmail.com:password

    (Of course, you don’t have to use GMail or port 587, but you get the idea.)

  2. Configure postfix:
    sudo postmap /etc/postfix/sasl_passwd
  3. Backup and edit your postfix configuration:
    sudo cp /etc/postfix/main.cf /etc/postfix/main.cf.orig
    sudo vim /etc/postfix/main.cf

    If you use TLS, then you will need to add the TLS settings but the other settings should already be there as a result of running the postmap command. You should have these options set in /etc/postfix/main.cf:

    mydomain_fallback = localhost
    mail_owner = _postfix
    setgid_group = _postdrop
    relayhost=smtp.gmail.com:587
    smtp_sasl_auth_enable=yes
    smtp_sasl_password_maps=hash:/etc/postfix/sasl_passwd
    smtp_sasl_security_options=
    smtp_use_tls=yes
    smtp_tls_security_level=encrypt
    tls_random_source=dev:/dev/urandom
  4. Start postfix:
    sudo postfix start

    If there are errors, you may need to edit your /etc/postfix/main.cf and restart postfix:

    sudo postfix reload
  5. Send a test message:
    date | mail -s test youremailaddress@yourdomain.com
  6. Make postfix start automatically on boot by opening your /System/Library/LaunchDaemons/org.postfix.master.plist file and adding:
    <key>RunAtLoad</key>
    <true/>

    Add this at the bottom just before the closing </dict> tag.

  7. Edit your /etc/php.ini file and configure the sendmail_path option:
    sendmail_path = "sendmail -t -i"

You should now be able to send email using PHP’s mail() function. If you continue to have issues, watch the contents of your postfix mail log:

tail -f /var/log/mail.log

Write tests, you might learn something

Writing unit tests for your code is widely regarded as a best practice. There are many excuses for not writing tests: time, cost, and the fun factor. Excuses aside, there are some Good Reasons to write tests for your code. I just discovered one today.

Write tests, you might learn something…faster

I’m working on an API integration that requires a bit of AES-256 encryption. Getting that worked out in PHP took some surprising turns, so just to be sure that I was getting all the details right (such as initialization vector size) I decided to write a unit test for my mcrypt wrapper library.

Since this library had worked well in other projects, imagine my surprise when the first AES-256 encrypt-decrypt test failed:

$ phpunit *
PHPUnit 3.7.8 by Sebastian Bergmann.

.F..

Time: 0 seconds, Memory: 2.50Mb

There was 1 failure:

1) EncryptionAes256Test::testEncryptDecrypt with data set #0 ('ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz')
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz'
+Binary String: 0x4142434445464748494a4b4c4d4e4f505152535455565758595a61626364656668696a6b6c6d6e6f707172737475767778797a00000000000000000000000000

/Users/jhill/Sites/mrtz_010/Source/tests/EncryptionTest.php:53

FAILURES!
Tests: 4, Assertions: 7, Failures: 1.

Echoing out the decrypted string proved just as bizarre:

string(51) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz"
string(64) "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefhijklmnopqrstuvwxyz"

It seems that mcrypt pads the string with enough null characters (\0) to match the block size, and unlike strings in C, PHP strings do not necessarily end with the first null character.

The fix was obvious:

$decrypted = rtrim($decrypted, "\0");

Guess what? By investing time in a simple unit test, I unexpectedly learned something new about PHP, AND saved myself quite a bit of time debugging an API call that would not have worked.

I’d say it was worth it.

Hello! I’m a self-taught freelance web developer, and this is my blog. Here, I document problems and solutions in PHP, MySQL, and Javascript that I encounter along the way. Enjoy!