A Different Type of Resume (Résumé)

The one thing that’s difficult to tell from a programmer’s résumé is “Can they actually code?”  Sure, they may have had some coding jobs in the past, or have some schooling in programming, but that doesn’t tell you much about their actual skill.  Or maybe they DON’T have the schooling or work experience, but have done tons of personal projects or worked in open source projects… a résumé might miss that talented coder.  One of the things that I see a lot of tech people looking for recently is a Github account, and examples of coding or helping with open source projects, which is great.

As I thought about putting together a résumé, I wondered how can I demonstrate understanding of modern PHP concepts, without the hiring person needing to jump through a lot of hoops, or visit a bunch of sites.  So I created a résumé in code, and got some useful tips from the Forrst community as well.

The goal was to make a resume that could be readable to a non-programmer.  And I think if you look at it, you should be able to follow along:

$myResume->myName = “Terry Matula”;
$myResume->myEmail = “terrymatula-at-gmail-dot-com”;
$myResume->myPhone = “281-656-1474”;
// Places I’ve worked
$workExperience = array();
etc…
Even if you knew nothing about coding, that should make sense. And the great thing is, if you copy the file to a server and run it, it actually makes a somewhat nice looking résumé page.

Things I’ve Learned Using Codeigniter – PHP

1) You don’t need an ORM

I had experimented with Datamapper, and it was great. But there was complex join statement I needed that DM didn’t support… so I had to just write out the SQL like normal.  I then realized it’s just as easy to use CI’s Active Record or regular query command and create your own methods.  Plus, it keeps things pretty speedy.

2) You DO need a base Model

I’ve only just recently started using Jamie Rumbelow’s MY_Model and it’s changed everything. Previously, when I wanting to get a single record from a table, I was writing $this->db->from('table')->where('id',$id)->limit(1)->get()->row(); for every single table. Now, that’s already included for every Model I make.

3) It’s helpful to look at the core code

For example, I was curious how the Active Record was implemented, so I opened up DB_active_rec.php. I know some people prefer to use “->get()” by adding in the table name and limit as parameters, and I wondering if there was difference in how it’s handled.  Interestingly, it runs the exact same “from()” method, just as if you had “->from()” in the query.

And while this is a micro-optimization, if you want to return a single result and you’re sure it’s the first result… use “->limit(1)”.  The “row()” method will work with multiple rows returned, so there’s logic built in to just return the first row.  Adding “->limit(1)” will help skip all that.

4) The url helper really needs to be auto-loaded by default

In my autoload file, I always load the database and sessions libraries and the url helper. I can’t remember a project where those didn’t get used.  I’ll occasionally autoload the form helper as well, but that’s a project-by-project call.

But the url helper… I honestly can’t see how anyone would ever NOT use that in every project.  “site_url()” and “redirect()” just seem like no-brainers.

5) Object-Oriented programming and MVC

Prior to learning Codeigniter, I was experience in Drupal and WordPress, and a bit of Joomla, but working with them isn’t strict OO.  The custom stuff I programmed was really procedural or functional, based on the fact that I learned programming using PHP 4 and classic ASP/ vbscript.  While I read about and tried using Classes and methods, I just didn’t get it. With CI, I had the ‘flipped switch’ moment, where Objects and Classes made total sense.

Now, I’m onto learning as much as I can about OO in PHP 5.3, including namespaces and inheritance… which aren’t yet built into CI

5 Rules for Your Email List Unsubscribe Link

I put my email address into a lot of forms, especially because I like to check out new sites and services, and I’m always hoping for the “beta” invite. Inevitably, this means I also get added (without my knowing) to a lot of email lists. At the bottom of most emails is usually (if they’re following the law) a link to “unsubscribe”.  I’ve noticed some companies do unsubscribes right, and others… not so much.  So here are my rules that you should always follow for YOUR email list:

1) The best unsubscribe link takes you to a page that says “You’ve been removed from our list”… and that’s it.  Simple, effective, and I won’t hate you or your company afterwards.

2) The second best way (if you really think your email recipients are so stupid they may click it unintentionally) is to have a page with two buttons. One saying “Unsubscribe” and another saying  “Oops! I made a mistake! I don’t know how links works! Derp” or something.

3) NEVER ask for my email address to unsubscribe. You sent me the freaking email, you should KNOW my address. Also, I often use the “plus trick” for my gmail, and asking me to track down exactly what email address I used for your stupid, spammy site will just fill me rage and hatred for you and your babies.

