Writing re-usable OOP PHP code


#1

This tutorial stems from a discussion on StackOverflow (http://stackoverflow.com/questions/16700375/alternatives-to-static-methods-in-a-framework-php/16700764) and is meant as a tutorial to writing efficient, re-usable and extensible code.

Performance might be an obvious thing to head for. However, why would you bother with reusability and extensibility? Because it sucks to have to deal with more than one codebase, and it sucks to have stuff magically break on you every time someone changes something. Believe me, I have been there - I have inherited codebases from people who did not write code with maintainability in mind (and was one of those before!), and frankly… the time that you save writing stuff quickly, you lose ten times over due to bugs the moment a slight mod is made.

We’ll be covering topics such as:
- Correct OOP usage: classes and interfaces, abstract classes, inheritance and extensions, when to use static methods, dereferencing (on this forum)
- Unit testing: what it is, how it helps, good frameworks, how it is awesome when you’re working in a team (on this forum)
- Advanced OOP usage: mocks, stubs, dependency injection, the Hollywood principle, separation of concerns, MVC/AOP approaches (on my blog, too long and too intensive for a post. Also, useful to have PHP live demos for this one…)

I’ll take a while to write those up. Keep checking this thread for updates! :slight_smile:


#2

[size=14pt]OOP Basics[/size]

PHP acquired its OOP syntax in PHP4, but only really had all the concepts in PHP5. It is still being extended, with the latest addition being Traits (PHP5.4). Before going into the details, what is OOP?
OOP is a programming methodology stemming from non-functional code. Instead of having your code run from start to finish with branching (the way machine code does it), your code can be neatly structured into objects. This does not detract from the ultimately linear execution that is typical of PHP, but it itself allows you to separate parts of your code. It also introduces the concept of an object: an entity with a finite state, that is separate in scope from the global scope of your code.

Objects in PHP can be classes or interfaces. We’ll go over both.

Classes

Classes are your go-to object definition in PHP. They can host properties and methods, and each property/method has three scope access restrictions available to it:

  • Public: your property/method is fully visible to the outside world and accessible using the -> operand on the instance of the class
  • Private: your property/method is private, and attempts to read or modify it will throw a fatal error if performed outside of the scope of the class
  • Protected: your property/method will throw a fatal error if you attempt to read/modify it. In addition, it is invisible to extending classes

Class extension is done using the keyword extends. Both target and source must be of the same type (you can only extend a class with a class, or an interface with an interface - more on that later).

The difference between private and protected is best illustrated by a simple example:

[php]<?php
class Definitions {
public $foo = 1;
private $bar = 2;
protected $baz = 3;
}
class Defs extends Definitions {
public $baz = 4;
}
$c = new Definitions();
$cExt = new Defs();

echo $c->foo; // prints 1
echo $c->bar; // Fatal error
echo $c->baz; // Fatal error

echo $cExt->baz; // prints 4[/php]

A function is typically called a method if defined within a class. It, too, can be public, protected or private, and the scoping access works in exactly the same fashion. The keyword function is used to define functions within a class, as follows:

[php]<?php
class MyFunctionClass {
public function Testfunction() {
echo “foo”;
}
}
$c = new MyFunctionClass();
$c->Testfunction();
[/php]

A function can also take arguments, the same way as any normal PHP function can. Note however that you cannot redefine a function. Explicit overloading, the way it is done in Java or C++, is not possible in PHP.

Extensions

Extensions allow you to tell PHP “take all the definitions from this class, but also these new ones”. It allows you to take the bulk of an existing object, append to it, and call the new “added stuff total” a different name. This is very handy, but also poses a lot of caveats.

An extension is done using the extend keyword, as follows:

[php]<?php
class Class1 {
public function foo() {
echo “Fooo”;
}
}
class Class2 extends Class1 {
public function bar() {
echo “Bar”;
}
}
$c = new Class2();
$c->foo(); // “Fooo”;
$c->bar(); // “Bar”;[/php]

Note that, when extending, you can re-scope properties and objects. You, however, still can’t access a private property from the extended class. The classes are still separate on that respect.

Note that you can only extend one object. This is one thing that majorly sucks about PHP, and we’ll learn how to overcome this one in part 3.

Interfaces

These may look stupid at first, but in part 3, they’ll become extremely handy. Before introducing them, let’s introduce a concept that will become very handy in the future: function signatures. A function signature is the entire list of parameters and type-hinting of a function. That’s it. Simple as that.

Why did I mention that? Because interfaces allow you to enforce them. They’re a control and an extension tool. They allow you to enforce strict guidelines on certain functions of a class. PHP makes heavy use of them and opens up a few interfaces of its own, too!

An interface also has a few restrictions:

  • No properties
  • No function code - you only provide the signatures

An interface is defined as follows:

[php]<?php
Interface MyInterface {
public function foo();
public function bar(stdClass $foo);
}
class MyClass extends MyInterface {
}[/php]

Note that the code above will throw a fatal error: the interface requires foo and bar to be defined and have a valid definition, but MyClass does not do so.

An interface prevents you from deviating from the signature it expects on:

  • the name of the functions
  • the parameters of the functions
  • the visibility of the functions

The obvious advantage of using interfaces is to constrain your fellow coders into providing a set of fixed, pre-defined functions on objects they pass to and fro. They also can be typehinted, which is the cornerstone of something called Dependency Injection. The following code outlines a few of the properties outlined here:

[php]<?php
interface Foo {
public function bar();
}

class Bar {
public function isFoo(Foo $t) {
echo “oh yes!”;
}
}

class FooInst implements Foo {
public function bar() {
echo “test”;
}
}
$c = new FooInst();
$d = new Bar();
$c->bar();
$d->isFoo($c);[/php]

Note that you can implement multiple interfaces on the same object, and that implementation is inherited: if class A implements ArrayAccess, class B extends class A, class B will also implement ArrayAccess.

A few useful PHP native interfaces: ArrayAccess (allows you to use your class as an array: $object[“blah”] & co), SeekableIterator (allows you to throw your object in foreach loops), SplObserver (and SplSubject - allows you to use the Observer design pattern native to PHP)…

Abstract classes

An abstract class is a shorthand name for a class with abstract methods. It is the half-way step between a class and an interface, in that:

  • It allows you to define properties
  • It allows you to define function signatures to fill in

They serve a very specific purpose, and should not be abused, as they have the same restrictions as classes: you can only extend one.

A good way of using them would be a chain like this one:

  • MyObjectInterface is implemented by MyObjectAbstract, which contains a bunch of properties and generic method implementations
  • Every type of object extends MyObjectAbstract

A “real-world” example of this:

[php]<?php
class HTMLInterface {
public function print();
public function set($code);
}

class HTMLCode implements HTMLInterface {
private $code = “”;
public function print() {
echo $this->code;
}
public function set($code) {
if ($this->sanitize($code)) $this->code = $code;
}
abstract public function sanitize($code);
}
class HTML extends HTMLCode {
public function sanitize($code) {
// Sanitization here
}
}
class PHP extends HTMLCode {
public function sanitize($code) {
// Different sanitization here
}
}[/php]

You are then certain that:

  • Any HTMLCode element will have all your structure
  • To define a new one, you only need to define sanitize($code) as public! No more “lugging 2353532 methods”!

The main drawback of this is that you can, once again, only extend one. Another way to come across this gap in feature is to use traits. I’ll cover this in part 3.

Static scoping

Class can have properties bound to their instance. However, they can also have static properties and methods, which are bound to the class definition and can be accessed in every instance using the static:: or self:: keywords within the class, and by using the exact class name from the outside.

This follows the same scoping rule, and is pretty good to define properties common to every member of a class. They suck if they have to be used outside a class, however, as they require you to know the exact name of the class - horrible for unit testing. More on that later.

Here is a “good” example:
[php]<?php
class MyAuthor {
protected static $table = “my_db_table_for_authors”;
public function test() {
echo self::$table;
}
}
$c = new MyAuthor();
echo $c->test();[/php]

Note that, whilst you can access static methods and properties in a dynamic context, the converse does not hold. In a static context, using $this will throw a fatal error.