Songbird with Mike Smith in the post parade prior to winning the 50th Running of the Cotillion Stakes (GI) at Parx on September 24, 2016. Photo By: Chad B. Harmon
Genoa-Kingston Andrea Strohmaier signals as she makes a cut past coach Kyle Henkel during practice on Monday, Oct. 29, 2012.
DeKalb senior chess player Bruce Henry moves his queen to checkmate his opponent -teacher Christopher Judkins at chess practice on Friday, Jan. 29, 2016.
Students' lunches are stacked outside a conference room Wednesday at Greencroft Goshen. After caroling through the community, students returned to the main building to eat their lunches.
The 84dot5mm graduated neutral density filter is grey coloured filter which reduces amount of of light passing through a filter and neutrally darker the upper part of image as far as possible without affecting its color tone (neutrality). The result is often stunning - "blow" of the sky will disappear, the sky and cloud structure becomes visible, while the very bottom (landscape) remain ideal exposed (not over exposed, not dark).
While Soft & Hard Edge GNDs are darkest at the top, the 0.6 Medium Reverse GND is darkest near the filter center and lightens toward the top, and clear at the bottom half. This allows balancing of a bright horizon (sunrise/set) while seamlessly compensating for well exposed skies and detailed foreground. A useful application would be seascapes.
These filters allow you to seamlessly compensate for a bright horizon, while still maintaining proper sky exposure above the horizon, as well as foreground exposure. Singh-Ray filters are absolutely neutral in color with superior optical integrity. - See more at: http://www.thecamerastore.com/4508-Singh-Ray-Daryl-Benson-3-Stop-Reverse-GND-4x6.aspx#sthash.n1qxu0Ck.dpuf
- Color pigment in the filters are deeply embedded in the material at high temperature and pressure, which provides very good resistance
It’s maintained by me, Alex Cabal. I’ve been writing PHP for a long time now, and currently I run Scribophile, an online writing group for serious writers, Writerfolio, an easy online writing portfolio for freelancers, and Standard Ebooks, an open source project that produces liberated ebooks for the true book lover.
Drop me a line if you think I can help you with something, or with suggestions or corrections to this document.
PHP is a complex language that has suffered years of twists, bends, stretches, and hacks. It’s highly inconsistent and sometimes buggy. Each version has its own unique features, warts, and quirks, and it’s hard to keep track of what version has what problems. It’s easy to see why it gets as much hate as it does sometimes.
Despite that, it’s the most popular language on the web today. Because of its long history, you’ll find lots of tutorials on how to do basic things like password hashing and database access. The problem is that out of five tutorials, you have a good chance of finding five totally different ways of doing something. Which way is the “right” way? Do any of the other ways have subtle bugs or gotchas? It’s really hard to find out, and you’ll be bouncing around the internet trying to pin down the right answer.
That’s also one of the reasons why new PHP programmers are so frequently blamed for ugly, outdated, or insecure code. They can’t help it if the first Google result was a four-year-old article teaching a five-year-old method!
This document tries to address that. It’s an attempt to compile a set of basic instructions for what can be considered best practices for common and confusing issues and tasks in PHP. If a low-level task has multiple and confusing approaches in PHP, it belongs here.
It’s a guide suggesting the best direction to take when facing one of the common low-level tasks a PHP programmer might encounter that are unclear because of the many options PHP might offer. For example: connecting to a database is a common task with a large amount of possible solutions in PHP, not all of them good ones—thus, it’s included in this document.
It’s a series of short, introductory solutions. Examples should get you up and running in a basic setting, and you should do your own research to flesh them out into something useful to you.
It points to what we consider the state-of-the-art of PHP. However, this means that if you’re using an older version of PHP, some of the features required to pull off these solutions might not be available to you.
This document is not a PHP tutorial. You should learn the basics and syntax of the language elsewhere.
It’s not a security guide. While it touches upon some security-related issues, you’re expected to do your own research when it comes to securing your PHP apps. In particular, you should carefully review any solution proposed here before implementing it. Your code is your own fault.
It’s not an advocate for a certain way of doing high-level tasks like user registration, login systems, etc. This document is strictly for low-level tasks that, because of PHP’s long history, might be confusing or unclear.
It’s not a be-all and end-all solution, nor is it the only solution. Some of the methods described below might not be what’s best for your particular situation, and there are lots of different ways of achieving the same ends. In particular, high-load web apps might benefit from more esoteric solutions to some of these problems.
PHP is the 100-year-old tortoise of the web world. Its shell is inscribed with a rich, convoluted, and gnarled history. In a shared-hosting environment, its configuration might restrict what you can do.
You might find that some of these solutions work on different or older versions of PHP. If that’s the case, it’s up to you to research the implications of subtle bugs or security issues in these older versions.
A lot has changed in the PHP world in the years between Ubuntu 12.04 and 14.04. Since 12.04 is still very common in the wild, and since some of the solutions below have changed significantly in 14.04, I’ll include 12.04-specific solutions in a box like this one.
Hashing is the standard way of protecting a user’s password before it’s stored in a database. Many common hashing algorithms like md5 and even sha1 are unsafe for storing passwords, because hackers can easily crack passwords hashed using those algorithms.
PHP provides a built-in password hashing library that uses the bcrypt algorithm, currently considered the best algorithm for password hashing.
Many sources will recommend that you also “salt” your password before hashing it. That’s a great idea, and password_hash() already salts your password for you. That means that you don’t have to salt it yourself.
The built-in PHP password hashing library isn’t available in the version of PHP installed in 12.04. Instead, use the open-source phpass library, which provides the same bcrypt-based functionality in an easy-to-use class.
There are many ways to connect to a MySQL database in PHP. PDO (PHP Data Objects) is the newest and most robust of them. PDO has a consistent interface across many different types of database, uses an object-oriented approach, and supports more features offered by newer databases.
You should use PDO’s prepared statement functions to help prevent SQL injection attacks. Using the bindValue() function ensures that your SQL is safe from first-order SQL injection attacks. (This isn’t 100% foolproof though, see Further Reading for more details.) In the past, this had to be achieved with some arcane combination of “magic quote” functions. PDO makes all that gunk unnecessary.
Not having set the character set to utf8mb4 in the connection string might cause Unicode data to be stored incorrectly in your database, depending on your configuration.
Even if you declare your character set to be utf8mb4, make sure that your actual database tables are in the utf8mb4 character set. For why we use utf8mb4 instead of just utf8, check the PHP and UTF-8 section.
Enabling persistent connections can possibly lead to weird concurrency-related issues. This isn’t a PHP problem, it’s an app-level problem. Persistent connections are safe to use as long as you consider the consequences. See this Stack Overflow question.
You can execute more than one SQL statement in a single execute() call. Just separate the statements with semicolons. Ubuntu 12.04 (PHP <= 5.3.10): If doing this, beware of this bug, which isn’t fixed in the version of PHP shipped with Ubuntu 12.04.
There are a few different ways to delimit blocks of PHP: <?php ?>, <?= ?>, <? ?>, and <% %>. While the shorter ones might be more convenient to type, they’re disabled by default and must be enabled by configuring the PHP server with the short_open_tag option. Therefore the only method that’s guaranteed to work on all PHP servers is <?php ?>. If you ever plan on deploying your PHP to a server whose configuration you can’t control, then you should always use <?php ?>.
If you’re only coding for yourself and have control over the PHP configuration you’ll be using, you might find the shorter tags to be more convenient. But remember that <? ?> might conflict with XML declarations and <% %> is actually ASP style.
When including a closing ?> tag in a pure PHP file (for example, in a file that only contains a class definition), make sure not to leave any trailing newlines after it. While the PHP parser safely “eats” a single newline character after the closing tag, any other newlines might be outputted to the browser and possibly confuse things if you’re outputting any HTTP headers later.
When writing a web app targeting older versions of IE, make sure not to leave a newline between any closing ?> tag and the html <!doctype> tag. Old versions of IE will enter quirks mode if they encounter any white space, including newlines, before the doctype declaration. This isn’t an issue for newer versions of IE and other, more advanced browsers. (Read: every other browser besides IE.)
PHP provides several ways to auto-load files containing classes that haven’t yet been loaded. The older way is to use a magic global function called __autoload(). However you can only have one __autoload() function defined at once, so if you’re including a library that also uses the __autoload() function, then you’ll have a conflict.
A lot of ink has been spilled about whether to define strings with single quotes (‘) or double quotes (“). Single-quoted strings aren’t parsed, so whatever you’ve put in the string, that’s what will show up. Double-quoted strings are parsed and any PHP variables in the string are evaluated. Additionally, escaped characters like \n for newline and \t for tab are not evaluated in single-quoted strings, but are evaluated in double-quoted strings.
Because double-quoted strings are evaluated at run time, the theory is that using single-quoted strings will improve performance because PHP won’t have to evaluate every single string. While this might be true on a certain scale, for the average real-life application the difference is so small that it doesn’t really matter. So for an average app, it doesn’t matter what you choose. For extremely high-load apps, it might matter a little. Make a choice depending on what your app needs, but whatever you choose, be consistent.
Traditionally in PHP you would define constants using the define() function. But at some point PHP gained the ability to also declare constants with the const keyword. Which one should you use when defining your constants?
define() defines constants at run time, while const defines constants at compile time. This gives const a very slight speed edge, but not one worth worrying about unless you’re building large-scale software.
define() puts constants in the global scope, although you can include namespaces in your constant name. That means you can’t use define() to define class constants.
define() lets you use expressions both in the constant name and in the constant value, unlike const which allows neither. This makes define() much more flexible.
Because define() is ultimately more flexible, it’s the one you should use to avoid headaches unless you specifically require class constants. Using const generally results in more readable code, but at the expense of flexibility.
In older versions of PHP, every time a script was executed it would have to be compiled from scratch, even if it had been compiled before. Opcode caches were additional software that saved previously compiled versions of PHP, speeding things up a bit. There were various flavors of caches you could choose from.
Lucky for us, the version of PHP that ships with Ubuntu 14.04 includes a built-in opcode cache that’s turned on by default. So there’s nothing for you to do!
For posterity, below are instructions for using an opcode cache in Ubuntu 12.04, which doesn’t include its own.
There are several PHP opcode caches available, notably eaccelerator, xcache, and APC. APC is officially supported by the PHP project, is the most active, and is the easiest to install. It also provides an optional memcached-like persistent key-value store. For these reasons, it’s the one you should be using.
If you’re not using PHP-FPM (for example you’re using mod_php or mod_fastcgi), each PHP process will have its unique APC instance, including key-value store. This can lead to synchronization problems in your app code if you’re not careful.
A caching system can often improve your app’s performance. Memcached is a popular choice and it works with many languages, including PHP.
However, when it comes to accessing a Memcached server from a PHP script, you have two different and very stupidly named choices of client library: Memcache and Memcached. They’re different libraries with almost the same name, and both are used to access a Memcached instance.
It turns out that the Memcached library is the one that best implements the Memcached protocol. It includes a few useful features that the Memcache library doesn’t, and seems to be the one most actively developed.
However if you don’t need to access a Memcached instance from a series of distributed servers, then use APCu instead. APCu is supported by the PHP project and has much of the same functionality as Memcached.
After you install the Memcached server, you need to install the Memcached client library. Without the library, your PHP scripts won’t be able to communicate with the Memcached server.
You can install the Memcached client library on Ubuntu 16.04 by running this command in your terminal:
Before Ubuntu 14.04, the APC project was both an opcode cache and a Memcached-like key-value store. Since the version of PHP that ships with 14.04 now includes a built-in opcode cache, APC was split into the APCu project, which is essentially APC’s key-value storage functionality—AKA the “user cache”, or the “u” in APCu—without the opcode-cache parts.
If you’re migrating APCu code from a version of APUc before 16.04, note that the function names have changed from apc_* to apcu_*. For example, apc_store() became apcu_store().
Each family of functions uses a slightly different flavor of regular expression. Luckily for us, the POSIX functions have been deprecated since PHP 5.3.0. Because of this, you should never write new code using the POSIX functions. Always use the PCRE functions, which are the preg_* functions.
There are several ways of configuring a web server to serve PHP. The traditional (and terrible) way is to use Apache’s mod_php. Mod_php attaches PHP to Apache itself, but Apache does a very bad job of managing it. You’ll suffer from severe memory problems as soon as you get any kind of real traffic.
Two new options soon became popular: mod_fastcgi and mod_fcgid. Both of these keep a limited number of PHP processes running, and Apache sends requests to these interfaces to handle PHP execution on its behalf. Because these libraries limit how many PHP processes are alive, memory usage is greatly reduced without affecting performance.
Some smart people created an implementation of fastcgi that was specially designed to work really well with PHP, and they called it PHP-FPM. This was the standard solution for web servers since 12.04.
In the years since Ubuntu 12.04, Apache introduced a new method of interacting with PHP-FPM: mod_proxy_fcgi. Unfortunately, the version of Apache that ships with Ubuntu 14.04 has a few problems with this module, including not being able to use socket-based connections, issues with mod_rewrite, and issues with 404 and similar pages. Because of these problems you should stick with the tried-and-true method of working with PHP-FPM that we used in Ubuntu 12.04.
Using the AddHandler directive instead of the SetHandler directive can be a security risk. AddHandler will execute PHP in files that have “.php” anywhere in the file name. So if a user uploads evil.php.gif using your file upload form, you might be in for a nasty surprise.
The configuration for Ubuntu 12.04 is just as above, except don’t include the <Directory> block in the configuration file.
PHP provides a mail() function that looks enticingly simple and easy. Unfortunately, like a lot of things in PHP, its simplicity is deceptive and using it at face value can lead to serious security problems.
Email is a set of protocols with an even more tortured history than PHP. Suffice it to say that there are so many gotchas in sending email that just being in the same room as PHP’s mail() function should give you the shivers.
PHPMailer is a popular and well-aged open-source library that provides an easy interface for sending mail securely. It takes care of the gotchas for you so you can concentrate on more important things.
A common task your web app might need to do is to check if a user has entered a valid email address. You’ll no doubt find online a dizzying range of complex regular expressions that all claim to solve this problem, but the easiest way is to use PHP’s built-in filter_var() function, which can validate email addresses.
When displaying user input in any web application, it’s essential to “sanitize” it first to remove any potentially dangerous HTML. A malicious user can craft HTML that, if outputted directly by your web app, can be dangerous to the person viewing it.
While it may be tempting to use regular expressions to sanitize HTML, do not do this. HTML is a complex language and it’s virtually guaranteed that any attempt you make at using regular expressions to sanitize HTML will fail.
You might also find advice suggesting you use the strip_tags() function. While strip_tags() is technically safe to use, it’s a “dumb” function in the sense that if the input is invalid HTML (say, is missing an ending tag), then strip_tags() might remove much more content than you expected. As such it’s not a great choice either, because non-technical users often use the < and > characters in communications.
If you read the section on validating email addresses, you might also be considering using the filter_var() function. However the filter_var() function has problems with line breaks, and requires non-intuitive configuration to closely mirror the htmlentities() function. As such it’s not a good choice either.
If your web app only needs to completely escape (and thus render harmless, but not remove entirely) HTML, use PHP’s built-in htmlentities() function. This function is much faster than HTML Purifier, because it doesn’t perform any validation on the HTML—it just escapes everything.
htmlentities() differs from its cousin htmlspecialchars() in that it encodes all applicable HTML entities, not just a small subset.
For many web apps, simply escaping HTML isn’t enough. You probably want to entirely remove any HTML, or allow a small subset of HTML through. To do this, use the HTML Purifier library.
HTML Purifier is a well-tested but slow library. That’s why you should use htmlentities() if your requirements aren’t that complex, because it will be much, much faster.
HTML Purifier has the advantage over strip_tags() because it validates the HTML before sanitizing it. That means if the user has inputted invalid HTML, HTML Purifier has a better chance of preserving the intended meaning of the HTML than strip_tags() does. It’s also highly customizable, allowing you to whitelist a subset of HTML to keep in the output.
The downside is that it’s quite slow, it requires some setup that might not be feasible in a shared hosting environment, and the documentation is often complex and unclear. The following example is a basic configuration; check the documentation to read about the more advanced features HTML Purifier offers.
Using htmlentities() with the wrong character encoding can result in surprising output. Always make sure that you specify a character encoding when calling the function, and that it matches the encoding of the string being sanitized. See the UTF-8 section for more details.
HTML Purifier is extremely slow for complex HTML. Consider setting up a caching solution like APC to store the sanitized result for later use.
Right now PHP does not support Unicode at a low level. There are ways to ensure that UTF-8 strings are processed OK, but it’s not easy, and it requires digging in to almost all levels of the web app, from HTML to SQL to PHP. We’ll aim for a brief, practical summary.
The basic string operations, like concatenating two strings and assigning strings to variables, don’t need anything special for UTF-8. However most string functions, like strpos() and strlen(), do need special consideration. These functions often have an mb_* counterpart: for example, mb_strpos() and mb_strlen(). Together, these counterpart functions are called the Multibyte String Functions. The multibyte string functions are specifically designed to operate on Unicode strings.
The hard part is remembering to use the mb_* functions at all times. If you forget even just once, your Unicode string has a chance of being garbled during further processing.
Not all string functions have an mb_* counterpart. If there isn’t one for what you want to do, then you might be out of luck.
Additionally, you should use the mb_internal_encoding() function at the top of every PHP script you write (or at the top of your global include script), and the mb_http_output() function right after it if your script is outputting to a browser. Explicitly defining the encoding of your strings in every script will save you a lot of headaches down the road.
Often you’ll find yourself writing files with contents or filenames encoded in some flavor of Unicode. PHP is able to run on a variety of operating systems, including Linux and Windows; but sadly how it handles Unicode filenames differs on each platform due to OS-level quirks.
Linux and OSX appear to handle UTF-8 filenames fairly well. Windows, however, doesn’t. If you try to use PHP to write to a file with non-ASCII characters in the filename in Windows, you may discover that the filename is displayed with strange or corrupted characters.
There doesn’t seem to be an easy, portable workaround here. In Linux and OSX you can encode your filenames with UTF-8, but in Windows you have to remember to encode using ISO-8859-1.
If you don’t want to bother with having your script check if it’s running on Windows or not, you could always URL encode all of your filenames before writing them. This effectively works around Unicode quirks by representing Unicode characters by a subset of ASCII.
If your PHP script accesses MySQL, there’s a chance your strings could be stored as non-UTF-8 strings in the database even if you follow all of the precautions above.
To make sure your strings go from PHP to MySQL as UTF-8, make sure your database and tables are all set to the utf8mb4 character set and collation, and that you use the utf8mb4 character set in the PDO connection string. For an example, see the section on connecting to and querying a MySQL database. This is critically important.
Note that you must use the utf8mb4 character set for complete UTF-8 support, not the utf8 character set! See Further Reading for why.
In the bad old days of PHP we had to work with dates and times using a bewildering combination of date(), gmdate(), date_timezone_set(), strtotime(), and so on. Sadly you’ll still find lots of tutorials online featuring these difficult and old-fashioned functions.
Fortunately for us, the version of PHP we’re talking about features the much friendlier DateTime class. This class encapsulates all the functionality and more of the old date functions in one easy-to-use class, with the bonus of making time zone conversions much simpler. Always use the DateTime class for creating, comparing, changing, and displaying dates in PHP.
PHP’s loose typing system offers many different ways of checking a variable’s value. However it also presents a lot of problems. Using == to check if a value is null or false can return false positives if the value is actually an empty string or 0. isset() checks whether a variable has a value that is not null, but doesn’t check against boolean false.
Thanks for reading! If you haven’t figured it out already, PHP is complex and filled with pitfalls. Since I’m only human, there might be mistakes in this document.
PHP Best Practices by Alex Cabal is dedicated to the public domain via the CC0 1.0 Universal Public Domain Dedication, and is thus free of copyright restrictions worldwide. Why?
Make something… that can be used… again and again… because being a lazy designer… is pretty smart. Be a Lazy Designer… was originally …
I think I’ve cracked the obsession amongst much of the Silicon Valley set with compressing work life, sacrificing everything until the big exit, and running …
The newest release introduces a brand new tab along with improvements to searching, navigation, and for people who have multiple accounts. Get it for iPhone …
For years we’ve used Basecamp To-Dos to track all of our design and programming work here at Basecamp. They help us make sure that nothing slips through …
I asked this to 700+ managers, founders and executives from all over the world. Here’s what they said. Time is the one constant we are all given. No one …
Using SMS as a second security factor for signing into web applications is no longer recommended by security experts. Therefore we will be ending our …
Be careful not to throw your weight around without knowing it. Yesterday I was in a board meeting for a company I advise. Great group, strong business, …
Last summer, my little corner of the Internet blew up with a post on Ask A Manager, a workplace advice column by Alison Green . The letter writer said that …
What seems small to you, as a leader, is not small to your team. I was running a leadership training a few months ago, when a CEO said this to me… “I …
It used to be a fundamental requirement that you learned an extensive amount of SQL before you were able to start working on database-backed applications. It …
How to spend your time when there’s nothing left to do? This morning something happened that reminded me of an important lesson re: time well spent. Three …
Welcome home! In 2014, Highrise was spun off as a separate (but wholly-owned) company from Basecamp. Last year it celebrated its tenth anniversary in …