Hi, my name is Terry Smith and I'm a developer and aspiring entrepreneur.


17
Oct

Testing, Testing…

Posted by Terry Smith on 10/17/2011 at around 1:23 PM

As a couple of my 4 or 5 readers (hi wife!) might have noticed, my blog has been in and out of service a lot with a white screen lately.  As part of my work for 23press, I’ve been running a lot of tests of my code on this blog.  As a result, sometimes, I have to fix things and in the process I break things (it makes sense in the end, I swear).  So please bear with me, and if you get here and it’s just a blank screen, give it a minute or two and it should be back.

Thanks in advance you 4 or 5 fantastic people.

16
Oct

Upgrading To Android: What Happened RIM?

Posted by Terry Smith on 10/16/2011 at around 7:38 PM

This weekend (after my wife upgraded from her 3GS to an iPhone 4S and I got jealous), I upgraded my phone.  As with most users, I had three major options for what OS/device I wanted to move to: BlackBerry, iPhone or Android.  Windows wasn’t really an option as I’ve never been a huge fan of Windows Phone, and after Microsoft really botched rolling out their major update, their fate was sealed for me.  As a starting point, I previously had the BlackBerry Bold 9700.

When I first got my BlackBerry Bold, I loved it.  I wanted to tell people and show it off.  I previously had a track ball, and the new track pad was fantastic.  It did push e-mail for all of my accounts, while everyone else needed a separate app to push e-mail.  Overall, it still felt like I was using one of the leading phones on the market.  But now… it felt antiquated next to my wife’s iPhone 3GS.

So I spent an hour last week in the store looking at different devices and what I saw was pretty much what I expected: iPhone was still iPhone: pretty, Apple-y (redundant), and with its iOS lock in, while the Android devices were fragmented, each with their own quirks.  After testing and playing with a bunch of different devices (a lot of them 3D — what a shit show), I chose the Samsung Galaxy S 4G.

But what surprised me were the BlackBerrys.  What happened to you RIM??  After using the Galaxy S for a couple days now, I feel like I’m free of the shackles that was my BlackBerry Bold, and I am reinvigorated by my phone.  I wanted to talk about a few of the things that I love that I feel like BlackBerry is really missing out on.

The Browser

This is absolutely #1 on my list of things RIM needs to get a handle on.  Maybe this is better in their newer phones, but just before I got my Galaxy S, I upgraded my Bold to OS 6.  The browser just plain sucked.  Before I upgraded to OS 6 (I was on OS 5), many sites that relied on JavaScript and/or AJAX simply didn’t work (this included Twitter).

After upgrading to OS 6, those sites did work, but holy shit was it slow on the JavaScript execution side. I would compare some of the B5Media sites (that have a ton of JavaScript for ads and post-loading non-essential content) and those sites would load exponentially faster on my new phone or on my wife’s iPhone (both the old 3GS and the new 4S).  It was slower on almost every front: SSL content was slower, JavaScript was slower, rendering was slower, zooming was slower… while our new phones are quite a bit farther ahead in the processor department, their new phones that I tested were using the exact same engines; in my opinion, this isn’t an issue that’s going to be fixed at the hardware level, it’s just bad (feels like legacy) software and it is in serious need of a reboot.

Apps

App availability specifically. I’m not sure what the solution is here because app developers have stopped releasing apps for the BlackBerry platform in their initial mobile release.  And the apps that are available are not even on the same level as apps for Android and iPhone.  The Twitter and Facebook apps for BlackBerry feel just as old as the system they’re running on.  RIM needs to get back in the game on app development; maybe they should use some of their cash horde to start promoting incentives.  Since I haven’t developed a lot of mobile apps, I can’t really offer much input onto why this is (other than the obvious falling market share), but it was a huge motivator for me to not get another BlackBerry because most companies released iPhone, Android and then BlackBerry apps, in that order (if for BB at all).

App Links

There isn’t much I wasn’t expecting about Android, but this was unexpected and surprised me in a very good way.  Links between apps like Twitter, Facebook, and YouTube are so seamlessly integrated into the system; when I open a YouTube URL, it asks me if I want to open it in the YouTube app or use the web, and it works similarly for Facebook and Twitter links (and others I’m sure).  This is hugely powerful, and means I can choose the best experience for myself (and so far the apps have won every time).

Contact Management

This has become one of the biggest tools our phones are used for, and it’s not just for managing the basic information like e-mail address and phone number anymore.  This also seems to be exclusive to Android, because iPhone isn’t as in depth, but Google has this down pat.

