After many weeks of developing in my free time, I can finally announce a new Talkbackr feature.

For those of you who don’t know anything about Talkbackr, it’s a website (talkbackr.com) that allows for free, anonymous feedback to organizations for events. Let’s say your organization is putting on a production of Romeo & Juliet. You can create a free event in Talkbackr, then give out the URL to your audience, and they can sign into Talkbackr later and give anonymous feedback. It’s 100% free.

There is a premium section that provides some completely optional features, but they are by no means required to partake fully in the Talkbackr experience.

So that sounds great, right? Free, anonymous feedback. Well, I got to thinking. Why should you have to send your audience to my site to do that? Why not just get them to leave feedback via Facebook? And that thought led to other thoughts, and those thoughts to other thoughts, and those thoughts led to me being hungry because thinking is hard work, and that hunger led to pizza, and my sated hunger led to other thoughts, and then THOSE thoughts to action, and then…

Introducing the new Talkbackr Facebook Widget.

The idea is simple. It boils down to this: you can set up a Talkbackr Now! tab on your organization’s Facebook page (because, let’s face it, every organization has one, and if you don’t have one — GET ONE), and then your audience can leave feedback via that tab instead of having to leave Facebook. It’s the ultimate in convenience.

So how do you sign up? It’s really simple and can be done in three easy steps:

1) Sign into your Talkbackr account and go to the My Account section. There is a box that says “Get your Facebook Widget API Key”, and underneath it provides an API key.
2) Follow the three steps under the API key. (Recursive steps, oh my!.)
3) Shoot me an email with photos of you and your organization flipping out about how awesome the new Talkbackr Facebook Widget is.

Okay, you don’t have to do the third step. But do let me know if you have any questions or comments or whatever. I’m excited about it, and I think you guys will be to.

Enjoy!

P.S. This is totally in BETA. That means there are bugs. If you report them to me, I will fix them as soon as I can.
P.P.S. Regular website widget to come soon. (And by “soon” I mean whenever I get around to it, which depends entirely on how successful the FB widget is, so… get crackin’, people.)

Yesterday I talked about various kinds of websites and what the differences are. I also very briefly touched on why each one has its varying levels of complexity. There are some things, however, that many people don’t seem to understand about web development — specifically, how complex many seemingly simple tasks are.

Let me try and explain. I will attempt to use my thought processes when I build a website to show you the steps I take to build this kind of feature. Quite literally, these are steps I have to take every time I build a website.

One of the most simple and common tasks on any website is the ability to create an account and log in, right? Every website does it: Facebook, Twitter, Google, Amazon, ThinkGeek, Lifehacker, Etsy,… I don’t need to go on. You all have logged in to numerous sites. If every site does it, it must be simple, right?

Wrong.

In order to have a log-in system, users must first be able to create an account. This requires the following things:

1) Some way to keep track of existing users (a database)
2) A mechanism to accept input from the user (the form)
3) A process to insert the input into the database.

That seems simple enough, but it’s really not. Each of those steps has many (possibly dozens) of steps to do them. Let’s look at Step 1: Database.

Step 1: Database

There are many, many, many kinds of databases out there, but detailing those is out of the scope of this post. Instead, I will simply tell you that my preferred database is mySQL (pronounced “my sequel”), mainly because it’s free and very widely supported.

The first thing we need to do is create a database. Depending on the web host, this may be easy or complicated. In my case with Dreamhost, it takes me roughly 20 minutes to log in to their system, create a database, and then wait for it to show up on the server. I have to decide the name of the database (which has to be unique), which of my user accounts can access it, and on which hostname (e.g. databases.brianseitel.com) it would reside.

Once the database is created, I have to create something called tables. One of these tables will be the User table. This contains every bit of data that we have about any individual user. For a basic login system, we need three things:

1) A unique User ID (so that I can conclusively identify this user no matter what)
2) An email address (or username… I find it’s easier for users to remember their email addresses, but whatever works)
3) A password
4) (optional) The User’s name (e.g. Brian Seitel)

If we wanted more data, we’d have to add more fields. Now I have to think about what kind of fields are these. Are they integers? Are they strings? Are they booleans (true/false)? How long might the values be? And based on the answers to these questions, I would draw the following conclusions:

1) User ID (integer: max of 11 digits long)
2) Email (string: max 255 characters)
3) Password (string: max 255 characters)
4) User’s Name (string: max 255 characters)

I tend to default to 255 characters, but in larger, enterprise-level applications, you might restrict an email address length to 64 characters. It’s just faster for a database to search for it if the strings are shorter. But anyway…

I’ll skip the code to generate the tables, but suffice it to say that this process would take another 15-20 minutes to do. The more fields we have, the more thought and work I have to put into it.

Now that the database is created, we can move on to step 2.

Step 2: The Form

The form is what you, the user, sees. This is where you put your email address and password. It contains three labels, three text fields, and at least one button (usually Submit and sometimes there is a Cancel button). Often there is a link nearby that says “Forgot your password?” and takes you to another form to recover forgotten or lost passwords.

Let me show you a really quick, basic, unstyled set of code for a basic form.

This code turns into this:


As you can see, this is a rather simple form. There are many other things that I would normally add to this form, such as Javascript validation (to make sure you actually entered an email address and not something else, or that your password is at least 6 letters long or something like that). I would also have to have some PHP conditionals to be able to tell whether your password was invalid or whatnot. We’ll get to that in a bit. Anyway, for a basic form, this is it.

