PHP: Cleaning input from multiple parameter sources

In PHP, parameters can arrive into a page from multiple sources: GET, POST, SESSION variables, cookies, etc. There are often situations where an expected parameter can arrive from more than one of these variable scopes. Rather than write conditional code to check each possible scope for the incoming variable, I wrote a piggy-back method called captureArg() on top of an open-source input filter class (called “$clean” in the examples below) I found on the Net (there are numerous excellent examples; pick one).

Let’s say I have a form action script that processes a user’s form submission, grabs values from a database based on criteria found in the incoming fields, and returns the result set. The script is expecting a field called ‘sk’ (for search keyword), and it may arrive from either the GET or POST scope, but may also have a favorite value stored as a cookie or even a session variable. Rather than check all four, I call captureArg() like this:

require_once 'class.input_filter.php';
$clean = new input_filter();
$tSelectionKeyword = $clean->captureArg('sk', 'VAR');

In this example, I call the captureArg() method within the input_filter class, and pass it the name of the parameter and it’s expected type. The function is smart enough to use ‘VAR’, ‘TEXT’, ‘TXT’, or ‘CHAR’ interchangeably. I can also pass an optional default value as the third method parameter in case the variable ‘sk’ doesn’t exist in any of the known scopes. In this example, I’m leaving it up to the method to set a default value.

At this point, I can use captureArg() to collect just about any incoming parameter using a single line of code, without having to guess what variable scope it exists within. Here are some examples:

$tUserID = $clean->captureArg('user_id');   // Integer type with a default value of zero

$tPostDate = $clean->captureArg('post_date', 'DATE', '1980-01-01', 'Y-m-d');
// Date type, default value, and format

$tOrderTotal = $clean->captureArg('order_total', 'FLOAT', '0.0');

Want to see how the code works? As you can see, it can be expanded to include multiple variable types, and even additional variable scopes pretty easily.

function captureArg($pInval = '', $pType = 'INT', $pDefaultValue = '0', $pDateFormat='Y-m-d') {

if ( isset($HTTP_SESSION_VARS[$pInval])) {
    $tRetVal = $this->process($HTTP_SESSION_VARS[$pInval]);
} else if ( isset($_POST[$pInval]) ) {
    $tRetVal = $this->process($_POST[$pInval]);
} else if ( isset($_GET[$pInval]) ) {
    $tRetVal = $this->process($_GET[$pInval]);
} else {
    $tRetVal = $pDefaultValue;
}
$tType = strtoupper($pType);

switch ($tType) {
    case 'INT':
        $tRetVal = intval($tRetVal);
        break;
    case 'FLOAT':
        $tRetVal = floatval($tRetVal);
        break;
    case ($tType == 'VAR' || $tType == 'TEXT' || $tType == 'TXT' || $tType == 'CHAR'):
        $tRetVal = trim($tRetVal);
        break;
    case 'DATE':
        $tRetVal = date($pDateFormat, strtotime(trim($tRetVal)));
        break;
    default:
        $tRetVal = trim($tRetVal);
    }

return $tRetVal;
}

You may notice a call to a local method called $this->process(). The process() method is included in the input filter class I obtained and performs several input filtering techniques, including the removal of HTML tags, etc.

Counter-intuitive Productivity

If you want to get something done, do it. When writing PHP, if I need to output something to the screen or save a record in the database, I write code that performs that function. But something happened in recent weeks that changed my approach to this situation.

Instead of writing code to perform the operation, I began writing functions that perform the operation. I would then insert calls to those functions. Long-in-the-tooth programmers that read this are probably thinking “Duh!” but there’s something subtle about this.

Even though I’ve been writing code since the mid 80′s, I’ve always had a ‘use whatever approach best fits the current need’ way of doing it. If it makes sense to write a function, that’s what I do. If it makes sense to build a class, that’s what I do. If it makes sense to write the functionality I need in-line with the main body of code, that’s what I do. I don’t have a default way of doing things like many developers do (OOP, anyone?)

The way my mind works is to ask, “Will this functionality be needed elsewhere? If so, write a function. Does this functionality need to encapsulate both code and data? If so, write a class.” This time, however, I began writing functions right away and didn’t specifically ask myself those questions (I already created the necessary classes for the project). Then something remarkable happened.