Add the Facebook app, it scans your contacts and adds profile pictures, info, etc. for matching contacts.  Same with Twitter, Google accounts, Skype, and others I’m sure.   It also allows me to search and join contacts from all of those apps into my existing contacts, to do it manually if I wanted, and to merge contacts together where things might not match perfectly.  It’s a seamless experience that has been of huge benefit to me already (for example the Skype app let’s you choose whether you want to call or Skype call anyone who you also have on Skype).

This seems like such a natural fit for RIM in both the consumer space and the enterprise space (think LinkedIN, getting social updates on contacts, etc.) that I would be extremely disappointed if they didn’t try to mimic this feature in the future.

Touch Screen

From a consumer point of view, I am probably 80/20 on touch screen versus a physical keyboard (I do not think RIM’s idea of having both is a long term solution).  The touch screen just makes sense nowadays, even if the keyboard takes some getting used to.  RIM really botched this with their attempt at tactile feedback on the early version of the Torch where you actually had to press the screen to press a key.  For a long time one of the major reasons I would not get a touch screen was because I loved my physical keyboard.  But after using it for two days, I’m getting used to it (and it to me if there’s some intelligence there), even with my fat fingers.  RIM needs to ditch their physical keyboards, and just go all in with the touch screen.

E-mail (Push/Pull/Etc.)

The last feature I really wanted to touch on was e-mail.  This used to be RIM’s bread and butter, but now everyone has e-mail.  They still have a leg up with the ability to do push from any e-mail account (Android natively only pushes Google accounts, and while the iPhone pushes all sorts of e-mail now, it’s not just any IMAP/POP account); but it’s not enough to make a meaningful difference.  That said, reading HTML e-mail on the BlackBerry is painful, and so is designing HTML e-mails that may or may not look good on it (depending on device, OS, and the general mood of the phone).  Even our daily stats e-mails from B5Media, which have a simple table in them, wrap around to fit the space and scroll through each table cell. I would put this right above the browser on a usability scale; this issue needs some serious love and attention.

Conclusion: Reinvention v. Repurposing

RIM is supposedly working on their QNX operating system, but early reports assume that it will continue to underwhelm.  In my opinion, RIM made a mistake trying to create phones that were oriented to both consumer and enterprise alike, and now the reality is that they have a hold on neither of them.  I would even argue that it’s because of this that consumer phones are now making their way into the enterprise.  More enterprises are allowing employees to use Androids and iPhones; it might not do everything they want from a technical enterprise management point of view like BlackBerry does, but it’s what the employees want, and it’s pretty clear why.

RIM has tried repurposing their phones and has tried differentiating themselves in the stupidest ways (press touch screen, the Playbook as an extension to your phone…); it’s time to go back to the drawing board and reinvent and completely rethink their strategy; and in my opinion they need to start creating consumer phones with an easy to use and highly configurable enterprise layer on top.  They have a lot of things they need to fix to get there; maybe they should use Android as a base, maybe QNX will be a step in the right direction.  Whatever they do, they need to do it soon, because they’re falling further and further behind in developers’ minds, and that’s a really crappy cycle to be in as people move to other platforms because of the availability of apps.

I wanted to like you guys so badly, but you’ve fallen so far behind I’m not sure if you’ll ever catch up.  The community, your customers, and your developers are telling you what they want.  If you listen to them, it’s a step in the right direction, but you need to start fixing all of the things that are broken before you can make people pay attention to any real innovation.

29
Aug

23press: Game on

Posted by Terry Smith on 08/29/2011 at around 11:25 AM

Wow!  It’s been a crazy few weeks.  While I’m not likely to take up regular blogging for a little while still, I wanted to let everyone know where I’m at.

Recently, I moved from full-time employment with B5Media to full-time contract work.  I am still on a part-time contract with B5, but my focus has begun to turn to other projects.  Before I talk about those though, I want to give a huge shout out and thanks to Lee Newton and Joe Taiabjee, who have been incredible to work with at B5.  On top of being great friends, they have taught me so much that I will take with me, to anything else I do.

Speaking of which, I am happy to announce that 23press, a small project I started back in Februrary (after Jeremy Wright gave me the idea), is now a real company.  Jeremy has officially come on board as our CEO, and we’ve added another founder, Jason Hall, as our COO (I remain the faithful company janitor/CTO).  Jason is a super smart operations guys who brings a wealth of experience in managing, marketing and running venture backed companies to the table.  I couldn’t be happier to have him on board.  Since most of you that read this blog are in the blogging and/or start up world, I’ll let Jeremy’s experience and reputation speak for itself.

