There's no denying that ours is an incredibly difficult industry. Ever considered learning a second language? Well, how about five? That's what will be required of you, if you intend to become a modern web developer. Considering this, if you're not careful, very quickly, you may find yourself overwhelmed, as you stare blindly at countless confusing blog articles, or techical books.
The key, as with anything, is to take one step at a time.
The key, as with anything, is to take one step at a time. Would you fault yourself for not learning a spoken language in a month? Of course not. Then apply that same level of thinking to your programming journey. These things take time, but, as long as you continue pushing forward, you'll be there in no time. Don't stop!
Step one is HTML. Understand what purpose a <div>
serves. Learn how to structure content using semantic tags. Build a basic, unstyled web page.
Step two, as you might have guessed, is CSS. Learn how to style elements on the page. Appreciate what "separation of concerns" refers to, and how this applies to your HTML and CSS. Complete your first simple website.
Step three is when developers begin branching off into their own specialities. At this point, you could dive into the world of JavaScript, which is booming like never before. Or, you could instead focus your efforts on the backend.
Confused by the difference between frontend and backend? Think of the frontend as the tip of the iceberg that brought down the Titanic. It's the part of the application that is visible to the user, and can be interacted with. The backend, on the other hand, handles everything from persistence, to validations, to routing.
For the purposes of this article, let's assume that you've chosen the latter option; the server-side, it is!
There's no denying the fact that PHP dominates the web.
Unfortunately, once again, you come upon a handful of paths to take. Should you choose the most popular option - PHP? What about Ruby? The cool kids seem to prefer that these days. Then again, what if you have a beard? Is Python the correct choice. Most importantly, though, how could you possibly make a selection, when you have zero experience?
In situations such as this - and in this author's opinion - there is no wrong choice. And, certainly, there isn't a thing prohibiting you from switching down the road. In fact, all developers are encouraged to learn multiple languages! For now, however, the key is to pick just one, and learn it well.
While it's true that PHP is not the most beautiful of languages, there's no denying the fact that it dominates the web. In fact, it's the world's most popular scripting language. The benefit to this is that you may rest assured that every PHP question has already been asked, solved, and documented. There's comfort in knowing this. Though you're at the most fragile stage of your learning, a massive, friendly community is at your doorstep, ready to help. Even better, PHP is experiencing a modern renaissance like never before, thanks to tools like Composer and Laravel.
What is PHP?
PHP, an acronym for PHP: Hypertext Preprocessor (yes, developers love their recursive jokes), is a scripting language that was built specifically for the web. Chances are high, though, that this still means nothing to you. Scripting language? Huh? When would you reach for PHP over simple HTML? Well, perhaps an example is in order. Assuming that you've successfully installed PHP, create an index.php
file within a new folder on your desktop, and add:
<?php echo 'Hello world';
Yes, it's the ubiquitous "hello world" example that you'll become quite familiar with as your skills progress. Every language/framework/tool has one!
In order to run this code, use PHP's built in server. Switch to your favorite command line tool (Terminal, for Mac users), cd
to the project folder, and boot up the server with php -S localhost:8888
. This command translates to, "Run a server, and make it accessible from my browser at localhost, port 8888." Go ahead and try it out! Open Google Chrome, browse to localhost:8888
, and you'll see "Hello world*" on the page! Nifty! echo
is a language construct that does nothing more than output a given value.
Tip: MAMP and WAMP are excellent one-click solutions for installing PHP, MySQL, and Apache on your Mac or PC, without having to fumble with the command line. They can be helpful choices in the early stages of your learning.
WampServer is a development environment that allows for a one-click installation of PHP, Apache, and MySQL.
Admittedly, this isn't the most exciting thing in the world. In fact, you're likely thinking to yourself, "Why couldn't I write 'Hello world' directly into the HTML page, and remove the need for PHP all together?" It's true; for this example, it serves no purpose. However, a scripting language like PHP becomes particularly useful when the output should be dynamic in nature. What if, rather than world, you want the greeting to reference a value passed through the URL's querystring (the text in the address bar that comes after the question mark). Here's an updated example, which accomplishes just that!
<?php echo 'Hello, ' . $_GET['person'];
Ahh, this introduces a few new techniques. Firstly, the single period that separates the Hello string and that confusing $_GET
allows you to concatenate (or group) values. In this case, we wish to print "Hello, *" and then the value represented by $_GET['person']
. This is what we refer to as a super-global array. For the sake of simplicity, think of this as a way to *GET a value from the URL's querystring.
Test this out by loading localhost:8888/?person=Joe
. If configured properly, the web page should now display "Hello, Joe." Play around with it by replacing Joe
with your own name. Notice how the output updates each time the page is refreshed? This simply wouldn't be possible with static HTML.
One of the keys to mature programming is considering every possible path through your code. For example, what if no person
key is available? Perhaps the query string was omitted entirely. In that case, an error will certainly be thrown, as the person
key won't exist. What's the solution? While it's true that this is nothing more than a simple example, it's still important to consider all possible outcomes. Let's provide a default.
<?php if (isset($_GET['person'])) { $person = $_GET['person']; } else { $person = 'Joe'; } echo 'Hello, ' . $person;
Though there are more streamlined ways to allow for this, the example above is an excellent starting point. It's also your first introduction to conditional statements. Approach your code in the same way that you would handle scenarios in real life. For example, "If we are out of milk, then go to the store. Otherwise, stay home." This line of thinking could be translated to PHP, using the following logic:
$outOfMilk = true; if ($outOfMilk) { echo 'Going out to the store.'; } else { echo 'Breakfast is served.' }
In this bit of code, only a single line of text will be printed to the screen. The value of the variable (a dynamic value), $outOfMilk
, will determine the control flow.
Tip: To declare variables in PHP, precede any name with a dollar sign. As a best practice, opt for readable variable names over cryptic alternatives.
Returning to the previous example, as long as $_GET['person']
is set (think of this as a pseudo-name for "is available"), then create a new $person
variable equal to its value. Otherwise, apply a default. If you return to the browser, it should now function correctly, regardless of whether the person
key exists in the querystring.
Security
Unfortunately, we're still not home free. A key programming best practice is to place security at the forefront of every action. Even with this incredibly basic example, we've opened the door to one of the most widespread security issues on the web: XSS (Cross-Site Scripting). A true understanding of this is absolutely beyond the scope of this introductory lesson (entire books have been written on it), however, here's a basic illustration: what if $_GET['person']
is equal to, not a string, but a script?
http://localhost:8888/?person=<script>alert('ATTACK!')</script>
Because this value has not been sanitized, upon execution, in some browsers, an alert box will be displayed.
Webkit-based browsers (think Chrome and Safari) now provide protection against these sorts of attacks. However, this wasn't always the case, and still isn't in Firefox and Internet Explorer.
Yikes! We can't have that. While modern society dicates that a man is innocent until proven guilty, the same is not true for the programming world. All user input is guilty until sanitized! Here's an updated example which does this very thing:
<?php if (isset($_GET['person'])) { $person = $_GET['person']; } else { $person = 'Joe'; } echo 'Hello, ' . htmlspecialchars($person, ENT_QUOTES);
With this modification, should someone attempt an XSS attack, we'll be ready! htmlspecialchars
is a native PHP function that translates various symbols to their entity counter-parts. &
becomes &
, <
becomes <
, etc. This makes it the perfect tool to provide that extra bit of security. <script>
is meaningless if it is converted to <script>
before being executed. The user will simply see:
Hello, <script>alert('ATTACK!')</script>
Great; no harm done!
Functions
While PHP ships with a plethora of native functions, there will certainly be times when you require your own. Luckily, they're a cinch to write.
Think of a function as a reusable piece of logic that can be abstracted away, so that it may identified and called, using a readable name.
Perhaps you run a night club (not likely if you're reading this!), and need an easy way to accept a person's birth date, and calculate whether he or she is at least twenty-one years old. A custom function would be an excellent way to accomplish this task.
The first step is to define a new function, called isAdult
. Functions may accept outside input, which can then be operated on. This allows the returned data from the function to be dynamic. In this case, to determine if a person is an adult, we need to know their year of birth. The final step is to return either true
or false
, dependent upon whether the current year minus the person's birth date is at least twenty-one.
function isAdult($yob) { $currentYear = 2013; return $currentYear - $yob >= 21; }
It's really quite simple! Now, we only need to pass it off to the bouncer. A function may be triggered, or called, by referencing its name, followed by a set of parenthesis: isAdult()
. However, if the function requires an argument, then you may specify it within these parenthesis, as illustrated below:
if (isAdult(1985)) { echo 'Come on in!'; } else { echo 'Please leave now, before I call your mother.'; }
There's one glaring problem with this isAdult
function. The current year has been hard-coded. Sure, it will work throughout 2013, but what about next year? It seems that this value, too, needs to be dynamic. PHP provides a date
function, which can be used to calculate the current year. As such, the function may be updated to:
function isAdult($yob) { $currentYear = date('Y'); return $currentYear - $yob >= 21; }
Arrays
Fast-forward a few months, and, now, the night club is doing better than ever. In fact, it's doing so well to the point that the bouncer can't keep up. His job might be easier if he could instead filter through a group of people at a time.
Think of an array as a container for related data. You could even refer to it as a list: a list of tweets, a group of family members, an array of birth dates.
An array in the latest version of PHP (5.4) may be defined using a comma-separated list within brackets, like so:
$group = [1985, 1990, 1992, 1997];
This single $group
variable now contains multiple birth dates. Values within it may be accessed by specifying an index, such as $group[0]
. Arrays are what we refer to as being zero-based. In translation, this means that the first item, or key, in the array will have an index of zero. As such, to access the 1992 value, you would reference $group[2]
.
Now, the bouncer can rapidly filter through these birth dates, and calculate whether to allow the person in, or reject them. A foreach
statement may used for this type of filtering.
$group = [1985, 1990, 1992, 1997]; foreach($group as $yob) { if (isAdult($yob)) { echo 'Come on in!'; } else { echo 'Please leave now, before I call your mother.'; } }
Notice how the bouncer declares that the birth year foreach
person in the group
should be contained within the variable, $yob
. Next, as he did before, he passes that value off to the isAdult
function, and proceeds accordingly.
It's possible, though, that the bouncer will become confused when he doesn't have a link between the person's year of birth and their name. PHP also allows for associative arrays, which provide the necessary functionality to associate a given value with a key. Here's an example:
$group = [ 'John' => 1985, 'Susan' => 1990, 'Joe' => 1992, 'Sara' => 1997 ];
That's better. As an added bonus, the bouncer can be a bit more friendly to the person, now that he knows his or her name.
$group = [ 'John' => 1985, 'Susan' => 1990, 'Joe' => 1992, 'Sara' => 1997 ]; foreach($group as $name => $yob) { if (isAdult($yob)) { echo "Come on in, $name!"; } else { echo "Please leave now, $name, before I call your mother."; } }
When storing strings within double quotes, you may nest variables rather than use concatenation. This can lend itself for a more readable syntax.
Classes
Object-oriented programming is well beyond the scope of this tutorial, but, nonetheless, classes deserve a mention. For now, think of them as simple containers for related properties and methods. For instance, here's how a class that represents a single person might look:
class Person { public $name; public $age; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } }
Notice that __construct()
method? This is referred to as a magic method, and will be triggered immediately upon instantiation. When this method fires, it will accept a name and age, and then attach that to the object.
To use this class, try:
$me = new Person('Jeffrey', 28);
This will create a new instance of the Person
class. This instance, which is stored in the $me
variable, can be referred to as an object. Now, there's nothing prohibiting you from creating multiple instances of this class - and, in fact, in real world projects, you will! The class is just a blueprint.
At this point, though, the class isn't overly useful. Let's add a method, or function, to designate the spouse of a person.
class Person { public $name; public $age; public $spouse; public function __construct($name, $age) { $this->name = $name; $this->age = $age; } public function marry(Person $spouse) { $this->spouse = $spouse; } } $me = new Person('Jeff', 28); $her = new Person('Allison', 28); $me->marry($her);
This modified code now includes a marry()
method that will update a $spouse
property on the object. Now, you have a direct link between the two people.
If a method argument is preceded by a class name (
Person $spouse
), referred to as type hinting, this designates that the parameter must be an instance of the given class, or an error will be thrown.
To fetch the name of my spouse, you could write:
echo $me->spouse->name; // Allison
The concept of object-oriented programming goes much deeper than this, but keep it simple for now. It helps to think of classes as singular nouns: a tweet, or user, or customer, or file.
True appreciation for this pattern will only come with time.
Hands-On
Put your new found skills to the test. How might you go about registering and displaying tweets for a user on the page? Well, the first step might be to define a class that represents a single Tweet
. This class should store properties for the body of the tweet, as well as its publish date. Additionally, it should ensure that the body of the tweet does not exceed 140 characters. Here's a first stab at such a class:
class Tweet { public $body; public $pubDate; public function __construct($body) { $this->setBody($body); $this->setPubDate(new DateTime); } public function setBody($body) { if (strlen($body) > 140) { throw new InvalidArgumentException; } $this->body = $body; } public function setPubDate(DateTime $date) { $this->pubDate = $date->format('Y/m/d H:i:s'); } }
Though it may initially seem overwhelming, give this code snippet a bit of study, and try to understand what is happening each step of the way. You may find that it's quite readable!
One interesting new piece of functionality stems from the setBody
method. If the text provided exceeds 140 characters, which we can calculate using PHP's strlen
function, then we should take exception to that, because it breaks the rules of a tweet. An exception can be thrown using the syntax, throw new ExceptionType
.
Now that we have a decent enough container for a tweet, we can create a couple of tweets, store them in an array, and then, ultimately, render them on the page, using a foreach
statement.
$tweets = []; # add two new tweets to the array $tweets[] = new Tweet('Going to the store.'); $tweets[] = new Tweet('Back from the store!'); # Filter through, and display on page. foreach($tweets as $tweet) { echo "<h2>{$tweet->body}</h2>"; echo "<p>Posted on: {$tweet->pubDate}</p>"; }
Upon viewing the output in the browser, you should see something along the lines of:
Excellent, but how do we save those tweets?
Storage
So far, you've learned the essentials: variables, conditionals, functions, arrays, classes. There's more to cover, but you should research that on your own, as the need arises. The next step in your learning is persistence. For example, how might you keep a log of all tweets? A tweet service that doesn't remember tweets is a terrible one! This is when the idea of databases come into play.
Think of a database table as an Excel spreadsheet. It can have any number of fields, such as the person's name, age, or mailing address. However, PHP doesn't provide this sort of storage natively. Instead, the most common option is MySQL, which is the world's most popular open source database.
Installing MySQL doesn't fall within the scope of this tutorial. Instead, refer to this tutorial on Nettuts+ for a complete walk-through.
Here's a simplified example to get you started with securely fetching rows from a database table. Don't worry if it seems overwhelming. MySQL is your second new language to learn. PHP's PDO API, as well as the query language, itself, require time to learn.
First, you'll need a way to connect to the database.
function connect() { $conn = new PDO( 'mysql:host=localhost;dbname=DB_NAME', 'USERNAME', 'PASSWORD' ); $conn->setAttribute( PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION ); return $conn; }
PDO is one of PHP's three available APIs for connecting to a MySQL database.
Next, we'll add a helper function to fetch all records from the tweets table. Pay close attention to the query
method's argument, SELECT * FROM tweets
. This is a special language for querying the database. In this case, we're using the *
symbol to reference all rows. As such, we're selecting all rows from the table, called tweets
.
This function prepares the query, and then fetches the complete result set.
function fetchTweets($conn) { $stmt = $conn->query('SELECT * FROM tweets'); return $stmt->fetchAll(PDO::FETCH_OBJ); }
Now, with the stage set, we only need to call the functions, accordingly.
# Connect to the DB $conn = connect(); # Fetch all rows from attendees table var_dump(fetchTweets($conn));
An easy way to dump the contents of a variable is through the use of the var_dump
function. If you pass the output of fetchTweets($conn)
to this function, upon viewing it in the browser, you'll see something along the lines of:
var_dump
is helpful for debugging, but for production purposes, it's better to filter through the results, and render them on the page properly. The foreach
statement, which you're already familiar with, will handle the job quite nicely!
$tweets = fetchTweets($conn); foreach($tweets as $tweet) { echo "<h2>{$tweet->body}</h2>"; echo "<p>{$tweet->pubDate}</p>"; }
Conclusion
As with any skill, writing fluent PHP requires nothing more than your time. It may take hundreds of hours to fully grok, but that's okay. This is fun, right? It should be!
The best way to learn is to do. Build throw away projects like they're going out of style! The techniques outlined in this tutorial will take you through the first phase, but, certainly, as your skills progress, you'll move on to more advanced topics, such as PHP frameworks, design patterns, and test-driven development. Have fun!
Comments