Getting up to Speed with PHP

As I said previously, this book assumes you are already familiar with PHP. In this chapter I will quickly cover a few newer additions to PHP, as well as a few tools and techniques which you will need to know about to continue with this book.

I don’t intend to go into anything in too much depth. It will contain just enough information the things we will be using. Therefore, I encourage you to research them further yourself.

Namespaces

If namespaces are new to you then the easiest analogy I can think of is that they are like folders for your code. Using them means you can have 2 or more classes with the same name in different namespaces - in the same way that you can have 2 or more files with the same name in different folders.

Without covering all the details of PHP namespaces here, I will quickly cover the aspects of them which we will be using.

Firstly, in order to define a class inside a specific namespace, you use the namespace statement on the first line of the file containing the class. Like so:

Class defined inside namespace


1 <?php
2 
3 namespace MyApp\Entity;
4 
5 class Contact
6 {
7     // ...
8 }

This defines the class Contact inside the Entity namespace which is inside the MyApp namespace. Namespaces are separated by backslashes.

To use a class inside code which in the same namespace, you can simply refer to it by name:

Using a class defined in the current namespace


1 <?php
2 
3 namespace MyApp\Entity;
4 
5 $contact = new Contact();

To use a class inside code in a different namespace, you can refer to it by its Fully Qualified Class Name (FQCN). Like so:

Referencing a class by its FQCN


1 <?php
2 
3 namespace MyApp;
4 
5 $contact = new \MyApp\Entity\Contact();

You can also refer to a class in a sub-namespace relative to the current namespace. Like so:

Referencing a class by its relative namespace


1 <?php
2 
3 namespace MyApp;
4 
5 $contact = new Entity\Contact();

Finally, you can pull a class from a different namespace into scope with the use statement. Add this at the top of the file just after the namespace statement. This is the way I prefer in most situations - here’s an example:

The use statement


1 <?php
2 
3 namespace MyApp;
4 
5 use MyApp\Entity\Contact;
6 
7 $contact = new Contact();

One final thing: if you want to use a class from one namespace in another namespace which already has a class with the same name in it, then you can rename the one you’re importing with the as keyword. Like so:

Aliasing an imported class


 1 <?php
 2 
 3 namespace MyApp\Form;
 4 
 5 use MyApp\Entity\Contact as ContactEntity;
 6 
 7 class Contact
 8 {
 9     public function __construct(ContactEntity $entity)
10     {
11         // ...
12     }
13 
14     // ...
15 }

It’s all pretty simple really right? That’s everything you’ll need to know about namespaces to continue with this book. However, if you do want to learn more about them, then the full documentation for PHP namespaces can be found in the manual.

Typehints

PHP is a dynamically typed language. It has a few basic, scalar types:

Scalar types in PHP


1 <?php
2 
3 42; // integer
4 
5 12.5; // float or double
6 
7 'abc123'; // string
8 
9 false; // boolean

It also has arrays, callables, resources and any user defined classes or interfaces, which are all also types.

Being a dynamically typed language means that a variable or function argument can contain any type of value at any time (this also goes for function return types):

Dynamic typing example


 1 <?php
 2 
 3 function fn($p)
 4 {
 5     return $p;
 6 }
 7 
 8 class C1
 9 {
10 }
11 
12 class C2
13 {
14 }
15 
16 $x = 42; // $x contains an integer
17 
18 $x = 12.5; // now $x contains a float
19 
20 $y = fn(123); // $p in fn() contains an integer and $y contains an integer
21 
22 $y = fn(false); // $p in fn() contains a boolean and $y contains a boolean
23 
24 $c = new C1(); // $c contains a C1 instance
25 
26 $c = new C2(); // $c contains a C2 instance

In contrast: in a statically typed language a variable, function argument or return value can only ever be the type it is defined to contain. If another type is assigned it will either cause an error, or it will get converted. Here’s a C++ version of the last example:

Static typing example (in C++)


 1 int fn(int p) {
 2     return p;
 3 }
 4 
 5 class C1 {
 6 };
 7 
 8 class C2 {
 9 };
10 
11 int main() {
12     int x = 42; // x contains an integer
13 
14     x = 12.5; // x contains 12, it keeps only the integer part
15 
16     y = fn(123); // p in fn() contains an integer and y contains an integer
17 
18     y = fn(false); // p in fn() contains 0 and y contains 0
19 
20     C1 *c = new C1(); // c contains a C1 instance
21 
22     c = new C2(); // this is an error as c can only contains instances of C1
23 }

Statically typed languages have great benefits. Because you always know what type everything is, there’s never a chance of you doing something to a variable which is not allowed to be done the type it contains. On the other hand, dynamically typed languages let you get on and do things quickly and without having to worry about how to work with type constraints.

Since static typing does have benefits, PHP introduced typehints on function arguments. Typehints allow you to specify exactly what user defined type a function accepts for each parameter; PHP will throw an InvalidArgumentException exception if the wrong type is given:

PHP typehint example


 1 <?php
 2 
 3 class C1
 4 {
 5 }
 6 
 7 class C2
 8 {
 9 }
10 
11 function fn(C1 $c)
12 {
13 }
14 
15 fn(new C1()); // works perfectly
16 
17 fn(new C2()); // error
18 
19 fn(5); // error

Frustratingly PHP does not allow typehints for scalar types or function return values (yet).

However, even though PHP is a dynamically typed language you should still strive to keep your typing sensible. This means that if you create a variable that contains a specific type, you should try not to reuse it by assigning a new value of a different type to it. Also, don’t call methods on objects if they are not in the typehinted interface. If you do PHP will produce be an error but it’s really not good practice:

Mis-using an interface in PHP


 1 <?php
 2 
 3 interface Fooer
 4 {
 5     public function doFoo();
 6 }
 7 
 8 class FooBar implements Fooer
 9 {
10     public function doFoo()
11     {
12     }
13 
14     public function doBar()
15     {
16     }
17 }
18 
19 function performAction(Fooer $f)
20 {
21     // This is fine, doFoo() is defined in the Fooer interface
22     $f->doFoo();
23 
24     // Don't do this, $f is a Fooer and doBar() is not defined
25     // in the Fooer interface
26     $f->doBar();
27 }
28 
29 performAction(new FooBar());

Throughout this book I will be writing PHP code as if I’m writing in a statically typed language 90% of the time - using typehint whenever possible. However, PHP is still a dynamic language and some times it’s helpful to take advantage of this; whenever I do this I will point it out and explain my reason for choosing to do so.

Front Controllers

The front controller is a design pattern for web applications which involves creating a single entry point into your application. It requires you to configure your webserver to redirect all requests to a single PHP script which then processes the request and decides what content to display.

Let’s take a look at an example:

The Traditional Approach

First, let’s look at the traditional approach of using PHP. Create 2 files inside an empty folder, the first one we’ll call page1.php:

page1.php


1 <?php
2 
3 echo 'You are on page 1';

And the second one we’ll call page2.php

page2.php


1 <?php
2 
3 echo 'You are on page 2';

Next open a terminal and cd into the directory containing these files, Now, use the following command to start up PHP’s built in webserver:

1 $ php -S localhost:8080

Now if you open your browser and go to http://localhost:8080/page1.php then you will see You are viewing page 1. If you then go to http://localhost:8080/page2.php you will see You are viewing page 2.

When you are done, press CTRL+C in your terminal to stop the webserver.

This is the approach that you normally first learn when starting out with PHP. There’s nothing wrong with this approach, but, in general using a front controller is better so let’s take a look at that.

Single Entry Point

Create a new folder and this time create a single file called index.php containing:

index.php


1 <?php
2 
3 echo 'You are looking at: ' . $_SERVER['REQUEST_URI'];