So what’s next? Today, we are launching our completely redesigned 23press site, as well as version 1.4 of our flagship product Move That Blog.  It has been a bit of a bumpy road, since (as you can imagine) browsers, blog setups, and hosts are all very different from each other, which makes our job of cross-communication even more difficult.  Version 1.4 of MTB is much more stable than it’s predecessors and addresses a ton of issues we’ve seen so far in our initial sales.

We are also planning a backup product.  It’s a busy market, but we think we can do it simpler, faster and better than the other guys and we can’t wait for the chance to prove it.

That’s it for now!  There are some other exciting updates in the pipeline I hope to make public soon, so please stay tuned.  As always, if you have any questions, feel free to reach out.

26
Jun

Re-creating Facebook’s Gallery Lightbox

Posted by Terry Smith on 06/26/2011 at around 4:18 PM

I have been fascinated with Facebook’s new gallery light box since it launched.  The details of it’s implementation confused me for a while, and I knew I had to find the time to re-create it.  After putting it off for far too long, last week I realized (with some amount of shock and awe) how it was being done.  So I spent some time coding it up and thought I’d share.

First, a demo.  If you scroll halfway down the page you’ll find a button to click that will reveal the light box.  There is a close button on the top right corner of the light box.  The demo can be found here: Facebook Gallery Lightbox

As you may have noticed, there are several cool things about the way this light box imnplementation works:

  1. When the light box is up, the window’s scrollbar represents the gallery height, not the height of the document.
  2. Your scroll position on the content is maintained (ie. it doesn’t move to the top of the document), and when you close the light box, you are right where you left off.
  3. The URL changes to reflect the new page you are on without refreshing the document.

Let’s go through the code, and we’ll tackle these each one by one.

The CSS and HTML

As you can see, the HTML for this demo is quite simple (made simpler by the fact that there isn’t any content :) ):

The first element of note is the “canvas” element.  This is an element I’ve had kicking around for a while for use in my CSS Sticky Footer (in this case you can ignore the “footer” element stuff). The element extends to the full width and height of the window, regardless of whether the body of the document is shorter than the window height or longer.  This is particularly useful for light boxes, and as you can see here, there is a “screen” element, which is simply an absolutely positioned element inside “canvas” that takes up the entire width and height of the window as well.  The CSS for the screen element is below (note: we are using a black color with a 30% opacity using a CSS RGBA color):

We also have the “gallery-wrap” and “gallery” divs, the CSS for which is below:

We use the “gallery-wrap” element here to create a horizontally centered div (margin: 0 auto) of the width 960 pixels (you can adjust this as necessary).  Inside of that is the “gallery” element, which is floated left.  Even though we’ve assigned it a min-height here to demonstrate the window scrollbars, because it is floated left, it will grow vertically to fit any content we put inside of it.  You can add your photos, navigation, comments, menus, etc.

As you can see, the CSS and HTML for this isn’t really anything special.  However ,let’s move on to the JavaScript.  This is where things get interesting.

The JavaScript

I have to applaud whoever came up with this since it’s pretty out-of-the-box. Basically, when the user opens the light box, the entire content of the HTML body is shifted upward and conversely, the height of the content is set to the height of the window.  This means that the view is set to the section of the page you were looking at.  Then, the light box is displayed, allowing the document’s height to fluctuate again with the height of the light box.

Let’s get right to  it and take a look at the JavaScript to display the light box; as you can see, I am using jQuery to simplify some of the method calls:

The first line (the old_top variable) is a record for us to keep.  This variable holds the current offset from the top of the document (the current window scroll position); when the light box is opened, the “top” property of the content is set to be negative the current offset. The height of the content is also locked to the height of the window and its overflow property is set to hidden so that the content does not cause the window to scroll vertically.  Finally, we display the screen and the gallery-wrap elements.

As I noted, the URL of the browser window changes when the light box is open.  This happens on line 5: we use HTML5′s window.history.replaceState function to change the location of the window without redirecting the user or refreshing the screen.  This makes the URL shareable.

To close the gallery, we basically do the opposite:

As you can see, we replace the current history item with our old location and hide the screen and gallery-wrap elements.  Then, we allow the content to overflow, set the height back to auto to allow it to expand to fit it’s content, and set the top to zero to put the top of the content back at the top of the document body.  Finally, we set the user’s current scroll location back to what it was using our storage variable.

Conclusions and Enhancements