As I began coding the different versions of functionality that would be available to different levels of users (easy and advanced, create and edit, etc.) I found I had created a library of handy drop-in functions that dramatically increased my programming productivity. It seemed counter-intuitive at the time, but creating functions took slightly more time up front but dramatically reduced the amount of coding required soon after.

Instead of building results, I wrote functions that produced those results. Whenever I needed that result, I’d call the function instead. Again, this probably seems old-hat to many developers, but what’s different is that I took this approach by default right from the start rather than making that choice as I went along.

It was subtle but profound.

Happy users

It’s impossible to please everyone. As a developer, it’s my job to please as many of my users as I can. This means creating web apps that are pleasing to look at, easy to use by both newbies and power-users, and easy to figure out for first-time visitors.

This is an impossibility, a chasing after the wind. It’s easier to play pool with a rope.

I maintain both our public web site and our rather inclusive Intranet, both of which I created from scratch. Public web sites tend to follow a set of fairly straightforward and standardized rules of usability and seldom get much contention from those involved in the design process. I’m more or less allowed to design according to my professional judgment.

Our Intranet is another ball game entirely.

The company I work for is a scientific consultancy and other than two other admin personnel like me, our entire staff is made up of scientists and technicians. They have a very diverse view of what’s good and what isn’t, and trying to please all of them on Intranet projects has been my biggest challenge.

Right now I’m working on adding an expense reporting system to the timesheet section of our Intranet. Employees will enter expenses they incur, including miles driven using a personal or company vehicle, purchases made with a company credit card, reimbursable expenses, travel, and even vendor invoices for large equipment or software purchased to be paid with a company check.

My development process is to interview a representative sample of key users and write down all the functionality needed and requested. I group everything into three categories: must have, need to have, and like to have. The ‘must have’ group is functionality that has to exist right out of the gate, version 1.0. The ‘need to have’ is functionality that will be built but doesn’t necessarily have to exist in the first release. The ‘like to have’ group is exactly that: something that is requested but not required, sort of “We’ll implement it if we can.”

Once that’s done, I create a clickable HTML prototype to let people see and touch the design. Several key users check it out and provide feedback about what works for them and what doesn’t. Feedback tends to fall within three types: Love it, hate it, or doesn’t care. How do I reconcile these disparate opinions about the system I’m building?

I can weigh the feedback based on where the responder exists in the corporate food chain. If a senior scientist likes something but a part-time seasonal technician hates it, who do you think will win out? What if two seniors have completely different opinions about the same functionality or design?

Although I create the designs based on my own experience and personal preferences, I try to leave my own likes and dislikes out of the equation, at least when it comes to aesthetics. When in doubt, I defer to the rules of usability and design. You’d be surprised how many people I’ve met that think hot pink text on a black background is beautiful. I have to rely on that experience and knowledge when settling disputes between users on aesthetic or usability issues as well.

If I have differing opinions about a design, and those opinions are more or less weighted the same, I’ll rely on usability standards to resolve the conflict and choose a design. Sometimes users don’t necessarily know what’s good for them. It sounds cold and almost arrogant, but people have a remarkable ability to forget they dislike something and simply get used to it. There are times, however, when I create a design or development functionality that violates my own judgment of what is ‘good’ for the sake of making the users happy. This sometimes works out okay, where a web site violates several rules of design or functionality but the users are happy with it so who cares in the end? That’s rare, however. Most often, when established rules are violated, things have to get redesigned after a while and we usually end up moving back toward the tried-and-true — where we [arguably] should have been in the first place.

In my position, at least on paper anyway, I have the final say when it comes to web development at my company. However, it’s rarely a good idea to pull rank if enough users don’t like what it would produce. Ultimately, happy users is what matters most.

The cost of lost opportunity

Those that are budget-minded may relate to the concept of ‘wait until it goes on sale.‘ The premise assumes everything eventually drops in price so it’s better to hold off on a purchase until it goes on sale. This idea holds true for most things, especially brand new technology. The old rule of thumb with computer processors was to buy whatever CPU was the latest and greatest the prior year. After 12 months the price has dropped substantially yet you still have a processor that’s very fast, typically within the top 10% in speed of what’s available at half the price.

