This repo contains my notes on Object oriented programming using php.
There are two directories of interest:
./snippets
: contains code snippets. Currently, only UltiSnips vim./src
: contains examples for every section in this file, it can be used while solving challenges.For contribution see here
OOP is a programming style in which we group methods and variables of a particular topic into single class. For example, the code that relate users will be in User class. OOP is heavily adopted because it support code organization, provides modularity and reduces the need to repeat ourselves.
Classes are used to group the code that handles a certain topic into one place. It is a template for creating objects, providing initial values for state (properties/attributes) and implementations of behavior (methods.
A person can be seen as an object defined by two components: attributes (such as eye color, age, height) and behaviors (such as walking, talking, breathing). In its basic definition, an object is an entity that contains both data and behavior. Each person is different in terms of there age and in how they walk or talk. But they all instance of a class that organize their attributes and behavior for example Human class.
In OOP, objects are the building blocks, they are instances of a some class. A program that leverages OO style is basically a collection of objects. The behavior of an object represents what the object can do and the data stored within an object represents the state of the object.
$this
keyword are used to interact with/refer to a class method or properties
from within the class. Among different uses of $this
keyword, there is
chaining methods and properties.
public
if we want the methods or properties to be accessed on public
scope as well as within the class.private
if we want the methods or properties to be accessed within
the class only.protected
if we want the methods or properties to be accessed within
the class and class child.To access private
properties from outside the class, we use publicly defined
setters and getters. Using private properties limit the possible interaction to
our private properties from public scope. This is useful when for example we
want to define a hook each time a method is called to get the model of the
object, such as save the request in a log.
Inheritance is central concept in OOP, they enable us to reduce code
duplications by creating a parent/master class with properties and method that
can be inherited by child classes. In php, and many other languages, we use extends
keyword to inherit from another class.
Put simply, an abstract class is a class with at least one abstract method and with a abstract keyword in front of it. They get used for multiple reasons:
Abstract classes cannot be instantiated, and whatever non-abstract class derived from it must include actual implementations of all inherited abstract methods and properties.
An interface can be seen as an outline of what a particular object can do. They are considered one of the main building blocks of the SOLID pattern. With interfaces we can create code which specifies which methods a class must implement, without having to define how these methods are implemented.
A lot of people may find interface to be similar to abstract classes, or doesn't know which one to choice, here a few notes on that:
Interfaces are contract, we "implement" them to provide code and behavior that fit the description of the interface. In the other hand, Abstract Classes are behavior, we "extend" them and add additional behaviors, sometimes we are required to add specific behavior left that are left out by the class (methods marked with "abstract").
Interface maybe used when multiple classes need to define the same methods. However, abstract class might be appropriate when we need the share code between subclasses
Interface | Abstract Class |
---|---|
An interface cannot have concrete methods in it i.e. methods with definition. | An abstract class can have both abstract methods and concrete methods in it. |
All methods declared in interface should be public | An abstract class can have public, private and protected etc methods. |
Multiple interfaces can be implemented by one class. | One class can extend only one abstract class. |
Put simply, Polymorphism is a principle that state that methods in different classes doing similar things should have the same name.
Type hinting is used to specify the expected data type for an argument. It is used for better code organization and improved error messages.
// Class
function funName(ClassName $object) { }
// Strings
function funName(string $arg) { }
// Array
function funName(array $arg) { }
// Boolean
function funName(bool $arg) { }
// Integers
function funName(int $arg) { }
// Floats
function funName(float $arg) { }
To specify the output type of a function, we add after (expected type)
: int
Static methods and properties are those properties with static
keyword
in front of them. They enable us to approach methods and properties of a class
without the need to first create an object out of the class. They are used
mainly as utilities. The following are the main use cases for them:
As counters, to save the last value that has been assigned to them. For
example, the method add1ToCars()
adds 1 to the $numberOfCars
property
each time they are invoked.
As utilities for the main classes. Utility methods can perform all kinds of tasks, such as: conversion between measurement systems (kilograms to pounds), data encryption, sanitation, and any other task that is not more than a service for the main classes. The example given below is of a static method with the name of redirect that redirects the user to the URL that we pass to it as an argument.
class Utilis {
static public function redirect($url) {
header("Location: $url");
exit;
}
}
Utilis::redirect("http://www.phpthusiast.com");
Traits are a mechanism for code reuse. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies.
A Trait is similar to a class, but only intended to group functionality in a fine-grained and consistent way. It is not possible to instantiate a Trait on its own.
Some people refer to traits as "like an automatic CTRL+C/CTRL+V for your classes". You specificity some methods in a trait and "import" them into your class. It will make your code behave like the methods were written inside your class.
When using a trait, we should be on the lookout for code duplication and for naming conflicts that are the result of calling the methods in different traits with the same name.
Namespaces and code integration are used when the project grow in complexity, and we need to start organizating our code and integrate them from different resources. Or when we have multiple class or methods with the same name.
Setting up namespace:
src/Car
folder,
as follows src/Car/CarIntro.php
is convention to have file names as same
as class name<?php namespace Acme/Car;
it as
customary to give the src directory the Acme
namespace, or maybe brand
name, and imitate the directory structure.Using a namespace:
require "src/Car/CarIntro.php;"
use Acme\Car\CarIntro;
$carintro = new Acme\Car\CarIntro()
use Acme\Car\CarIntro as Intro;
Dependency injection is the process whereby we input dependencies that the
application needs directly into the object itself. When class A
cannot do its job
without class B
, we say that class A
is dependent on class B
.
When writing a class, it's natural to use other dependencies; perhaps a database model class. So with dependency injection, instead of a class having its database model created in itself, you can create it outside that object and inject it in.
Lets look at the two ways where we make one class dependent on other:
a Car is dependent on Human Driver, so we create HumanDriver
object from the
in the constructor of the Car
class.
class HumanDriver
{
// Method to return the driver name.
public function sayYourName($name)
{
return $name;
}
}
class Car
{
protected $driver;
// Create the driver object in the constructor
public function __construct() {
$this->driver = new HumanDriver();
}
// A getter method that returns the driver object
public function getDriver() {
return $this->driver;
}
}
Tight coupling between classes become a real issue when we need to switch dependencies. In our example, say we have a robot driving the car instead of a human. In fact, when we do tight coupling between classes, we violate a fundamental principle of well designed code called the “single responsibility principle” (SRP), according to which a class should have only one responsibility.
First, rewrite Car
class so it can set its own $driver
property that is
passed as a parameter to the constructor.
// The Car class gets the driver object injected
// to its constructor
class Car
{
protected $driver;
// The constructor sets the value of the $driver
public function __construct($driver)
{
$this->driver = $driver;
}
// A getter method that returns the driver object
// from within the car object
public function getDriver()
{
return $this->driver;
}
}
Then, we inject dependency by first creating the Driver
object and then
injecting this object into the newly created Car
object through the
constructor:
$humanDriver = new HumanDriver();
$car = new Car($humanDriver);
$robotDriver = new RobotDriver();
$car = new Car($robotDriver);
Exception handling is an elegant way to handle errors which are beyond the program’s scope. For example, if our application fails to contact the database, we can use exception handling to contact another data source or to provide instructions to the users that they need to contact technical support.
In php we can handle exception with making the use of Exception
class
Rules to follow when implementing exceptions handling
OOP supports the idea of creating classes that are complete packages, encapsulating the methods and properties of a single entity. So, a class can be represent a logical component. The following are general design guidelines to be followed when developing classes:
User
class and Webapp
class model a real-world entity. The User
and Webapp
objects encapsulate their data and behavior, and they interact through each
other’s public interfaces.If you like to contribute, it's awesome! Just keep in mind this project using phpcs to achieve unified code style. So make sure you run
composer install
to install the dev dependencies
Then you can run code checks by using the composer script
composer phpcs
or use the code beautifier to auto fix violations.
composer phpcbf
Please run phpcs and solve all issues before creating a pull request
(i) This project is not about a real code lib. It's about OOP examples for better understanding. That's why the ruleset.xml exclude 2 fundamental PSR1 rules.
Areas of contribution
./src/challenges