This maybe takes me 30-45 minutes, including styling (making it look pretty — unstyled forms look like shit).

But now that the form is ready, we can move on to Step 3.

Step 3: Form Processing

If you’ll look back up at Step 2, the

FORM tag has an action attribute that refers to “contact.php”. This is where the form is sending the input data for processing. In our contact.php file, we need to do several things:

1) Check to make sure we received input at all
2) Validate the input (make sure the email address is an email address)
3) Sanitize the input (make sure the input won’t screw up our database)
4) Check to make sure the email address doesn’t already exist in the database (existing user)
5) Connect to the database
6) Build a SQL query to insert the new user into the database
7) Verify the response, and if successful, authorize the user
8) If unsuccessful at any point in Steps 1-7, redirect back to the login screen with an error message
9) If successful, redirect to “My Account” page (or whatever)

Wow. That’s a lot of steps. Let me write some quick code to show you what this file might look like.

<?php    // Connect to Database
$db = new mysqli(DATABASE_HOST, DB_USER, DB_PASS, "user");         

// Check to see that we got input. If not, redirect back with error message
 if(empty($_POST['email']) OR empty($_POST['password']) {
       header('location:/signup?error=empty'); exit;
}     

// We got input. Let's put them in some easier-to-read variables
$email = $_POST['email'];
$password = $_POST['password'];
$confirm = $_POST['confirm_password'];     

// Check to see if $password and $confirm_password are the same. If not, redirect with error.
if($password != $confirm) {
     header('location:/signup?error=password_mismatch');
     exit;
}    

// Validate email address to make sure it's actually an email. Use a REGULAR EXPRESSION.
if(eregi("^[_a-z0-9-]+(\.[_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*(\.[a-z]{2,3})$", $email) == FALSE){
    header('location:/signup?error=invalid_email');
    exit;
}     

// Sanitize the input to make it safe for Database entry
$email = $db->real_escape_string(htmlentities(strip_tags($email)));

    // Encrypt the password -- we don't want to store "letmein" as a password. If someone hacks into our database, they could see it in plain english! Instead, encrypt it to look more like '53234nadsfaw351afgaha131ga'
    $password = md5($password);

    // Check to make sure email address doesn't already exist
    $sql = "SELECT * FROM user WHERE email = '$email'";
    $query = $db->query($sql);
    if($query->num_rows > 0) { // Found it
        header('location:/signup?error=exists');
        exit;
    }

    // Insert the user
    $sql = "INSERT INTO user (email, password) VALUES ('$email', '$password')";
    $query = $db->query($sql);
    if($query) { // Successfull
          $user_id = $db->insert_id;
          $_SESSION['authorized'] = true;
          $_SESSION['active_user_id'] = $user_id;

          // Redirect to My Account or Dashboard
          header('location:/dashboard');
    } else {
          // Failed for some reason, possibly invalid SQL string
          header('location:/signup?error=failed');
    }

Whew! That’s a lot of code. And that’s just for a very basic form. On many registration forms, you’re also asked for address, zip code, state, city, date of birth, etc. All of those things need to be validated (make sure that date is actually a date!), sanitized, inserted and verified. It’s a very time consuming process. This particular task would take me roughly 30-45 minutes given this simplicity. For more complicated forms, it could take even longer. Much longer.

A few things before we go on. If you look at the end of each IF statement, there’s something that looks like this:

   header("location:/signup?error=exists");

The “error=exists” part is a GET variable that we can post back to the Signup page. On the signup page, I would have to have ANOTHER series of IF statements to check to see which error message we got back, then display that message to the user. See? Not so simple!

Who knew Signup Forms were so complicated?

Summary

Please keep in mind that this was a very, very simple example of a very, very simple task. Many other tasks, such as shopping carts, image galleries, and other things are much, much more complicated and take much more time.

Think about your favorite websites. Every time you click on a button, something is getting processed, much like Step 3. Simply putting the button there takes planning, foresight, and time to execute it properly.

Finally, look at the code above and think about how much you would have understood if I hadn’t explained it or commented it for you. It’s a lot harder than it looks — especially that email validation code! This is just a glimpse at the expertise that you are paying for. I know all of the steps and can perform them all. Can you?

Didn’t think so. I vaguely know where the oil comes out of a car, but I don’t know all the details and I certainly don’t know enough to do it quickly, efficiently, and correctly on the first try. That’s why I hire a mechanic.

And that’s why you should hire a professional web developer to build your websites. It may seem expensive, but that’s because there is a LOT of thought going into making your website solid and professional, and a lot of expertise to get it done correctly and efficiently.

I hope this helps you better understand why hiring professionals is so important, and I especially hope it helps you appreciate all the hard work they do. The prices we charge are (generally) very justified, given all the things that must be done for even the simplest of tasks to work properly.

Thanks for reading, and have a nice day. :)

Website Economics 101

February 25, 2011

People ask me all the time, “Brian, how much does a website cost?” This is a very complicated question, and I’ve recently taken to responding thusly:

“How much does a car cost?”

Their eyes glaze over for a second, then the connection hits them and I hear an inevitable “Ohhhhhh.”