Then, in the terminal cd to this new directory. This time start the PHP built in webserver with the name of the file we want to use as the application entry point. Like so:

1 $ php -S localhost:8080 index.php

Again open your browser and visit http://localhost:8080/page1 and you will see You are looking at: /page1, and again go tohttp://localhost:8080/page2 and you will see You are looking at: /page2.

So, as you can see, anything you type after the http://localhost:8080 is redirected to the index.php file, and you can use the $_SERVER superglobal to get the actual URI requested.

The Simplest Front Controller in the World

Next, let’s modify the index.php file to look like this:

index.php


 1 <?php
 2 
 3 switch ($_SERVER['REQUEST_URI']) {
 4     case '/page1':
 5         echo 'You are viewing page 1';
 6         break;
 7 
 8     case '/page2':
 9         echo 'You are viewing page 2';
10         break;
11 
12     default:
13         header('HTTP/1.0 404 Not Found');
14 
15         echo '<html>'
16             . '<head><title>404 Not Found</title></head>'
17             . '<body><h1>404 Not Found</h1></body>'
18             . '</html>';
19 }

Now if we go to our browser and go to http://localhost:8080/page1 or http://localhost:8080/page2 then they work as expected. Also, going to http://localhost:8080/anything-else now shows a 404 message.

Obviously this is a pretty pointless and limiting front controller, but hopefully you now understand the theory behind it.

Stop the webserver again by pressing CTRL+C in the terminal.

Front Controllers using Apache

In order to use a front controller with Apache you need to tell it where to find the PHP script to be used for the application entry point. As of Apache version 2.2.16, you can simply do this by adding the following to the .htaccess file in your document root:

.htaccess


1 FallbackResource /index.php

Standards

As a language gets more powerful it often allows many ways and approaches to achieve the same thing. Each person then has their own preferences of how they personally like to do things.

On one hand this is great: it allows programmers to be expressive and to write their code in the way which best fits how they think, lay it out in they way which looks the most aesthetically pleasing to them, and structure it in the way which they find easiest to navigate.

On the other hand this becomes a total nightmare: when you are working with several libraries, all written by different programmers who each have their own way of doing all things. You have to learn each of the different approaches to efficiently navigate and understand each author’s code. Also, it may make it tricky for some of the libraries to happily interact with each other.

For the reasons just mentioned, programmers get together in groups and create standards, these are a nice middle ground which everyone is mostly happy with. You’ll often find that you won’t agree with everything defined in a standard, but by putting that to one side and accepting it you reap the benefits of having your code being much more consistent with all the other users of the standard’s code - as well as any tools which have been built to work with that standard.

PHP-FIG

Introducing PHP-FIG! PHP-FIG or the PHP Framework Interoperability Group is a group built up of various key people in the PHP community who have got together and started to build some standards for using PHP. Many PHP software projects have now adopted or are adopting many of these standards. I fully recommend you do the same!

At the time of writing this there are 5 published standards:

Standard Description
PSR-0 Autoloading Standard
PSR-1 Basic Coding Standard
PSR-2 Coding Style Guide (implies PSR-1)
PSR-3 Logger Interface
PSR-4 Improved Autoloading (an extension to PSR-0)

And a 3 more in discussion:

Standard Description
PSR-5 PHPDoc
PSR-6 Caching Interface
PSR-7 HTTP Message Interfaces

In this book I will be using PSR-0 or PSR-4 for all code (except in some small examples) and PSR-2 for coding style. I will explain a bit more about these in the next few sections.

For more Information on PHP-FIG visit the website.

PHP The Right Way

PHP The Right Way is not a standard as such, it’s simply a website which lists lots of things about how PHP should be used if you are serious about writing good code. It contains lots of fantastic advice and I highly recommend studying it.

Docblocks