4) NEVER send an “Unsubscribe Confirmation” email. Seriously? Are you that stupid? I just said “Don’t send me any more emails” and you’re going to do the exact opposite? How are you able to feed and clothe yourself?

5) Do NOT ask me to sign in and “change my notification preferences”. More than likely, I already forgot the password for your lame company that TechCrunch will never cover, and I’ll just have to do a “forgot password” thingy… meaning I must both find what email address I used AND get another email from you. Fail. Fail. Hatred. Fail.

Simple Facebook / Codeigniter Authorization

On a Codeigniter project I’m working on, I wanted to have Twitter and Facebook logins available. Luckily, right around the time I was starting the project, Elliot Haughin released libraries for both Twitter and Facebook. The Twitter library worked almost instantly and is quite brilliant. However, the Facebook library was causing me some problem.

Looking through the Facebook Developer pages, it seemed like a fairly straight-forward process to get a User’s Facebook auth tokens… and with CI2 having querystring support now, I thought I could do everything in a simple Facebook controller.  Here’s what I got:

<?php

if (!defined('BASEPATH'))
    exit('No direct script access allowed');

/**
 * Name:  Simple Facebook Codeigniter Login
 *
 * Author: Terry Matula
 *         terrymatula@gmail.com
 *         @terrymatula

 * Created:  03.31.2011
 *
 * Description:  An easy way to use Facebook to login
 *
 * Requirements: PHP5 or above
 *
 */
class Facebook extends CI_Controller {

    public $appid;
    public $apisecret;

    public function __construct()
    {
        parent::__construct();
        // replace these with Application ID and Application Secret.
        $this->appid = '12345';
        $this->apisecret = '123abc123';
    }

    /**
     * if you have a Facebook login button on your site, link it here
     */
    public function index()
    {
        // set the page you want Facebook to send the user back to
        $callback = site_url('facebook/confirm');
        // create the FB auth url to redirect the user to. 'scope' is
        // a comma sep list of the permissions you want. then direct them to it
        $url = "https://graph.facebook.com/oauth/authorize?client_id={$this->appid}&redirect_uri={$callback}&scope=email,publish_stream";
        redirect($url);
    }

    /**
     * Get tokens from FB then exchanges them for the User login tokens
     */
    public function confirm()
    {
        // get the code from the querystring
        $redirect = site_url('facebook/confirm');
        $code = $this->input->get('code');
        if ($code)
        {
            // now to get the auth token. '__getpage' is just a CURL method
            $gettoken = "https://graph.facebook.com/oauth/access_token?client_id={$this->appid}&redirect_uri={$redirect}&client_secret={$this->apisecret}&code={$code}";
            $return = $this->__getpage($gettoken);
            // if CURL didn't return a valid 200 http code, die
            if (!$return)
                die('Error getting token');
            // put the token into the $access_token variable
            parse_str($return);
            // now you can save the token to a database, and use it to access the user's graph
            // for example, this will return all their basic info.  check the FB Dev docs for more.
            $infourl = "https://graph.facebook.com/me?access_token=$access_token";
            $return = $this->__getpage($infourl);
            if (!$return)
                die('Error getting info');
            $info = json_decode($return);
            print_r($info);
        }
    }

    /**
     * CURL method to interface with FB API
     * @param string $url
     * @return json
     */
    private function __getpage($url)
    {
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
        $return = curl_exec($ch);
        $http_code = curl_getinfo($ch, CURLINFO_HTTP_CODE);
        // check if it returns 200, or else return false
        if ($http_code === 200)
        {
            curl_close($ch);
            return $return;
        }
        else
        {
            // store the error. I may want to return this instead of FALSE later
            $error = curl_error($ch);
            curl_close($ch);
            return FALSE;
        }
    }

}


That’s about it. You could put it all in “index()”, but I wanted to separate it a little.

update: Looking at the bit.ly api, it’s actually very similar. i’ll eventually try to make it more generic.

CodeIgniter and Datamapper ORM base installation

More and more at work, I’m using CodeIgniter (actually version 2) coupled with Datamapper ORM for quick projects. I even completed a fairly substantial project (the Careers page for PetRelocation.com) with probably 90% of the work being done in an 8 hour period… solo. The most difficult aspect of the whole thing was having multiple file uploads required for the page.  For these projects, I created base framework with CodeIgniter 2 and Datamapper ORM already integrated… plus some of the config files already set, like the autoloads.