There are, of course, many different kinds of cars for many different kinds of needs. A single bachelor might want a two-door Mustang, while a mother of four might want a van or SUV. For each of these needs, the first question is rarely “how much does it cost?” but rather “What do I need?”.  Likewise on the web, there are many different kinds of websites, from simple splash pages to blogs to social networks to complicated e-commerce stores. Each of these (very broad) categories encompasses a different set of needs for the client, and as a result, each of these different categories will cost varying amounts of money.

Like a car, the simpler the website is, the cheaper it will be. The more frills, interactivity and other features you have, the more expensive it will be.

But let’s look at the types and see if we can lay out some ground rules for what the different kinds are and what they need:

Splash / Portfolio / Brochure sites

Splash pages, portfolio sites and brochures sites are the simplest websites there are. They are essentially the website equivalent of a business card. They say “Hey, here’s who I am and what I do.” That’s it. Just imagine these as billboards for the internet.

These kinds of sites are relatively simple for a few reasons. First, they tend to be static pages. By static I mean that the content doesn’t change much, if at all. This is kind of like buying a painting. You buy it once, you hang it on the wall, and it doesn’t change until you decide you want a new painting (which, of course, costs more money).

Time: I built my portfolio in about 15-20 hours.

Blog or Similar Dynamic Websites

The term “blog” is short for “web log”. Most of us have at least heard of what a blog is. You’re reading a blog right now. A blog is basically an online journal or diary, in which an author writes an article (or “blog post”) for others to read. Since there are dozens and dozens (if not hundreds) of blog platforms out there, the main task is to customize the look and feel of the website to fit the owner. A sharper, more unique design will cost more than a basic template.  The key difference between a blog and a splash/portfolio/brochure site is that blogs are dynamic. That is, the content changes on a regular basis. This means some sort of submission mechanism, some sort of database, and something that allows only the authors to sign in and write.

This would also include your basic business website. These websites often have some sort of product listing that needs to be updated by the owner of the website without having to call the web guys every time something changes. A good example of this is a restaurant, and a good example of a restaurant with a website is The Cosmic Deli in Alpharetta, GA. They have a menu that they can update on their own without calling their web guys, which, while it costs more up front, saves them tons of money later.

There are pre-fab CMS (content management systems) out there. My blog is powered by WordPress, a blog-oriented CMS. It can be repurposed to do other things, but that is a ton of work and really falls under a more complicated heading and would cost much more. If you are satisfied with a pre-fab template, then a developer can hook you up with a minimally customized WordPress blog for pretty cheap. Anything else will cost extra.

Time: Cosmic Deli took about 40 hours of work on my part (not including design, meetings, etc).

Social Media Oriented Sites

I don’t really mean Facebook or Twitter when I talk about this. Very few people can afford to literally build a social network like those from scratch. Even Diaspora, an up and coming Facebook alternative had to raise upwards of $300,000 to even begin development. I’m amazed at how many people request “a Facebook clone” and then set a budget of less than $10,000. I laugh at them. Quite bluntly, you can’t afford what it costs to build a social network like Facebook, so we won’t even address it.

However, there are other types of social media-oriented sites.  What I mean by a “social media oriented site” is something along the lines of My Life Is Average or Coffee Experiences. These websites involve a social gathering of online people that come together to discuss, share and explore a specific topic (or series of topics). The primary feature of these kinds of sites is interactivity (i.e. users can join and post content). User-generated content is REALLY complicated for a variety of reasons, the least of which is validation to ensure that the user is submitting what they said they were submitting. For instance, you don’t want a website geared toward stock photography for educational institutions to be full of pornographic images. Or if you take Coffee Experiences as an example, you don’t want someone submitting Blockbuster Video as a store, since Blockbuster doesn’t deal in coffee. Building in the features to detect, block, remove and prevent those kinds of submissions is complicated and critical.

These websites are going to be far more expensive than a blog or brochure website. These kinds of websites demand a custom CMS, which for reasons many and varied (including those above), are very complicated. This requires a developer with a certain level of know-how. Your nephew isn’t going to be able to build this. This calls for a master programmer.

Time: Coffee Experiences took roughly 40 hours of development time. It’s a little on the simpler side, though.

E-Commerce Sites

The first thing that should pop in your mind when you think of an e-commerce website is Amazon.com. They’ve pretty much got the e-commerce thing perfected. Other e-commerce sites include eBay, Threadless.com, and Off Book Market.  These websites all have one thing in common, and the phrase “e-commerce” should be a dead giveaway as to what that is: they all deal with money. Specifically, each deals with transactions of money in exchange for a product or service.

Now just imagine this: would you feel comfortable giving your bank account number to a stranger on the street? No, of course not. You need to ensure that your money is safe, that the people you are dealing with are reputable, and that you won’t be ripped off. These kinds of assurances require a Secure Socket Layer (SSL), some sort of payment mechanism, and encryption to ensure that your private, personal information isn’t leaked to the general public.

And guess what: those protections cost money. A lot of money.

Then imagine the sheer number of products on Amazon. Or even smaller, look at Off Book Market. Off Book Market currently contains roughly 50 plays on the market. Each play has an author. And each author and each play has its own page dedicated to information about that author or playwright. Not only that, but each of those pages links to a number of other pages that are related (e.g. other plays by that author). Then you have search pages, purchase pages for each of those plays, etc, etc. It goes on and on.

Very quickly, we’re dealing with literally hundreds, if not thousands, of pages that have to be built for the catalog to be complete.