The counter argument deals with what economists call the Cost of Lost Opportunity. It can be assumed that new hardware or a spiffier web site offers some kind of performance benefit, either through better efficiency or additional functionality. The longer you hold off on investing in a new computer the longer you have to deal with a slower model. The longer you hold off investing in a new Intranet design, the longer your employees go without a faster, more efficient work flow.

Although every situation is unique, it is sometimes possible to quantify the difference between what the investment will cost versus what you’ll lose without the enhanced efficiency. A very simple example is purchasing a second monitor for a bookkeeper. Assume a 23″ LCD monitor costs $200 and your bookkeeper costs the company $40 per hour. ROI figures for additional screens show that for the average office worker the investment will pay for itself within 3 months or less. Holding off until the monitor goes on sale for $180 would actually cost the company money in lost efficiency.

When it comes to more expensive web projects, like adding expense tracking and reporting to the company Intranet, determining the cost of lost opportunity is more complex. Quantifying the gain in efficiency a new system will provide is not always cut-and-dried. If entering expenses electronically into an Intranet takes 25% less time than the current system, it merely requires an aggregate calculation based on each employee’s net hourly cost to the company. Not all web projects are like that, however. Some improve morale but don’t necessarily reduce employee overhead. How do you quantify the value of keeping employees informed of what’s going on with other teams?

In my duties as IT Manager, I often have to trust my gut when it comes to prioritizing projects and tasks. Some things are easy to figure out. If a senior member of our staff needs a new computer, I’ll expedite the request at a higher priority to the point of paying full retail and overnight shipping on a system rather than hold off until a unit goes on sale and shipping it ground.

The same prioritization applies to larger projects. Projects that are fairly large in scope but apply the biggest benefit to the greatest number of people take priority over smaller projects that only impact a few people. “The needs of the many outweigh the needs of the few.” Conversely, if I can bang out a bug fix or enhancement in an hour or two, even if it only helps a single user, I’ll do it because it costs such a small amount of time to implement.

Resources are limited in every organization and we wear many different hats. Finding the biggest bang for each dollar of effort is crucial. The trick is to recognize the value of implementing something at full price today — with the efficiency gains it provides — versus holding off until a later date when implementation costs may be slightly lower.

Cheating on math tests

My parents gave me a Commodore 64 for Christmas during my junior year in high school (yes, that dates me a little). I had already been using a Vic-20 so BASIC programming was already a big part of my life. With the Commodore 64, I had a tape drive and could store my programs instead of typing them in from scratch every time, so the size and complexity of my programs really took off.

One of my high school courses was trigonometry. I had always done reasonably well in math classes but I had never really enjoyed it like I had English or science. I just wanted to get the homework done, pass the tests and move on. So I began cheating.

When Mr. Ford would give us a homework assignment, I’d dash home and begin writing a BASIC program that would solve the different math problems in the assignment. I’d verify the answers, write them down, then turn in the assignment the next day. I was getting 100% on my homework, but I was flunking the tests. Mr. Ford pulled me aside after class to talk with me about it.

I immediately confessed what I was doing and Mr. Ford’s reaction surprised me. He owned a Commodore 64 as well and had been dabbling in BASIC programming too, so he gave me a choice. I could either stop using my computer to do my homework and complete it and the tests the old-fashioned way, or I could continue as I was but with one difference…

When Mr. Ford had an in-class test, I had the option to write a BASIC program on paper that would solve the problems. He would take my test home and enter it into his C-64 and if it ran without bugs and actually solved the problems in the test he’d give me a 100% score. If it had bugs but still solved the problems I’d get a C. If it failed to solve one or more problems, I’d get an F. I also had to turn in the programs I’d write to solve the homework assignments with the same criteria.

I chose to write the programs during tests and ended up getting an A in the class.

Mr. Ford recognized that in order to write a software program that accurately mimics reality, the programmer would have to obtain a mastery of the reality itself. The way my brain works may be somewhat unusual … I would intensely dive into the math problems so I could write a BASIC program to solve them, learning them inside and out. But once I knew that my program worked and worked consistently, I’d purge the knowledge out of my head and move onto something else. Once you build a tool to do your work for you, you stop doing the work yourself.