Docblocks are comments which contain annotations which can be added to your code to make it possible to generate documentation about your codebase automatically. One such document generation tool is phpDocumentor. This can be fantastically useful if you are building a library for others to use, since you can easily generate great API documentation using it.

There is however another use for it; we’ve already talked about typehints which, by enforcing the types of function arguments, provide an extra level of documentation to people reading the code; it helps them to understand it quicker. They also help IDEs provide auto completion functionality while you’re writing the code. This is great, but so far PHP has only gone half way - as I said earlier there are no typehints for function return values or for scalar types. Also, the type of a variable or property cannot be defined. Therefore, I’ve made it a habit to document these by using PHPdoc tags. I hope one day PHP will add more complete typehinting.

The format of docblocks are fairly standard now, but there’s work to fully standardise it with PSR-5.

Here’s a little example of how I’ll be using docblocks in the code in this book:

Using docblocks to annotate types


 1 <?php
 2 
 3 class Example
 4 {
 5     /** @var string */
 6     private $name;
 7 
 8     /** @var Email */
 9     private $email;
10     
11     /** @param string $name */
12     public function addCustomer($name, Email $email)
13     {
14         // ...
15     }
16 
17     /** @return Customer[] */
18     public function getCustomers()
19     {
20         // ...
21     }
22 }

Docblocks allow you to add much more detail than I’ve shown here. You can give descriptions and details for the file, the class, any variables, properties or parameters, etc. But since I don’t want to generate an API document for this codebase, I’m only using it to specify the types which cannot be specified directly in PHP.

The Autoloader

You have may have never created a PHP autoloader, you may have never ever heard of one, but if you’ve every build an application using a recent PHP framework you have probably used one. However, if you’re not aware of the autoloader and you’re including all your different classes and functions by using PHP’s require, require_once, include and include_once statements, then you need to STOP and read this section now!

The autoloader is a system in PHP where you can create a callback function that will be called if you try to use a class which has not yet been defined. This callback receives the name of the class trying to be used as a parameter. The function can then use the name to lookup and require the file needed to provide the class definition.

In order to use an autoloader callback you can either define a function called __autoload which will provide the autoloading logic. Or, you can use the more recent and more flexible spl_autoload_register function to register your autoloading function.

Now you know what an autoloader is there’s some good news: there’s no actual need to write the autoloader function yourself, there’s a wonderful tool called Composer which can take care of that for you. However, if you do want to look into autoloading in more detail you can read about it in the manual.

PSR-0 - Autoloading Standard

Before talking about Composer I’d like to first introduce PSR-0. PSR-0 is a standard which was designed to make it easy to find the files where given classes are defined.

The basic rules of PSR-0 are as follows:

  • There is exactly one class defined per file.
  • The file name is the same name (and case) as the name of the class defined inside it, with .php appended to it.
  • The file exists in a directory structure which fully matches the namespace in which the class is defined.

The full PSR-0 specification can be read on the PHP-FIG website.

Example

A file located at /home/tom/projects/AutoloadExample/src/MyApp/Entity/Contact.php would contain the following class definition:

PSR-0 compliant class


1 <?php
2 
3 namespace MyApp\Entity;
4 
5 class Contact
6 {
7     // ...
8 }

Whatever comes before the root namespace in the file path (in this case /home/tom/projects/AutoloadExample/src) is not important, so long as the FQCN is mirrored in the folder structure up to the class name.

PSR-4 - Improved Autoloading Standard

PSR-4 improves on the PSR-0 standard. It removes some old, obsolete features and allows a namespace prefix to be defined. If your whole application exists under a single namespace this remove the need of having a directory level for that namespace.

Using the previous PSR-0 example: if the prefix MyApp is chosen then the Contact class definition can remain exactly the same, but the file is instead stored in /home/tom/projects/AutoloadExample/src/Entity/Contact.php.

Composer