I picked this apart because I was uber curious (and a little in awe) as to how it worked; that said, I’m sure it’s not perfect.  In fact, I’ve already thought of several improvements that could be made (I will post a follow up if I can find the time to make them):

  • Not all browsers will support the HTML replaceState method.  This should likely be wrapped in a if(typeof window.history.replaceState == ‘function’) and code should be added to fall back to a hash-bang URL change or a simple redirect.
  • This would pair extremely well with an infinite scroll like Facebook uses.  This obviously requires a session’s scroll state to be saved and/or cached and you would have to return the user to where they once were.  There was an excellent tutorial about this recently on Hacker News but I can’t find it for the life of me.
  • Content for the gallery could/should be loaded in via AJAX.  This could also be cached in the browser, etc., etc.

I am itching for a place to put this into practice; I’m sure my next project or site will find a way to incorporate it.  Again, whoever came up with this deserves a beer/pat on the back as the outside-of-the-box thinking here actually shocked me when I realized how it worked.

If you have any questions or suggestions for improvement, please let me know in the comments below!

19
Apr

How Not To Run A Conference: WordCamp Edition

Posted by Terry Smith on 04/19/2011 at around 3:21 PM

Update: One of the hosts of this year’s WordCamp Toronto has replied in the comments below.

There are a lot of uses for a blog.  I like to use mine to post new ideas for projects, or to discuss/propose controversial issues.  But today I’m going to use it for the other purpose: venting.

WordCamp Toronto may or may not be coming up soon.  I have been a pretty avid attendee here in Toronto.  I spoke at the conference in 2009 and got hooked.  I attended in 2010, and was hopeful to attend again in 2011.  So in February or March the site went up for WordCamp 2011 and the first thing I looked at were the cost of the tickets and the venue to make sure it’s not in the middle of nowhere.  The tickets were a little high ($35 for early birds and $55 for not), but more strangely the venue wasn’t printed in big bold letters on the home page like I would expect.

After some digging I found they had not yet chosen a venue and were waiting to see how many attendees there would be.  Fine, that’s reasonable if I think through it.  Cutting it close, but these people have likely not run a conference before (the WordCamp Toronto conferences I have been to in the last three years have been run by as many different people and organizations).  So I dutifully paid my $35 to let them know at least one more person would be in attendance.

And then… they redesigned their site and it was sexy and edgy and fun.  And it still didn’t have the venue information on the home page.  But, wait!  There was a Venue section on the site!  Hope!  Joy!

It linked here.  You could win a ticket by guessing the mystery location!  Wait… what?  Your only clue is “It’s in the city of Toronto.”  Recent population data says that 2.7 million people live here.  Needless to say it’s not a small city and there are tens of thousands of possible venues.

W.T.F.

I am all for promotion and I get that this is probably being put together by amateurs, but this is crossing the line.  Not only is there no venue, there is a page that reads to me like a desperate attempt to crowd source venues that almost never gets updated, and a contest to guess where it might be.  Plus there’s no shortage of misinformation on Twitter about what’s happening now and their registration page is down (that I pray to god isn’t true given their no refund policy — good thing PayPal does charge backs!).

This kind of silly game dilutes the value of WordCamp as an event and a brand.  I am fortunate enough to live in Toronto this year, but the previous years I’ve had to fly in to attend.  People can’t do that this year without information about where they should stay.

WordCamp Toronto has been on a definite decline in recent years but this takes the cake. It looks unprofessional and untrustworthy, especially to those who might want to come in to the city to take part.  Better to not have a WordCamp at all than to have a poorly put together event that tarnishes a good brand.  This feels more like a con than a conference.

27
Mar

SSL Is Not An Adequate Site Identification System

Posted by Terry Smith on 03/27/2011 at around 7:24 PM

I’m back!  After over a year of this blog being down, being used a testing ground for new projects, and having no content, I’m hoping to make a return to semi-regular blogging.

To kick things off I want to discuss the fiasco that is happening with SSL.  A while ago, one of Comodo’s certificate authority servers which generates SSL certificates was hacked and used to generate real certificates for some top sites including Yahoo and Windows Live Mail, Google, and Skype.  Those certificates have now been revoked, and Comodo has blamed “evil” governments abroad, and the issue had finally started to blow over.

And then, today, an Iranian hacker came out claiming that it was him, a single person who had perpetrated the attacks and vowing more of them.  And this hacker is right about one thing: who knows how many of these happen non-publically.  Ars Technica says that the CA trust system is broken, and in part I agree.  But I don’t think the issue is trust from a root Certificate Authority to it’s resellers, I think the issue is that we use SSL as a site verification system at all.