Now sure, there are pre-packaged e-commerce solutions out there that can reduce the complexity, but more often than not, they won’t save you that much money. The reason is that every business is different, and therefore every website is different. Imagine buying a Ford F-150. This is a pick-up truck that is very popular because it can suit a variety of different needs, from grocery shopping to driving to work to moving furniture. But let’s say you want to use it to carry your spouse and three kids over the river and through the woods to Grandma’s house for Christmas: how much would it cost you to add enough seats and room to fit all of you, plus luggage and gifts? Probably more than you’re willing to spend.

Likewise, most pre-packaged e-commerce solutions are built for a specific purpose and it’s usually rather hard to customize. Developers have to make a choice between extensibility and features, and usually features win. This means customizing something like that requires hiring experienced developers, and experienced developers equal more money.

Bottom line: E-commerce sites are expensive. Very expensive.

Time: Off Book Market took me over 200 hours to develop, and I’m still building it.

So what now?

The next step, of course, is to decide which website you want, then talk it over with your developer. Developers charge in two ways: hourly rates and project-based rates. If the project is rather simple, the developer will often charge a project rate (say, $500 for the entire thing). If it’s more complicated, then the developer would likely charge an hourly rate. This is to protect the developer.

Imagine if I asked you to bake a cake. You say you’ll do it for $20 because you think it will take you two hours. Now let’s imagine that you start baking the cake, and then you realize that the customer is lactose intolerant. You have to spend more time to find a recipe that will make a cake without using dairy products. Then you have to go buy the new products (let’s assume the price is negligible for the sake of argument). By the time you’re done baking the cake, it has taken you four hours — twice what you originally intended!

For this reason, if a project is complicated or there are special requests, developers will often charge an hourly rate.

So how much is that?

That’s a tricky question and it varies from developer to developer. My standard rate is $60/hour for freelance work. Depending on the project and how excited I am about it, I may lower that rate. If I really like you, I may do it for a project-based fee. But most of the time, it’s $60/hour. And that’s just for regular web development. I charge $100/hour for iPhone development (it’s much harder, and it’s a much rarer skill). Other developers may also do design as well, so their rates will be much higher.

And then you might consider a business, which could charge upwards of $200/hour! Keep in mind they have to pay both the developer AND the designer AND the project manager AND… well, the list goes on…

Why are these rates so high? For a few reasons: 1) it’s not as simple as waving your hand and making a website appear. It takes work — real work. 2) You aren’t just buying a product; you’re buying a service and the expertise of the people involved. We are experts. We know what works, what doesn’t work, and why. We do this all day. I wouldn’t presume to tell a mechanic how to fix my car. That’s why I hired him and pay him the big bucks — because he knows more than I about cars.

If you have any more questions about the economics of a website, let me know. The above numbers are merely guidelines regarding someone of my skill and experience level. For someone who is much newer to web development, prices will be lower, and for someone with many more years of experience than I have will be much more expensive.

The key point to remember is this: you get what you pay for. Seriously. You do.

Using cURL in PHP

February 23, 2011

Let’s be honest, folks. Nobody likes data entry. It’s the most boring thing on the planet. That’s why Al Gore invented the Internet — so we can steal other people’s data!

There are many ways to do this, of course, but today we’re going to focus on PHP’s built-in support for cURL, a library that allows PHP to get information from another server. This is primarily useful for APIs (Application Programming Interfaces), but it could also be used to grab RSS feeds (think Google Reader) and email. There are a billion possible applications, but today we’re just going to do a pretty simple one.

There are several types of requests that one can make via cURL, but we’re going to focus on two: GET and POST.

GET Requests

A GET request simply means that we’re passing information to the server via the URL. A GET request would look like this:

http://www.example.com?id=555&format=json

You can see very clearly that the URL is followed by a question mark. This indicates that there is additional GET data being passed. The following information is presented in the format of KEY=VALUE, where KEY is the field and VALUE is… well, the value. In the above example, we have passed in two separate values: an ID of 555 and a FORMAT of json. The server on the other end would process these parameters and spit out the results for ID #555 into a JSON format.

As you can see, the GET parameter is very easy to build: simply append the values in KEY=VALUE format, separating each pair with an ampersand (&). Easy, right?

There are some limitations to GET requests. For one thing, they’re not very secure. Imagine if I were to do this:

http://www.example.com?username=camel&password=abc123

See the problem? If someone were to glance at this URL, they could easily see that the username is “camel” and the password is “abc123″. That’s not very secure, is it?

Another limitation is that there are size limits to GET requests. URLs can only be so long before servers will truncate and ignore them. That’s why God invented POST requests.

POST Requests

A POST request is similar to a GET request, but instead of appending the fields to the URL, we’re going to build an array and then pass the values through the array. First, let’s set up a simple array using the first example above:

$params = array("id" => 555, "format" => "json"); 

What that does is create an array that contains the same values as above, but instead of appending the values to the end of the URL, we’re going to silently, invisibly pass these to the server. In other words, it won’t be immediately visible in the URL, and so is a little bit more secure.

There are, of course, ways to view POST parameters and such, so this isn’t perfectly secure, but it’s more secure than throwing things at the end of the URL. And this also neatly sidesteps the size limitations — a POST request can be as long as you want it to be.

Now the cURL part

Now that we understand the differences between GET and POST requests, I’ll show you a quick example of each. First, the GET request:

$url = "http://www.example.com?id=555&format=json";
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION , 1); // TRUE
curl_setopt($ch, CURLOPT_HEADER      ,0);  // DO NOT RETURN HTTP HEADERS
curl_setopt($ch, CURLOPT_RETURNTRANSFER  ,1);  // RETURN THE CONTENTS OF THE CALL
$results = curl_exec($ch);

That’s it! Now let’s go over this in a little bit more detail and maybe figure out what the heck is going on here. The first line is obviously the URL that we used for the GET example earlier. It’s just the URL with the field pairs appended at the end.

Then we start the cURL object ($ch):

$ch = curl_init($url);

This initiates the cURL object and sets the target as our URL. The $ch cURL object will be used for the rest of this transaction. What follows next are three options:

curl_setopt($ch, CURLOPT_FOLLOWLOCATION , 1); // TRUE
curl_setopt($ch, CURLOPT_HEADER      ,0);  // DO NOT RETURN HTTP HEADERS
curl_setopt($ch, CURLOPT_RETURNTRANSFER  ,1);  // RETURN THE CONTENTS OF THE CALL

The curl_setopt() method sets the options for the cURL Object. I’ve shown what each option does based on the value provided. Sometimes these values will change. For this particular request, we want to receive data back after we placed the GET request. Since we want to receive data, the CURLOPT_RETURNTRANSFER is set to 1 (true). Now we can get the data by executing the cURL request, like so:

$results = curl_exec($ch);

Once we execute the cURL request, it calls the URL that we declared in the curl_init() method, sets up the options, sends the request, and since CURLOPT_RETURNTRANSFER is set to true, it grabs the results and sticks them in the $result variable.

Now we can use the $results variable to do whatever we want with the data. If it’s simple a string, maybe we want to echo it. Whatever it is, it is now within our grasp.

POST example

The POST example is almost exactly the same as the GET example with two minor changes. First, the full POST code:

$url = "http://www.example.com";

$params = array(
"id" => 555,
"format" => "json"
);

$ch = curl_init($url);
curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
curl_setopt($ch, CURLOPT_FOLLOWLOCATION , 1); // TRUE
curl_setopt($ch, CURLOPT_HEADER, 0);  // DO NOT RETURN HTTP HEADERS
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);  // RETURN THE CONTENTS OF THE CALL
$results = curl_exec($ch);

The first major difference you’ll notice is that the URL does not contain any key-value pairs. That’s because we’ve stuck them into the $params array, much like the POST Request example above. Again, we initiate the cURL object, and then we come across the second major difference:

curl_setopt($ch, CURLOPT_POST, 1);
curl_setopt($ch, CURLOPT_POSTFIELDS, $params);

This time we’re setting two new options: CURLOPT_POST and CURLOPT_POSTFIELDS. Since we set CURLOPT_POST to 1 (true), then we’ve told the cURL object that we’re making a POST request (it otherwise defaults to GET). The second line should be self-explanatory: it attaches the POST fields — in this case, the $param object.

Finally, we request the results, execute the request, and store the results in the $results array, much like before.

I hope this was informative and useful. This is a very basic example of using cURL, and you can certainly find much more detailed information by visiting PHP.NET’s excellent documentation here.

I’m really excited about PayPal’s new “Express Checkout for Digital Goods” service and how I can apply it to Off Book Market and other services that I maintain. Currently, I’m using PayPal as the merchant gateway for OBM. Their normal fee is 0.29% + 30 cents (on a $5 purchase, that works out to 45 cents or so — or 9% of the total cost). With the Digital Goods service on Paypal, it offers a smaller rate for “microtransactions” or “micropayments” — any transaction less than $12.

Why is this good? Well, for purchases under 12 smackers, the rate changes to 5% + 5 cents. On a $5 transaction, that works out to 30 cents (or 6%).

That’s 15 cents (or 3%) extra hat I can apply toward other goals — either more $$ for playwrights, covering hosting/service-related costs, and maintenance. Another option would be to allow me to offer sales on OBM (which is currently not possible, given the way the fees are distributed).

At any rate, it’s an exciting feature. I hope you agree :)

Note: If you’re not a programmer, you won’t be much interested in this, though if you do decide to continue reading, it may give you a hint as to why websites are so expensive.

It seems like every website these days has social media integration. On some websites you can simply “Like” something and have it shared on Facebook, while on others they actively pull your information from Twitter to create accounts for you. In some cases, they will even allow you to post custom messages or ask for the authority to autonomously post information to social networks in your name. These things are ubiquitous on the web, especially when it comes to the successful games like Farmville and its ilk.

So how do they do this? Websites utilize a special interface called an API (Application Programming Interface) which allows the website to access information from the server. Some APIs are open and require no authentication, but many, especially those that contain private or sensitive data (such as Facebook), require some sort of authentication. The current standard method of authentication on the web is known as OAuth.

What is OAuth?

OAuth stands for Open Authentication. It’s a method of verifying the identities of those involved in secure transactions. Three-Legged OAuth is the most common, and the process goes something like this:

User: Hey, I want to share this on a service.
Consumer (website): Hey Server, I got a user who wants to use your service.
Server (e.g. Twitter): Great! Give them this Request Token so I know they came from you.
Consumer: OK, click this link and sign into the server with this Request Token and tell Server that you’re okay with this.
User: Hey Server, here’s Consumer’s Request Token and I’m okay with this.
Server: Great! Give this Access Token to the Consumer.
Consumer: Hey Server, I got this Access Token. Is this the right one?
Server: Yep! Have a great day!
Consumer: All right, User. You’re authorized! Let’s share your stuff!

As you can see from the “conversation” above, the server needs to verify the identities of both the User and the Consumer to ensure that both of them are who they say they are. You can read more about it (and how insanely complex and ridiculous it is) at Oauth.net.

The reality

The reality is that OAuth transactions rarely go so smoothly. The reason is that some services such as Twitter use the full OAuth process, while others such as Facebook only use parts of the OAuth process. At any rate, implementing OAuth is often a huge headache to many programmers.

My Solution

I’ve written a handful of classes that you can use to connect to Facebook, Twitter and Google. Basically, I’ve locked down all the code that makes each of these connections possible and encapsulated them into a single file, so that all you really need to do is include the file, add a few lines of code in your existing website, and you’re good to go.

OAuth

The OAuth class is not of my own design. Honestly, I can’t remember where I got it, and the guy didn’t leave comments in the code indicating that he was the author. To whomever wrote this, if you want to let me know, I’ll give you credit.

At any rate, everyone who wants to do OAuth with PHP needs to download this file, and include it in your code, like so:

 include('OAuth.php');

That’s it. Moving on…

Facebook

I’ll start off with Facebook since it’s the most popular social network out there. Facebook kind of does a simpler handshake than the others, and they actually prefer that you use their custom FBML. That kind of stuff is more for people who don’t know much about programming, though, and it allows for really simple Like buttons and other similar widgets. When you use OAuth, you typically want more secure, more detailed information.

First, you need this file. Then you need to include it, of course, like so:

<?php
include('Facebook.class.php');

Second, you will need to register a new Application with Facebook. Once you do so, you will be given a Facebook App ID and a Facebook App Secret. These are very important. They identify your website with Facebook. Think of it as a username and password for your app. YOU DO NOT SHARE YOUR SECRET EVER! (That’s why it’s called a secret).

Once you have those, you need to define them in your code somewhere. You should know the best way to do this, but I generally define constants:

DEFINE("FACEBOOK_APP_ID", "1234567890");
DEFINE("FACEBOOK_APP_SECRET", "abcd1234efgh8910");

Generally on a website like ours there is a button or link that says “Connect to Facebook.” That link should go to a file that will instantiate the Facebook class and connect. Let’s call it “facebook_connect.php”. This file should look like this:

<?php
$callback_url = "http://www.example.com/facebook_callback.php";
$facebook = new Facebook(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, $callback_url);
$facebook->start();

You can, of course, replace FACEBOOK_APP_ID with $facebook_app_id if you’d rather just store them in variables. Depends on how your code is structured.

The first line sets the callback URL. This is important for Step 2, because it tells Facebook where to send the Access Token. The second line instantiates the Facebook class. It creates the Facebook object, setting the App ID and Secret internally for future use. The third line starts the connection process by redirecting the user to the Authorization page. This is where the User gets to sign in and “Allow” access for the app.

Now that we’ve sent the user to the Authorization URL, we need to create a Callback page for them to come back to.

Create a new file: facebook_callback.php

It should look like this:

<?php
$callback_url = "http://www.example.com/facebook_callback.php";
$facebook = new Facebook(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, $callback_url);
$access_token = $facebook->callback();

The first line does the same thing as it did earlier. The second line initiates the Callback sequence, which grabs the access token, makes a few more requests to verify its authenticity, and then returns the Access Token into the $access_token variable.

It’s up to you how to save this variable using the method of choice (e.g. database, cookies, session, etc).

Tada. Congratulations! Your user is now connected to Facebook via your web app!

What now?

Now you should have saved the user’s Access Token into a database, cookie or session somehow. This will ensure that you can make requests on behalf of this user from now on. Note: the access token is valid only for THIS user, not for any other.

First, let’s make a generic makeRequest method that will allow us to make a request on behalf of this user without repeating too much code:

function makeRequest($token, $url, $method = "GET", $params = null);
       $token = array("access_token" => $token);
       if(is_array($params)){
	    $params = array_merge($parameters, $token);
       } else {
            $params = $token;
       }
       ksort($params);

       if($method == "GET"){
            foreach($params as $key => $value){
                $url_params[] = $key . '='. ($value);
            }
            $url .= '?'.implode('&',$url_params);
       }
       $ch = curl_init();
       curl_setopt($ch, CURLOPT_URL, $url);
       curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

       if($method == "POST"){
            curl_setopt($ch, CURLOPT_POST, 1);
            curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
       }
       $response = curl_exec($ch);
       curl_close($ch);
       return $response;
}

This is a pretty straightforward class. It makes a cURL request and formats the parameters depending on whether we’re making a GET request or a POST request.

Let’s grab the information about this user from Facebook using this simple code:

$url = "https://graph.facebook.com/me";
$token = "ABC"; // Your stored Access Token for this user
makeRequest($token, $url, "GET");

The first line defines the URL to which we post our request. You can find a huge list of these in the Facebook API Documentation. The second line pulls our Access Token for this user. If you stored it in the database, you’ll have to make a database call to grab it. The third line, of course, uses our generic makeRequest function to make an API call using the above information. Since we don’t have any parameters, and they default to null, we don’t have to include the $params parameter.