Composer is a dependency manager for PHP. It allows you to specify all the libraries and tools that your PHP project depends on in a simple JSON file. It will then fetch the correct versions of those dependencies (and all their dependencies) into your project.

This means that it’s easy to distribute your project without including its 3rd party dependencies. While making it very easy for users or developers working on the project to easily install them themselves. It also makes it easy to quickly update to newer versions of dependencies.

Composer installs the dependencies locally to the project in a directory called vendor, rather than installing them globally onto the system. This is a definite plus, as it means you can run many projects on the same system, all working with different versions of their dependencies and without getting in to a mess.

Now this is all very interesting, but you might have no intention of using any external libraries or tools with your new project. So is Composer still useful?

The answer is most definitely yes:

  • Firstly, there are lots of great development tools which can be installed via Composer. You should be using these tool even if you don’t intend on using 3rd party libraries.
  • Secondly, you may not intend on using 3rd party libraries but if you start off using Composer from the beginning, you can always change your mind and add a dependency very easily later on.
  • Thirdly, Composer provides a nice and easy to set up autoloader for PHP. By simply adding a few lines of JSON to your project, your autoloader is set up and ready to go.

While there are plenty of people out there who will have a good reason not to use Composer, in my opinion if you don’t have one, then you should definitely be using it in your projects.

So, that’s a little intro on what Composer can do for you. You can find out about all its features and settings in the documentation but, to save you the hassle of reading it all now let’s have a look at a little example of the basics.

Composer Example

Installing

The various installation options for Composer can be found on the website.

You can either install a copy locally to your project which means your use it by running:

1 $ ./composer.phar

Or you can install it globally on your system and rename it to composer. I have done it this way so on my system I run Composer by simply typing:

1 $ composer

If you have installed it differently from me you will need to adjust my instructions accordingly.

Setting up the Autoloader

To start off, create a new project directory and cd into it:

1 $ mkdir ComposerExample
2 $ cd ComposerExample

If you want to use Composer locally you’ll want to install it inside this directory now. However, if you have installed it global already then you can just carry on.

Next up, create a file in the project folder called composer.json and add the following content:

composer.json


1 {
2     "autoload": {
3         "psr-0": {
4             "ComposerExample\\": "./src"
5         }
6     }
7 }

What we have told Composer to do here is set up its autoloader, to locate any classes in the ComposerExample namespace, by using the PSR-0 file structure inside a directory in our project called src.

Next, tell Composer to apply these settings with the following command (remember you will need to adjust it if you have installed Composer locally):

1 $ composer install

Once it has finished, you will notice it has created a new directory called vendor and another file called composer.lock. If you’re are using a source control system like git (and you really should be!), then you should instruct it to ignore the vendor directory from the repository. The composer.lock file should be added to the repository though.

Next up, create a directory structure for our PSR-0 classes to go in:

1 $ mkdir -p src/ComposerExample

Then create a file called src/ComposerExample/HelloApplication.php with the following content:

src/ComposerExample/HelloApplication.php


 1 <?php
 2 
 3 namespace ComposerExample;
 4 
 5 class HelloApplication
 6 {
 7     public function run()
 8     {
 9         echo "Hello beautiful World!\n";
10     }
11 }

Finally, create a file called run.php containing:

run.php


1 <?php
2 
3 // Load up Composer's autoloader
4 require_once __DIR__ . '/vendor/autoload.php';
5 
6 // This class will loaded automatically
7 $app = new \ComposerExample\HelloApplication();
8 $app->run();

Now to see it work run:

1 $ php run.php

Ta da!

Composer also supports PSR-4. To use it instead simply use psr-4 in the composer.json. When doing this everything in the src folder will have the prefix (ComposerExample) applied to the namespace so the ComposerExample directory level would have to be removed.

Adding a Dependency

Next let’s dress it up a bit using a 3rd party library. I had a little hunt around for something interesting to try and found Maxime Bouroumeau-Fuseau’s ConsoleKit library.