SSL does a really good job with what it was originally intended for: encryption.  Data is encrypted on the client, decrypted on the server, and vice versa.  My payment information cannot be read by someone in between or who is monitoring data on an open wireless connection, and as we’ve all heard over and over again it would take 1000 servers a million years to crack the code (or something like that).

But then browsers and certificate authorities started using SSL as a means for verifying that the site they were connected to was the right one, which to me is a separate issue.  It was certainly a logical step at the time, and it makes sense that the actual site should be the only one who has an SSL certificate.  But with recent vulnerabilities like the NULL byte attack a few months ago, and this recent attack of “trusted” resellers and certificate authorities, I think it’s time to re-think the way we verify a site’s identity.

There’s a huge market opportunity here and now is the perfect time to capitalize on it (and I imagine it’s going to continue to be a good time until another solution comes along).  While I don’t yet have an idea on implementation, I will follow up if I do.

I’m excited to see what you guys come up with.

6
Aug

Programming your own PHP framework, Part 2

Posted by Terry Smith on 08/06/2009 at around 7:47 PM

Welcome back (or just plain welcome)! In the last part of our PHP framework exploration, we looked at URL rewriting.  Today we’re going to look at creating an MVC framework to wrap around your application.  I’ll be making reference to parts of the first tutorial to help us accomplish this.

To get things started, you should be familiar with the Model-View-Controller paradigm.  The basics components are models (classes/objects/etc.) that represent items in your application (users, database records, etc.), controllers which do the processing for a page or module and views, which contain the HTML/CSS for your output.  You can read more about it here

Step 1: Directory Structure

As noted in the last part, I have chosen to structure my URLs in the format domain.com/[controller]/[module]?vars.  In this case, the controller indeed represents the controller in the MVC paradigm.  I will take a moment to explain the directory structure I’ve used; again, note that you can use almost any structure for your own applications.

/config - Basic configuration files (database settings, etc.)
/controllers – Controllers are all in this directory.
/lib – Default library files included with every new site I deploy (database class, URL rewriting, templating and other base classes)
/models – Custom models for each application (users, sessions, etc.)
/views - View files (PHP files), that contain the HTML
/web – The actual web directory we point our web server to.

There are two things of note here.  First, our images, CSS, etc. go into our /web directory, since the web server can’t read anything above the /web folder.  Second, and most important, all of these files should be outside/above the directory you actually point your web server to serve files from.

Step 2: The only real file

So let’s start at the beginning, since that seems the most reasonable place.  Inside my /web directory, I have just one PHP file, index.php:

<?php
require(dirname(getcwd()) . "/lib/init.php");
RoutingController::getInstance()->route();
?>

As you can see, there isn’t too much to it.  You may note that we’re using a singletoninstance of the RoutingController; more on that later.  We’re including the initialization file that comes standard with each deployment.  This file will include all of the others and set up the rest of our system.  Note: make sure you have mod_rewrite enabled and the .htaccess file in place from the last part.

Step 3: Initializing the system

So, let’s take a look at that initialization file:

<?php
// Are we currectly in production?
define('PRODSERV', false);
// Directory definitions
define('ROOT_DIR', dirname(getcwd()) . '/');
define('LIB_DIR', ROOT_DIR . 'lib/');
define('VIEW_DIR', ROOT_DIR . 'views/');
define('MODEL_DIR', ROOT_DIR . 'models/');
define('CONTROLLER_DIR', ROOT_DIR . 'controllers/');
define('CONFIG_DIR', ROOT_DIR . 'config/');
define('TEMPLATE_DIR', ROOT_DIR . 'templates/');
// Set up the library includes
set_include_path(CONTROLLER_DIR . PATH_SEPARATOR . LIB_DIR . PATH_SEPARATOR . MODEL_DIR . PATH_SEPARATOR . get_include_path());
// Include database settings
$dbini = parse_ini_file(CONFIG_DIR . 'database.ini');
// Get our connection to MySQL
$mysql = MySQL::getInstance();
$mysql->initialize($dbini['host'], $dbini['username'], $dbini['password'], $dbini['database']);
// Make sure we can autoload files
function __autoload($class)
{
        require("$class.php");
}

Let’s go through this part by part.  The very first thing we do is create a define called PRODSERV which represents whether we’re running in a production environment or not.  If we’re not, we can output error information, but we certainly wouldn’t want that in production.  Next, we define all of the directories where our various files reside and make sure to let PHP know where they are by temporarily changing the include path.  We can then load the database settings (I’m using INI files for ease of use, you could also use XML, etc.) and tell MySQL to connect (or whatever database you’re using).  Finally, we’re setting PHP’s __autoload variable to autoload classes with the simple [ClassName].php naming system from anywhere in our include path.