The third parameter (“GET”) is important. Some Facebook requests require that you make a GET request (e.g. /me) and some require that you make a POST request (e.g. /me/feed). It depends on whether you’re READING or WRITING. The GET method is a READ action and the POST method is a WRITE action. Keep that in mind. The Facebook Graph API mentions which ones are supported. Anyway, I digress…

But what if we do have parameters? Let’s try posting something to our Facebook wall.

$url = "https://graph.facebook.com/me/feed";
$params = array("message" => "I'm using Brian's OAuth code to post this to Facebook!");
$token = "ABC"; // Your stored Access Token for this user
makeRequest($token, $url, "POST", $params);

You’ll notice there are three changes: I added “/feed” to the end of the URL. This tells Facebook that we want to post to the news feed. I added a line that defines what the parameters are, in this case the “message” is “I’m using Brian’s OAuth code to post this to Facebook!”. Finally, I added the $params parameter to the makeRequest method.

If you now run this code, it should post the message to your Facebook wall.

Here’s the final code in its entirety for you:

facebook_connect.php

<?php
DEFINE("FACEBOOK_APP_ID", "1234567890");
DEFINE("FACEBOOK_APP_SECRET", "abcd1234efgh8910");
include('OAuth.php');
include('Facebook.class.php');
include('functions.php');

$callback_url = "http://www.example.com/facebook_callback.php";
$facebook = new Facebook(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, $callback_url);
$facebook->start();

facebook_callback.php

<?php
DEFINE("FACEBOOK_APP_ID", "1234567890");
DEFINE("FACEBOOK_APP_SECRET", "abcd1234efgh8910");
include('OAuth.php');
include('Facebook.class.php');
include('functions.php');

$callback_url = "http://www.example.com/facebook_callback.php";
$facebook = new Facebook(FACEBOOK_APP_ID, FACEBOOK_APP_SECRET, $callback_url);
$access_token = $facebook->callback();

// Store $access_token using database call, cookie, or session

functions.php

<? php
function makeRequest($token, $url, $method = "GET", $params = null){
       $token = array("access_token" => $token);

	if(is_array($parameters)){
			$params = array_merge($parameters, $token);
    	} else {
    		$params = $token;
    	}
    	ksort($params);

    	if($method == "GET"){
	    	foreach($params as $key => $value){
	    		$url_params[] = $key . '='. ($value);
	    	}

	    	$url .= '?'.implode('&',$url_params);
		}
        $ch = curl_init();
        curl_setopt($ch, CURLOPT_URL, $url);
        curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);

        if($method == "POST"){
        	curl_setopt($ch, CURLOPT_POST, 1);
        	curl_setopt($ch, CURLOPT_POSTFIELDS, $params);
        }
        $response = curl_exec($ch);
        curl_close($ch);
	return $response;
}

get_facebook_info.php

<?php
DEFINE("FACEBOOK_APP_ID", "1234567890");
DEFINE("FACEBOOK_APP_SECRET", "abcd1234efgh8910");
include('OAuth.php');
include('Facebook.class.php');
include('functions.php');

$url = "https://graph.facebook.com/me";
$token = "ABC"; // Your stored Access Token for this user
$result = makeRequest($token, $url, "GET");

// Convert JSON result to array
$data = json_decode($result);

// Print data to screen
print_r($data);

That should do it. Of course, if you were so inclined, you could have an includes file that automatically includes the OAuth, Facebook and Functions class on every page, eliminating the need to include those each time. My framework does this automatically, so my code winds up having fewer lines than the above. However, in the interests of this tutorial, I’ve included those in each file.

I’ve set up a basic demo for you to look at to see how this works. Check it out here: DEMO.

Tune in next time when I go over how to use Twitter and OAuth using a very similar class.

Any comments, questions or suggestions? Hit me up in the comments below.

For the sake of argument, let’s assume that your production of Annie sucked.  The first night was sold out, because hey, everyone loves Annie, but after the first night, audience attendance dropped dramatically, and by the second weekend, you’d be lucky if you could get more than a dozen butts in the seats.  Obviously, this is a crappy scenario, and nobody wants that.

Most artists, though, don’t produce a show they know is going to suck.  With that in mind, it’s easy to see how an artist would be confused as to why people wouldn’t show up.  It’s a good show! The first thing you need to do is find out why it sucks.  And to do that, you need feedback.  There are, of course, different degrees of feedback — some more helpful than others.

Which would you rather hear:  “Your show sucked.” or “Your show sucked, and here’s why…”?

Obviously, nobody wants to hear either of those statements, but if we had to choose between the two, most people would rather hear the latter choice.  Why?  Because the latter choice offers reasons — it sucked because of THIS and THIS and THAT and THAT.  And once you know what those things are, it’s a billion times easier to step back and think “Hey, maybe they’re onto something that I didn’t catch.”

It’s notoriously difficult to get feedback in theatre.  Your family will tell you you’re wonderful (they have to), your colleagues will tell you it was good (so you won’t pan their shows), and random audience members will nod and smile and walk out.  There’s nothing wrong with these responses — your family should support you 100% and you can’t blame colleagues for being tactful (if not helpful).  But then the question remains: how do you get feedback?