First up, let’s add it to the project as a dependency by updating our composer.json file to contain the following:

composer.json


 1 {
 2     "require": {
 3         "maximebf/consolekit": ">=1.0.0"
 4     },
 5     "autoload": {
 6         "psr-0": {
 7             "ComposerExample\\": "./src"
 8         }
 9     }
10 }

Then we tell Composer to download its new dependency by running:

1 $ composer update

This should download the ConsoleKit package, which will now be ready to use. Let’s update our ComposerExample\HelloApplication class to look like this:

src/ComposerExample/HelloApplication.php


 1 <?php
 2 
 3 namespace ComposerExample;
 4 
 5 use ConsoleKit\Console;
 6 
 7 class HelloApplication extends Console
 8 {
 9     public function run()
10     {
11         $console = new Console();
12         $console->addCommand('ComposerExample\\HelloCommand');
13         $console->run();
14     }
15 }

And let’s add a new class called ComposerExample\HelloCommand like so:

src/ComposerExample/HelloCommand.php


 1 <?php
 2 
 3 namespace ComposerExample;
 4 
 5 use ConsoleKit\Command;
 6 use ConsoleKit\Colors;
 7 
 8 class HelloCommand extends Command
 9 {
10     public function execute(array $args, array $options = array())
11     {
12         $this->writeln('Hello green World!', Colors::GREEN);
13     }
14 }

Now to try to run it:

1 $ php run.php hello

There we have it, we’ve simply added a dependency to our app and made use of it. Composer has done all the hard work of downloading it and setting up the autoloader required to find it.

Adding Development Tools

Composer’s require section lets you define the requirements your project needs to run. It also has a require-dev section which is for dependencies which you want to use for development only - testing tools for example.

CodeSniffer is a tool which checks that your code follows a given coding style, lets add it to our project. To use it update the composer.json file to include the CodeSniffer development dependency:

composer.json


 1 {
 2     "require": {
 3         "maximebf/consolekit": ">=1.0.0"
 4     },
 5     "require-dev": {
 6         "squizlabs/php_codesniffer": "1.*"
 7     },
 8     "autoload": {
 9         "psr-0": {
10             "ComposerExample\\": "./src"
11         }
12     }
13 }

Once again, tell Composer to update its dependencies by running:

1 $ composer update

After it has finished, CodeSniffer is ready to be used. When Composer installs any tools it will install the executable files in a local directory, by default this directory is vendor/bin.

We can now run CodeSniffer by with the following command:

1 $ vendor/bin/phpcs --standard=psr2 src

If all the code in our src directory conforms to the PSR-2 coding style then CodeSniffer should have completed without and errors.

To make life easier, your can add vendor/bin to your operating system’s PATH variable so you can execute your tools more easily. On Linux you do this by adding the following to your .bashrc file in your home directory:

PATH=./vendor/bin:$PATH

After you have done this you should be able to simple run:

1 $ phpcs --standard=psr2 src

Keeping Logic and Display Code Separate

PHP lets you easily mix text output (usually HTML) with your logic. This makes PHP a really useful and powerful web templating language, but it also makes it very easy to write hideous code which mixes application logic in with the HTML output like so:

Mixing logic and display code


 1 <?php
 2 
 3 $repository = new CustomerRepository();
 4 
 5 ?>
 6 
 7 <h1>List Customers</h1>
 8 
 9 <?php
10 
11 function escape($string)
12 {
13     return htmlentities($string);
14 }
15 
16 if ($_POST['search']) {
17     try {
18         $customers = $repository->getMatching($_POST['search']);
19     } catch (LoadingException $e) {
20         die('The was an error');
21     }
22 }
23 
24 if (count($customers)) { ?>
25     <table>
26         <thead>
27             <tr>
28                 <th>Name</th>
29                 <th>Email Address</th>
30                 <th>Phone Number</th>
31             </tr>
32         </thead>
33         <tbody>
34             <?php foreach ($customers as $customer) { 
35                 echo '<tr>';
36                 echo '<td>' . escape($customer->name) . '</td>';
37                 $customer->printEmail();
38                 ?>
39                     <td><?php echo escape($customer->phone); ?></td>
40                 </tr>
41             <?php } ?>
42         </tbody>
43     </table>
44 <?php } else {  ?>
45     <p>No customers found.</p>
46 <?php } ?>