So in the effort of being a good community member, I’m offering the CodeIgniter/Datamapper base that I use.

Weekend project – Auto Missing Child Alerts

Last week I saw some posts in my Twitter stream that were retweets of a missing child alert in the UK. It made me wonder if there was something that would do this automatically, so that a tweet would get sent from a user as soon as an alert was issued.  Kind of like the Emergency Broadcast System but for social networks.  I searched over a few days and couldn’t find anything, so I thought I’d build my own.

The guts of the program literally took a few hours yesterday, since I’m already aware of how to access Twitter and Facebook’s API.  I think the big hurdle is convincing people to essentially hand over their accounts to a service… with the knowledge that an alert post could come up at any time.  Also, trusting that the service won’t use the information for “evil”.  If it all works, however, it could be a huge boost to the Amber Alert system.

Imagine, the instant an alert is issued, it’s posted to multiple accounts and in front of millions (10s of millions?) of people.  One argument might be, if you follow 50 people who signed up for the service, you’d get 50 of the exact same message in your stream… but really, it only happens infrequently, and it’s to help find a missing and endangered child. People should be able to overlook that.

Right now, I think I have it working well… but I’ve only been able to test it with my accounts. I’m not sure how it will scale, but it seems to be okay. Here are some details of how I have it setup…

First, if you login using Twitter, I’m saving your “twitter name”, “oauth token”, and “oauth secret token”.  With Facebook, I’m saving your “name”,”oauth token”, and “facebook id”, and asking for offline posting privileges.  Then I have a table that sets whether you have the service active or not, keyed off your unique id. After you activate the service, you’re done.

After that, I have a script that checks for new Amber Alerts… though I’m hoping to add in international alerts.  If it finds a new one, it sends out a post with a link to the Amber Alert page. I also built a sort-of “panic button” script, in case something goes horribly wrong… or the site is compromised… I can run it and the whole system is wiped. Contingency plans, you know.

So it’s all at AutoAlert.Me. I’m probably not going to publicize it anymore than this post and tweet, and just having it running for my own accounts… but it’s there if others want to use it too.

Things I Learned from Codeworks Austin 2010

I went to Codeworks Austin on Saturday, and it was kind of eye-opening. Lots of good info about how to better approach PHP development.  Here’s what I learned:

  1. First and foremost, even after developing for over 10 years, I have a LOT to learn. In fact, there’s an alarming amount of stuff I DON’T know.My biggest issue, is that I originally learned PHP4 10 years ago, and it was very procedural. You wrote code from top to bottom, and it ran from top to bottom. After I started getting into it, I got my first programming job doing mostly Flash, ActionScript 2, and classic ASP using VBscript. I basically set aside learning PHP, since there wasn’t really a need in my day-to-day life.  I picked it back up a couple of years ago, mostly for personal sites, but PHP5 had many new features, and I never had need to learn them all.
  2. I really need to master OOP. Again, my previous programming experience was ActionScript 2, classic ASP, and PHP4… which are all mostly procedural or functional.  I’ve jumped ahead quite a bit in my OOP experience with getting into some of PHP Frameworks like CodeIgniter and CakePHP… but I need to get more comfortable writing my own classes outside of the frameworks.
  3. Speaking of frameworks, I might need to check out Zend. It seems a lot of people there were using Zend Framework, and the speakers seemed pretty happy with it.  Also, I think I was the ONLY person there that isn’t using PEAR.  So I should probably get on that as well. Though, working on a Windows machine, it doesn’t look all that straight forward.
  4. Speaking of Windows not being easy… it seems most people there were on Macs, and many seemed to be Terminal/Command Prompt ninjas. Since current Macs have Unix at their base, there is a lot of built in functionality that makes setting up a PHP dev environment a lot easier.  However, I think I may go the Linux route, because… why not just go as hardcore as possible?
  5. Subversion/ Version Control. I’ve submitted one bit of code to Github, and that’s the ONLY time I’ve ever checked anything in or out, ever.  In a multiple dev environment having version control is a necessity,  but since I’ve been a “lone ranger” for all of programming career, I’ve never bothered to learn or implement it. Moving forward, with both my personal advancement and expanding my current job, I really need to get this up and running.