Enter Talkbackr (http://www.talkbackr.com).

In recent debates about the problems facing theatre, one of the major issues seen by artists like Don Hall and myself is a lack of discussion about art.  When theatre companies converge, they tend to discuss money: fundraising, marketing, ticket prices.  Go to a TCG convention, and most (if not all) panels are in regards to theatre administration.  Few deal with the ideas of art itself.

A recent discussion on Twitter with the 2amtheatre group (2amtheatre.com) highlighted some of the problems that this lack of attention posed.  I realized that I was in a unique position to do something about it.  Within 48 hours, I had coded Talkbackr, a platform for asking for and receiving feedback from audience members.

The process is simple:

  1. Create an event
  2. Hand out the Feedback URL to as many people as possible
  3. ????
  4. Profit!

All the audience has to do is go to the Feedback URL and answer four questions:  what went right? what went wrong? what can we do differently next time to make it better? do you have any other thoughts?

That’s it.  They can provide their name if they want to, but it’s completely optional.  If you don’t provide your name, your feedback is completely anonymous.  Hopefully this encourages honesty, an aspect of feedback in which many theatre companies are sorely lacking.

Added bonus: Talkbackr comes with widget to put on your blog or website to make getting users to talkback even easier.

Remember, no matter how good your show is, you can always, always, always improve.  Get feedback. Get talkbackring.  Get Talkbackr.

My last PHP post included a quick way to process any form.  Today, I decided to show you what the rest of my control panel is comprised of.  This is a really dumbed down version and virtually impractical, because my actual code is a lot longer and a lot more complicated.  However, I did want to share with you the basics so that you can figure out how to do it yourself.  It’s really not that difficult of a concept.

There’s something in the programming world called OOP (Object-Oriented Programming).  This means that we treat data like an object.  I think we can all agree that a car is an object, correct?  Cars have attributes (color, horsepower, top speed, anti-lock brakes) and functions (park, drive, neutral, turn on AC, turn off AC, start car, roll down windows, etc).  A class is similar in that it also has attributes (variables) and functions (uh.. functions).  Here’s a quick example:


class Car {
this->$color;
this->$horsepower;
this->$topspeed;

function __construct(){
$color = "red";
$horsepower = "550";
$topspeed = "150";
}

function changeColor($newColor){
$color = $newColor;
}
}

The __construct() function is what is known as a constructor. It sets the default variables upon creation of the item. This can also run other functions, but for our purposes, we’re just setting default variables. The this->$color means that the $color variable is accessible within the entire class, not just inside individual functions. I think the changeColor function is self-explanatory.

Here’s how you might use it:


$car = new Car();
$car.changeColor("purple");

I created a new instance of a Car object, and in the second line, I changed the color of the car from the default color (red) to the new color (purple). See how simple that was? I hear you thinking right now: “What’s the point? I could have defined a variable and set the color in a regular function. Why do I need a class?”

Well, classes can do one really neat thing like this:


$honda = new Car();
$toyota = new Car();
$ford = new Car();

$honda.changeColor("green");
$toyota.changeColor("purple");
$ford.changeColor("blue");

See what I did there? I created three different objects, and each one contains its own color. When I set the color of $honda to green, I’m not changing the color of $toyota or $ford. Basically, you can have a bazillion objects, each with its own set of attributes and functions!

So how does this turn into my control panel class? Well, I basically made a class like the Car() class, except it contained many more variables and many more functions. Most of the functions dealt with generating a view (menu, table, or button) that was context aware — it changed depending on what the variable is that is passed into it. All I have to do to set up a control panel is pass in an array of variables that tell the control panel what to generate, and it does all the repetitive work itself. Here’s a quick example of what I’m talking about:

class Panel{

__construct(){
// Connect to the database code
}

buildMenu($tables){
echo "<ul>";
foreach($tables as $table){
echo "<li><a href="/$table">$table</a></li>";
}
echo "</ul>";
}
}

So now to generate the menu, I pass in something like:

$tables = array( "categories", "products", "users" );

$panel = new Panel();
$panel.buildMenu($tables);

And it generates a UL with each LI containing a link to that table page. All I have to do in order to update that control panel is change the $tables variable. I don’t have to go hunt down the code and add yet another line of code to represent a new table. Pretty nifty, right?

More to come next week…

A few months ago, I was working on a control panel for a client, and I realized I was doing a LOT of copying and pasting.  In addition, each form on the control panel had a separate back-end file that processed that particular form.  That’s a lot of redundancy, repetition and duplication!  I figured my form processors are doing three things:

  1. Inserting into the database
  2. Updating the database
  3. Deleting a row from the database

There had to be a better way.  Here’s what I came up with:


$count = 0;
$table = $_POST['table'];
foreach($_POST as $key => $value){
if($key != "table"){
if($count > 0){
$keys .= ", ";
$values .= ", ";
}
$keys .= $key;
$values .= "'".$value."'";
$count++;
}
}

This is the basic version for the add query generation.  It loops through the $_POST parameters and concatenates a string to be used in the SQL statement.  To generate the SQL statement, you’d simply write something like this:

$add_sql = "INSERT INTO $table ($keys) VALUES ($values)";

Simple, right? The catch, of course, is that the $_POST keys must match up with the field names in the database, but if you plan out correctly, it shouldn’t be a problem. You would also need to pass the table into the script as well.

Hope that helps someone out there, and if you have any other suggestions or faster, more efficient ways to do this, let me know!