I think we can all agree that is pretty ugly, but if it’s left to get out of control it can get a lot uglier!

The solution to this is to not mix your HTML and PHP code together and instead maintain a clear separation between the two. This also allows designers to work on the user interface without have to understand the codebase.

There are templating libraries for PHP such as Twig and Smarty which introduce their own template tags for using in your HTML templates. You can also use PHP itself to do the templating, but if you do you really should maintain the discipline of keeping logic and view code separate; it may even be worth using different file extensions to keep it clear - .php for logic and .phtml for HTML templates is often used.

The choice between using PHP or a dedicated templating library can often be down to who is going to have access to modify the view templates. If your designers are in house, trustworthy and trained, then using PHP can be the easiest approach. However, if you are out sourcing the design work to people you trust less, then using a templating engine means they cannot compromise the security of the application by adding bad PHP code into the templates.

Coding Style

Coding style is simply the way you layout and format your code. In the previous Standards section I talked about how they were introduced to maintain a consistent approach to using a programming language between many developers. Using a consistent coding style is one element of this.

Coding style standards define things like:

  • How many spaces should be used to indent code.
  • If the opening brace for a function’s body goes on the same line as the function definition, or on the line after.
  • If variables be named using camelCase or snake_case
  • etc.

As with all standards, it’s unlikely that you’ll find one which you agree with every bit of. Even so, rather that creating your own perfect one which no one else uses, you should use a well used one you like mostly.

At the moment the best one to use for PHP in my opinion is the one defined by PSR-2 as many people have adopted it. All application code I present in this book will follow the PSR-2 standard - with a couple of exceptions:

1. Unit Tests

When writing unit tests I follow PSR-2 apart from 2 elements - both regarding the method names for the tests.

  • Firstly, instead of using camelCase for test method names I use snake_case. This is because the method names are sentences, and with snake_case it’s easier to separate the words visually when reading it.
  • Secondly I’ll omit the public access specifier as it’s the default in PHP and keeps the line shorter with long test method names.

Unit test coding style example


 1 <?php
 2 
 3 namespace spec;
 4 
 5 use PhpSpec\ObjectBehavior;
 6 
 7 class ExampleSpec extends ObjectBehavior
 8 {
 9     function it_adds_2_numbers_together()
10     {
11         $this->add(5, 2)->shouldReturn(7);
12     }
13 }

2. Template Code

When writing template code using PHP I prefer to keep it looking as close to HTML as possible. I try to keep the code inside PHP tags to single expressions and I use the foreach :/endforeach, if :/endif, etc. style of code blocks instead of using braces as I think they are easier to match up in this context. Here’s an example:

Neat display template code example


 1 <h1>List Customers</h1>
 2 
 3 <?php if (count($customers)) : ?>
 4     <table>
 5         <thead>
 6             <tr>
 7                 <th>Name</th>
 8                 <th>Email Address</th>
 9                 <th>Phone Number</th>
10             </tr>
11         </thead>
12         <tbody>
13             <?php foreach ($customers as $customer) : ?>
14                 <tr>
15                     <td><?php echo escape($customer->name); ?></td>
16                     <td><?php echo escape($customer->email); ?></td>
17                     <td><?php echo escape($customer->phone); ?></td>
18                 </tr>
19             <?php endforeach; ?>
20         </tbody>
21     </table>
22 <?php else : ?>
23     <p>No customers found.</p>
24 <?php endif; ?>