While the actual talks themselves were okay, they were mostly “overview” type stuff. Very little detail.  But just seeing how other devs worked was the most education thing I took away. Lastly, I really want to get more involved with other events like that… and take my coding to the next level.

    My Sacrilegious Twitter App: Jesus the Zombie

    I like to play around with PHP and APIs and create silly, stupid things every now and then.  After recently watching a number of zombie-themed shows, namely The Walking Dead and Dead Set, I thought it would be funny to have an app that would “eat” the brains of people’s Twitter avatars. And for whatever reason, I thought having a Zombie Jesus doing the eating would be even funnier.

    I worked out the steps that needed to happen: 1) get a submitted user’s avatar from Twitter, 2) process the image so it looks like Jesus is eating the “brains”, 3) display/save the image, 4) send out a Tweet with a link to the picture.

    Getting the avatar from Twitter is a fairly simple function:

    function getAvatar($screen_name){
         $url = "http://api.twitter.com/1/users/show.json?screen_name=".$screen_name;
         $ch = curl_init();
         curl_setopt($ch,CURLOPT_URL,$url);
         curl_setopt($ch,CURLOPT_RETURNTRANSFER,1);
         $return = curl_exec($ch);
         curl_close($ch);
         $return = json_decode($return);
         return $return->profile_image_url;
    }

    Since you don’t need authentication, you just “curl” to get the user’s info, parse the json, and return the avatar’s url.  Processing the image isn’t so easy. I’ve used the GD2 library in the past… for another simple app that put a custom message on Charlie from “Lost”‘s hand, in the episode where he wrote “Not Pennys Boat” on his hand, which I can’t seem to find now.  GD2 is powerful, but not user-friendly at all. So I searched for a better solution, and found the amazing WideImage library. It does everything I needed, and I was able to map out the process I needed in a few minutes.

    I grabbed the image from Twitter, resize it to 60px by 60px, then rotate it -45 degrees. Then I have a Jesus png that I use as a mask, with the section where the avatar goes being cut out… and some blood coming down for effect. To do the masking effectively, I had to then resize the avatar’s canvas to the size of the main Jesus pic, and position the avatar on the canvas to the area where the open area of the Jesus pic is. Then you merge the two pictures to make the final image.

    After that, I just used “writeText” to put the caption on. I had do a second “writeText” in black for the bottom part, to give it a shadow, since just the white was being washed out. Once all that is done, I save the file. For the filename, I was originally using the timecode… but if by chance multiple people hit the site simultaneously, it might be hosed. So instead, I took the two submitted usernames and the timecode… and ran md5 on it. I’m assuming that will give totally unique names.

    I didn’t want to be serving up the images solely on my machine, so I decided to use the TwitPic API to save the images. This also allowed me to skip using the Twitter API and do the actual post from TwitPic as well. Since this is a simple, fun project, I decided to use the legacy v1 of the API, because I didn’t want to mess with oAuth.  Here’s that function:

    function sendPic($file,$to,$from) {
         $key = ""; // TwitPic API key
         $consumer_token = ""; // Twitter application consumer key
         $consumer_secret = ""; // Twitter application consumer secret
         $oauth_token = ""; // the user's OAuth token
         $oauth_secret = ""; // the user's OAuth secret
         $ar = array (
             "consumer_token" => $consumer_token,
             "consumer_secret" => $consumer_secret,
             "oauth_token" => $oauth_token,
             "oauth_secret" => $oauth_secret,
             "key" => $key,
             "message" => "I just ate @" . $to . "'s brains at the request of @". $from ,
             "media" => "@$file"
         );
         $url = "http://api.twitpic.com/1/uploadAndPost.json";
         $ch = curl_init();
         curl_setopt($ch, CURLOPT_URL, $url);
         curl_setopt($ch, CURLOPT_POST, 1);
         curl_setopt($ch, CURLOPT_POSTFIELDS, $ar);
         curl_setopt($ch, CURLOPT_RETURNTRANSFER,1);
         curl_exec($ch);
         curl_close($ch);
         return true;
    }
    

    And that’s basically it. The only other bit of code-fu I used was to check the Twitter names people might put in… since sometimes people will use the “@” in front of the name, and other times they won’t. So I just ran a “strpos” checking for “@”, and if it’s at the 0 position, I “substr” to position 1.

    As far as security, there really isn’t any.  Since there’s no mySQL, I wasn’t too worried about it… as there’s not much to exploit with the simple code I used. I did set a session with the timecode, and if you try to submit the form more than once a minute, it sends an error… though that would be trivial to overcome.

    Other than toying with it some more, I’m pretty much finished. Being wide open as it is, it’s very very VERY susceptible to spam… so I may implement a bit of oAuth eventually. Other than that, it’s really only amusing for a few times… after that, it’s just a bit annoying. So we’ll see if anyone else finds it humorous.

    Social Shopping – the problems and some ideas

    My wife has been very wary of looking for a sitter/daycare for our 19 month old. Especially since he’s still not talking and not able to communicate his needs clearly. But when a woman in a mom’s groups she belongs to emailed with a recommendation for a sitter, she forwarded the email to me and is considering using her.  It struck me how powerful just one email, from a mom she’s only known for a few weeks, about another women who she’s never met, can be.

    Countless sites are attempting this, from Scordit to hollrr and more successfully to Blippy. Even Facebook is getting into the game with Places and it’s couponing system. But all those solutions seem to be lacking… something. Here are the pitfalls as I see them:

    1. They show you all reviews/ratings from everyone. The problem with that is I don’t care what most people think about a product. Though, I do occasionally read some of the more thoughtful reviews on Amazon.
    2. The products/services are show in a “stream”. The Twitter feed/Facebook wall style of presenting status updates just isn’t useful for product recommendations. My friends may buy a new vacuum cleaner today, but I may not need one until next year. However, I still want to get their opinions, and not have to do tedious searches to find them.
    3. You only get one review, and usually just after you got the product. The sites that offer incentives to review/rate products only incentivize the initial review.  To be a truly effective review, I want to see the initial thoughts on the products, plus the thoughts after a month or so of using (or not using) it, and then maybe 6 months or a year later.
    4. They want you to be part of THEIR social network. Here’s the sobering fact… NO ONE is leaving Facebook. At least not for the near future. People are NOT going to your site, signing up, filling in their info, leaving reviews, and “talking” to others on YOUR site. They will stay on Facebook. As the ReadWriteWeb/Google debacle from a few months ago shows, for many people Facebook IS the internet… and your site is not going to change that.

    I figure there a few things that a successful social shopping site must have.

    1. First and foremost, it must be a Facebook app. Sure, you can have a regular website for those who want it… but the focus should be on FB and keeping the info within the FB frame.
    2. Finding recommendations needs to be super simple and intuitive. If I’m looking for a TV, I should be able to simply type “TV” and see what my friends have bought. I would also offer an advanced search for power users, so people can drill down into specifications or even expand the social graph beyond just their friends… but the core functionality should be just the basics.
    3. Awesome incentives to post and review. “Badges” are fine, but “20% off a $100 purchase at Best Buy” is GREAT. Also, increase the incentives as time passes – I envision something like Scordit, where you get points for each post or review.  Your first review, or “I just bought ___” post, gets 1 point.  A month later, your second review gets 5 points… a year later, 10 points. The points can then be used to get rewards, for example 100 points gets 10% off a purchase at Amazon… or a $5 gift card from Best Buy.
    4. Assign “importance” to your friends. Over two Facebook account, I have 117 friends. These are all people I know, but honestly, I only truly value the opinions of about 35 or so of them.  In my theoretical Social Shopping app, I should be able to give those friends priority and have their results be first on the list.

      Additionally, it would be cool to give certain friends priority over certain types of purchases — like my more tech-savvy friends having more priority when it comes to computer purchases. In a perfect world, there would be an algorithm that parses the data from your friends, and your interactions with them, and automatically prioritizes them. For example, you have two friends with the jobs listed as “IT specialist”, but you’ve only written on the wall of one of those friends.  So when you search for “computer monitor”, those 2 friends show up first, with the #1 friend on top.

    5. Mobile apps for every platform. If you’re in the store with your iPhone or Android, you should be able to open the app, scan the barcode, and get reviews. If there aren’t any reviews from your friends, you then have the option to view ANY review of the exact product, or your friends’ reviews of similar products. Including something like Google Goggles functionality would also be useful… since some stores don’t always have barcodes on their display items.

    These are just a few of my thoughts on the matter. I think the biggest issues are going to be lowering the barrier for entry, and providing good incentives for people to participate.  Blippy gets really close, and has shown some success… but they’re still just not quite there.

    Maybe one day I’ll spend a few days hacking out a prototype of my idea.