Step 4: Routing to a controller

Alright, on to the meat.  This is going to be the longest step by far so hang on!  Next up, our RoutingController class (located in my install at /lib/RoutingController.php).  The route() function in our index.php class was actually covered in our last section:

$path = parse_url(
     (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' .         // Scheme     
     $_SERVER['PHP_AUTH_USER'] . ':' .                               // User     
     $_SERVER['PHP_AUTH_PW'] . '@' .                                 // Password     
     $_SERVER['HTTP_HOST'] .                                         // Hostname     
     $_SERVER['REQUEST_URI']                                         // Path and query string
);
$temp = explode("/", substr($path['path'], 1));
$controller = strtolower((@$temp[0]) ? $temp[0] : "welcome");
$module = strtolower((@$temp[1]) ? $temp[1] : "index");
if(!file_exists(CONTROLLER_DIR . "{$controller}Controller.php")) {     
     $controller = "Error";
     $module = "index";
}if(!method_exists("{$controller}Controller", "{$module}Handler")) {
     $controller = "error";
     $module = "index";
}
$class = $controller . "Controller";
$controller = new $class($controller, $module);
$method = "{$module}Handler";
$controller->$method();
$controller->render();

Basically, we’re tearing apart the URL and redirecting control to a Controller.  So let’s take a look at the Controller base class, from which all of our other controllers will inherit:

<?php

class Controller {
        private $Template;
        protected $vars = array();
        private $Controller;
        private $Module;

        function Controller($controller, $module) {
                $this->Template = new Template;

                $this->Controller = $controller;
                $this->Module = $module;
        }

        function get($var) {
                if(isset($_GET[$var]))
                        return($_GET[$var]);
                return(false);

        }

        function post($var) {
                if(isset($_POST[$var]))
                        return($_POST[$var]);
                return(false);

        }

        function cookie($var) {
                if(isset($_COOKIE[$var]))
                        return($_COOKIE[$var]);

                return(false);
        }

        function setLayout($layout) {
                $this->Template->setLayout($layout);
        }

        function redirect($controller, $module) {
                if(strcmp($module, "index"))
                        header("Location: /$controller/$module");
                else
                        header("Location: /$controller");
        }

        function render() {
                // Set our template variables first
                foreach($this->vars as $key => $value)
                        $this->Template->set($key, $value);

                // Render
                $this->Controller = strtolower(substr($this->Controller, 0, 1)) . substr($this->Controller, 1);
                $this->Template->render(VIEW_DIR . "/{$this->Controller}/{$this->Module}.php");
        }
}

Again, we’ll walk through it bit by bit (function by function in this case).  We start off with our constructor, which saves the controller and module that are being called and initializes our template class (which we’ll look at in the another part).  Next we’ve defined wrapper classes around our get, post and cookie variables.  The reason for this is that while I’m not doing it here, you can preform various sanitizations on the values getting returned.  We define a wrapper function to make things a little easier for our users for the template in setLayout.  The only real use for this is if we want to disable any page layout (again, more on this in our section on templating).  We also define a redirection function to redirect internally (adding support for external redirects will be left as an activity for you).  Finally, we have created a render function which was called from our RoutingController which passes set variables into the template and then tells it which file will generate the content for the layout.

Whew!  It’s a lot, I know, and I’ve tried to compress is as much as possible.  But keep on trekking, we’re almost there.

Now we’ve got URL re-writing and our basic routing system and controller base class set up.  So let’s look at an actual controller.  We will define a basic “welcome” controller I will include with every default deployment of this system.  This file will therefore be located at /controllers/welcomeController.php:

class welcomeController extends Controller {
        function indexHandler() {
                $model = new SomeModel;
                $this->vars['title'] = 'Welcome';
        }
}

This controller illustrates several things:

  1. The class name and file name must be the same.  This is because in our __autoload call in our initialization file, we told it to look for [controller]Controller in the file with the same name. 
  2. Our module name must be in a function called [module]Handler.  As I’ve said throughout this entire series, this is simply a design decision on my part and is located in the RoutingController::route function. 
  3. The default module, as defined in the same route function is “index” so if there is no module (ie. domain.com/welcome) it will be sent to the function indexHandler().
  4. Variables passed in to our template will be located in $this->vars.  These variables will be passed into our layout and our controller/module template.  In this case, we’re passing the page title in as a variable called “title”, therefore we set $this->vars['title'].

Step 5: Models and Views

This will be a short section, mostly because Models will be covered in more detail when we look at database abstraction and we’re going to cover views when we look at our template system.  But let’s take a quick peek nonetheless:

Models are our custom classes.  So users, sessions, database records, etc.  All of our models reside in our /models directory.  Let’s take a look at our default model (for fun, defined at /models/Default.php):

class Default extends MySQLObject {
}

As you can see, we’re creating a Default class that extends our MySQLObject base class to be discussed later.  Simple as that!

Next let’s take a quick look at a view.  The corresponding view for our welcomeController::indexHandler function can be found at /views/welcome/index.php.  This can include an entire HTML file, but as you’ll see later, our template class wraps whatever is in this file in a layout that is standard to all views.  So let’s take a look:

<h2><?php echo $tpl_vars['title']; ?></h2>

This is the default welcome view file for each deployment.  Edit away!

Like I said, super simple.  However, you can see our template variable being used!

Step 6: Keep going!

This entire process has been trial and error for me, and as I said in the last section, I am by no means an expert in these subject.  But I haven’t seen a good guide on doing this sort of stuff yourself and I hope that you can take what I’ve presented here and keep going and create new and even more wonderful things.

In our next sections, we’ll cover database abstraction and templating!

29
Jul

Programming your own PHP framework, Part 1

Posted by Terry Smith on 07/29/2009 at around 2:33 PM

I’ve always been torn about posting code on this site, since I’ve historically (if I can use that word) wanted to keep it about business ideas.  However, since I’ve started working for b5media, I’ve had a lot less time to work on my own projects; therefore I think I’ll start talking about some code.

These posts are geared towards people who know programming (specifically to people who code in PHP, but if you can read the code, you can port it to most other languages).

As with most engineers, I like to re-create tools I use on a regular basis.  Some I’ve tried and failed at for various reasons (3D game engine), but one of the ones I’ve always wanted to try is a PHP framework of my own.  So last weekend, I sat down and wrote a basic framework that I would enjoy using.  This series of articles will talik about how I did that.  So, without further ado:

There are several components of a web framework: URL rewriting, database abstraction, an MVC framework, a templating system and plug-ins.  All of these are optional and you can pick and choose which you want to include in your framework and how you want to include them. 

In this first article, I will cover URL rewriting. 

The most important thing here is to remember that you can style your URLs in almost any way you choose.  In my case, I have elected to combine some of the existing frameworks’ systems and structure my URL in the form domain.com/controller/module?var1=value&var2=value.  This solves one of my personal pet peeves with existing frameworks.  Many of them are an either or (technically an exclusive or) system.. your GET variables are either all in the query (ie. domain.com/index.php?controller=test&module=function&var1=value&var2=value) or they are all in a directory format (domain.com/controller/module/var1/value/var2/value).  Most frameworks do a poor job of mixing and matching.

Step 1: .htaccess/mod_rewrite

Note: As you can see, I am gearing this tutorial towards what I know (Apache + PHP).  However, I have made the code as easy to read and understand as possible so that you can port it to other languages, web servers, etc.

The first step is to configure Apache to allow for our rewriting.  This is done through mod-rewrite, which on Apache 2+ can be enabled by going into the apache2/mods-enabled directory (on Debian systems usually located in /etc/apache2/mods-enabled) and create a symlink to the file ../mods-available/rewrite.load with the following command:

ln -s ../mods-available/rewrite.load

Now you can re-load Apache, and mod_rewrite should be enabled.  The second part of this step is to create an index.php file in your web directory and route all traffic through it.  To do this, create a .htaccess file in your web directory with the following inside:

<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^.*$ /index.php [L]
</IfModule>

This will route all traffic for non-existent pages and directories to index.php where we can parse the URL and route it appropriately. If you are having trouble getting this to work, ensure that you have the AllowOverride variable in your Apache configuration set to “All”.

Step 2: Parsing the URL

Open up your index.php file in your favourite editor (I still use vim).  Interestingly enough, the first step to deconstructing the URL is constructing it.  Since there is no since variable (that I’m aware of) to get the full URL, we need to put all of the info variables together first.  We can do that like so:

$path = parse_url(
     (isset($_SERVER['HTTPS']) ? 'https' : 'http') . '://' .         // Scheme      
     $_SERVER['PHP_AUTH_USER'] . ':' .                               // User      
     $_SERVER['PHP_AUTH_PW'] . '@' .                                 // Password      
     $_SERVER['HTTP_HOST'] .                                         // Hostname      
     $_SERVER['REQUEST_URI']                                         // Path and query string
);

Here, we’re using PHP’s parse_url function to break apart the full URL into parts that PHP can handle a little better.  Specifically, we can now break apart the file request:

$temp = explode("/", substr($path['path'], 1));
$controller = strtolower((@$temp[0]) ? $temp[0] : "welcome");
$module = strtolower((@$temp[1]) ? $temp[1] : "index");

In this case, I’m only allowing two parts to the URL: the controller and the module.  You could expand this to include any number of parts.  I am also setting the default controller and module so that a request to domain.com/ or domain.com/controller will still have a place to go.  I finally convert the controller and module to lowercase so that I can identify the file name there the controller lives (more on this in the MVC part of this series).

Finally, I can route this to a class/function.  In my case, I am going to send it to a class called {$controller}Controller and a function called ($module}Handler.  We do want to make sure that it’s a class we’ve defined in our directory structure as well, to protect again any vulnerabilties (so users can call any class/function)  So I want to make sure that those exist:

if(!file_exists(CONTROLLER_DIR . "{$controller}Controller.php")) {      
     $controller = "Error";
     $module = "index";
}
if(!method_exists("{$controller}Controller", "{$module}Handler")) {
     $controller = "error";
     $module = "index";
}

If it doesn’t exist, we re-direct this user to errorController class and the indexHandler function.  This class/function would ship by default with the framework and could be customized later.  Provided that it passes that test, we can finally send it off to the appropriate place:

$class = $controller . "Controller";
$controller = new $class;
$method = "{$module}Handler";
$controller->$method();

In this case, I am using PHP’s __autoload function to load in the appropriate files/classes (again, more on this in the MVC part).

Step 3: Explore

That’s it!  You have a basic URL re-writing framework.  There is obviously a lot more to come, but this should give you a taste of the flexibility a PHP framework can give you (especially one you’ve designed).

Feel free to explore all of the other options for structuring URLs your own way.  In the next part, we’ll cover the MVC framework so we can put this to good use.

Note: I by no means consider myself an expert in PHP.  I view these articles as equal parts instruction for those of you in the dark and learning opportunity for me.  Feel free to comment or critique, especially if you can make it faster/cleaner/more secure!

15
Jun

An Engagement Story

Posted by Terry Smith on 06/15/2009 at around 9:31 PM

So there it was, the big day. The day I popped the ultimate question and asked my then girlfriend to become my then fiancee (now wife). I was living in San Jose, California, life was good and Ashlyn was coming to visit for a few days where we would enjoy the beach and check out Disneyland. Sound romantic? Well I’m getting ahead of myself; it was actually the day before I was going to ask the question and I didn’t have the ring. Yup, you read that right: on the day I proposed, I didn’t have the ring to propose with. It was back ordered. I had a ring (Engagement Ring Jr.), but not the ring.

By the time we got back to my apartment after I picked her up from the airport, she was tired and just wanted to pack for our trip to Disneyland and go to bed. Unbeknownst to me, she goes to the bedroom and begins to empty out my suitcase (where, being smart, I had “hidden” the ring). So as soon as I heard the unzipping of the bag, I ran to the bedroom as she was reaching into the “hiding” spot and, in true Terry style… I tackled her.

Yup… tackled.

She had found the box; no definitive proof of what it was (she suspected), but she had felt it and, based on my response she knew it was probably something for her. So I had to improvise. Ashlyn had brought down a summer dress (her “California dress” she called it) so I asked her to go into the closet and put it on.

The closet. The bathroom was open, but the closet seemed more appropriate for some reason. Please don’t ask.

It was a walk in closet so we closed the large mirrored door so that she had enough light and still couldn’t see me and vice versa. So I got down on one knee and waited. When she finished changing into her California dress, I was waiting outside the closet on my knee with Engagement Ring Jr. and I asked her to marry me.

That sounds a little more romantic at the end right? Well it almost was. She got so excited that she forgot to say “yes” and kind of left me hanging for a few minutes while she danced around and cried a little before I asked “Soo… is that a yes?”. And it was!

The end result was the same, but it was the method of getting there that makes the story.

8
May

Wordcamp Toronto 2009 Presentation

Posted by Terry Smith on 05/08/2009 at around 4:03 PM

I’ve posted my presentation from Wordcamp Toronto 2009 on buddyPress/bbPress integration below.  I will be making more posts in the next little bit about some of the content and going over my talk, but the presentation itself is in high demand, so voila!