Fortunately my teacher was able to see that I was actually doing twice as much work as the other students. I was learning the math and was writing computer software, too. It would be the same as an English Composition teacher asking her students to write a 5-page essay on Shakespeare’s use of metaphors, and then translating that essay into French.

Novelist or programmer?

I’m writing a book. It sounds cliche but it’s true. I’ve been working on it since the first of the year, with most of my writing taking place on quiet Sunday mornings before the rest of the house is awake. The week’s worries are gone, I’m well rested, and I’m free of distraction.

The first chapter was a stream of consciousness without any plan or forethought. Once it was completed, I read over it several times and began to identify what aspects really stood out and what needed work. Then I outlined in my mind where the story would go from there. I also created a more fleshed out definition of who the main characters were and what their primary characteristics would be.

The second chapter fed the plot based on my initial outline and introduced some new characters. The third chapter refined the plot and filled in important details that set up where the main story would go. If it were a screenplay chapters one, two and three would make up the first act. Now I’m ready to dive into act two and let my creative horses run wild.

In other words, now the hard part begins.

Designing and developing a large software or web project has many parallels to writing a novel. Chapter one is the creative, conceptual phase where ideas are brainstormed and put down on paper. Chapter two represents the process of defining what the app will do and how it will do it. Chapter three produces a solid, thorough project plan and product definition. Act I is all about planning and laying the groundwork.

Act II is the where the bulk of the story is written and is the bulk of where the application is developed. The story is fleshed out in bits and bytes and real functionality is created.

Act III resolves conflict and closes loops. The application gets tested and deployed without any new functionality added; there’s time enough for that in sequels.

One of the biggest challenges novelists and software developers face is maintaining the discipline to keep plugging away on what may seem like a dauntingly large effort, making progress on a daily basis even if it’s a small contribution to the overall project.

Writing software can also be productive or a waste of time based on circumstances, just like writing a novel. Sometimes you have to be in the mood for it. I’ve had salmon days* on development projects where I shouldn’t have wasted my time getting out of bed. Other times I’ve been in the zone and got three days worth of work achieved in a matter of hours. It goes to show that software development can be just as much a creative endeavor as a technical one. Every developer has a pattern of efficiency. Some are morning people, others get their best work done late at night.

Press 0

There’s a lot to be learned by calling a company’s main phone line and listening to their maze of phone options. At best “Press 1 for sales” is the first option, but if you pay attention you’ll notice that the final option you hear — the last option you hear — is “Press 0 to speak to an operator”.

I think it should be the other way around.

Programming is quite a bit more than just syntax and code and design patterns. Code is programming. Psychology and project management and human relations is software development. The human factor. It involves listening to what the client is saying and what they’re not saying. It means striving to understand what their needs and wants are and knowing the difference between them.

Many programmers have a natural aversion to human contact, at least with clients anyway, and prefer the predictable yet non-judgmental company of technology. Yet one of the hallmarks of top-notch software developers is their ability to handle the soft side of the craft, the interpersonal communication that helps them truly understand their customer. If you look at the full software development life-cycle, writing code is a small portion of the overall process.

Pressing 0 to speak with a real human should be the first option. As any real programmer can tell you, zero comes before 1 anyway.

Quick Objective-C update

My effort to learn Objective-C on the Mac is going well. Like most things, I find it helps to immerse myself in it for several hours or a day or two at a time rather than touch the subject in small chunks here or there. On days when I have to write PHP I don’t touch the Objective-C effort at all. That just makes me get confused about which syntax to use.

So far I’ve created a straightforward iPhone app that displays current GPS coordinates with vertical and horizontal accuracy. I’ll use that code to grab the current location when I expand into capture user-entered data for the field sampling app I’m building.

Cross-language polination

If you learn habits and patterns in one language, it’s bound to cross over and infect the way you do things in another language. Any given programming language will let you skin the proverbial cat 9 different ways (or more). I’ve been writing PHP more or less full-time since 2002, with a scattering of Cold Fusion and Javascript thrown in. I started writing my PHP code using a procedural approach with some dabbling in OOP. PHP lets me do either, both, or a mix (which is most often the case). It’s a very flexible language and there is power in that flexibility. But, like a permissive parent, it doesn’t force a lot of discipline in its followers.

