TODO: Add info about self:: and $this=

Classes are at the foundation of Object Oriented Programming (OOP); its cornerstone. The appropriate use of classes greatly benefits a project and allows for much more advanced code, in general, than the programmatic counterparts. Also, classes are at the very heart of Design Patterns.

What is a class?

Classes are

  • Collections of functions, variables, and constants.
  • Blueprints — or DNA, if you will — of objects: discrete units of action and information.
  • Almost always named after nouns — a person, place, abstract idea, etc.
  • Representations of a concept or abstraction for a specific domain that commit certain actions and/or store certain states. For instance, a class called UserManager that handles user actions.

What are classes good for?

Classes are great at

  • Organizing hierarchies and relationship maps between distinct information and action domains.
  • Organizing and packaging code in discrete, logical groupings,
  • Reusing code efficiently and wisely, without having to copy and paste,

Classes are great at organizing hierchies and relationship maps

Classes can make it much easier to see how two or more really different things are related. In the below diagram, we have the abstract notion of a Car, three Car implementations, and two different types of engines.

Classes are great at handling hierarchies

ToyotaCar class inherits from a class called Car and contains a member object called $engine. Now, depending on whether the car is an Avalon or Prius, it will have either a CombustionEngine or HybridEngine. Now imagine that Ford has its own FordCombustionEngine off to the side, but that they lease Toyota’s Hybrid technology (which they do!) and use the Toyota HybridEngine in their Ford Focus Hybrid.

Classes are great at reusing code efficiently

In the above example, we don’t have to duplicate code for Ford to use the HybridEngine from Toyota, and Toyota doesn’t have to reinvent the wheel, either: they can take all that they can from the Engine class. Since HybridEngine is a combustion+electric hybrid, this means much of its functionality can be inherited from Engine without having to worry about duplicated code.

How do I create a class?

Classes are composed of any number of properties (variables specific to that class), constants, and functions. While there is no firm restriction on how to organize a class’ members in PHP, there is a widely-accepted standard laid out by the official Zend Coding Standard:

The Scope of Class Properties and Functions

In PHP, as most OOP languages, a class’ properties and functions can be in one of three scopes: Private, protected or public.

  • Private properties and functions are accessible only to functions inside the class itself. This is the safest scope in which to place your properties and functions, as it helps ensure that your class remains well-encapsulated Advanced Topic and is well-designed.
  • Protected properties and functions are accessible to the class itself and its descendants. Over-use of protected properties strongly hints at possibly poor application architecture, particularly if you find yourself moving previously-private properties to the protected scope. For more on why it is to be avoided, see Designing by Inheritance vs. Composting Advanced Topic.
  • Public properties and functions are accessible everywhere. While it is agreed by everyone that public functions should be absolutely limited to only what is needed, debate still rages on as to when to make properties public. For more details, see The Public Properties Debate Advanced Topic.

How should a class be structured?

  1. Class names should:
  2. Constants should be defined first, then its properties, followed by its functions.

An Example Class

class LoginController
{
    const LOGIN_SUCCESS = "Login successful.";
    const ERROR_INVALID_LOGIN = "Invalid login. Try again.";

    private $userManager;

    public function __construct()
    {
        $this->userManager = new UserManager();
    }

    public function login()
    {
        $username = filter_input(INPUT_POST, 'username', FILTER_SANITIZE_STRING);
        $password = filter_input(INPUT_POST, 'password', FILTER_SANITIZE_STRING);

        $status = $this->userManager->validate($username, $password);

        // Returns true on successful login, false otherwise.
        if ($status == UserManager::VALID_USER)
        {
            return self::LOGIN_SUCCESS;
        }
        else
        {
            return self::ERROR_INVALID_LOGIN;
        }
    }
}

PHP Tutor Lessons