Along comes Objective-C in my life. As I’ve mentioned, I’m working to learn the lingua franca of iPhone and Mac apps. Objective-C pretty much demands a 100% OOP approach (yes, it’s possible to write procedural code but that would be like owning a Porsche and never taking it out of first gear). As a result, my exposure to the Objective-C way of doing things is affecting how I write PHP code.

I have a series of classes in PHP used for database access. They inherit some basic functionality from a generic database class, but for the most part whenever I add a new table to my database I have to create a new class to access it. It’s reasonably efficient and works well once it’s in place, but there is still a great deal of functionality that’s identical between each table class.

Now that I’m seeing how things are done in Objective-C, I’ve already got some great ideas of how to abstract my database table access classes so that the creation of a new table is reduced to passing a list of field names, rather than the creation of a whole new class.

See, you can teach an old dog new tricks!

And so begins the iPhone app journey

Time to add programming language #26 to my repertoire, Objective-C, the language underneath iPhone apps. I work at a fisheries consulting firm and we want to use the versatility of the iPhone as a field sampling tool. It’s got data entry, wireless connectivity, GPS, and photography all built into a hand-held unit. What’s not to like?

We just need an app that will do what we want, that’s all.

Being the IT guy, it’s my job to manage servers, buy hardware and install software, train users, and build and maintain several public web sites and our fairly substantial Intranet. It’s also my job, semi-voluntarily, to take on the challenge of building an iPhone app that will do everything we need.

Right now there are some off-the-shelf iPhone apps that come close to what we want, but none match our requirements entirely. While we get by with those, I’m doing everything I can to learn Objective-C and become fluent in iPhone app development so we can have the software that meets 100% of our needs.

First steps

There are a lot of things that need to fall into place before we have a working and tested custom iPhone app. The first thing I did was download Xcode from the Apple developer’s web site. It’s free and is the defacto way to write software for Mac OS X and the iPhone. I’ve also registered to become an Apple iPhone developer, at a cost of $99 per year.

I tend to learn by doing, and have found great success by following along one or more books on the subject. To that end, after doing some research, I decided to get Learn Objective-C on the Mac by Mark Dalrymple and Scott Knaster, and Beginning iPhone Development: Exploring the iPhone SDK by Dave Mark and Jeff LeMarche. Both books are published by Apress. I purchased them through my old standby, Amazon.com. I actually bought the iPhone development book first and while reading the introductory chapter discovered that I needed a fundamental understanding and working knowledge of Objective-C first, hence my purchase of the Dalrympe/Knaster book. To round things out I downloaded some iTunes University videos on the subject to get familiar with Xcode as well as several PDFs from the Apple developer web site on both subjects (Objective-C and iPhone).

Getting into a pattern

Learning a new programming language is difficult enough, but doing it while still coding in an entirely different language — PHP, in my case — makes it even more of a challenge. Let’s say your native language is English, but you work at a job that required you to learn and speak Spanish 6 hours a day. Now try learning Russian on top of all that.

Learning a new programming language requires a certain aptitude, but more importantly it requires a level of discipline. Keeping a consistent schedule where you focus on the new technology a certain number of hours every day really helps. Since I wear both IT and web development hats at work, I tend to get my IT related tasks done during the first part of the day — often all day during Monday through Wednesday — and switch to development after lunch. Thursdays and Fridays tend to be weighted more toward development than IT, and it’s not uncommon for me to spend almost the entire day on Friday nose-down on the keyboard writing code.

Sometimes I even close my office door to shut out distractions and noise so I can better focus on coding. Programming takes a certain ramp-up time to get into the groove, at least for me. It’s not something I can drop and pick up on short notice. Instead it’s better if I devote several hours to the task and stay in it. Sometimes I’ll even work from home so I truly have the whole day to focus on coding.

Next steps

Now that I have all the tools and learning materials in place, my next step is to dive into the Learning Objective-C book and complete the exercises contained therein.

←Older