Skip to content

Instantly share code, notes, and snippets.

@Pen-y-Fan
Created March 28, 2020 10:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Pen-y-Fan/de770755d9457db62e308c467380a443 to your computer and use it in GitHub Desktop.
Save Pen-y-Fan/de770755d9457db62e308c467380a443 to your computer and use it in GitHub Desktop.

OOP PHP Bitfumes Webnologies

YouTube OOP PHP Bitfumes Webnologies

Notes & disclaimer

  • The purpose of these notes are to follow the above tutorial, making detailed notes of each step.
  • They are not verbatim of the original video.
  • Although the notes are detailed, it is possible they may not make sense out of context.
  • The notes are not intended as a replacement the video series
    • Notes are more of a companion
    • They allow an easy reference, making it easy to search in one file to find content.
    • Allowing a particular video to be found and re-watched.

OOP PHP | Class Properties & Object #3

<?php
/**
 * Student class
 */

class Student
{
    public $name = "Michael";
    public $attendance = true;
    public $totalMarks = 89;
}

$student = new Student();

echo $student->name . "\n";
echo $student->attendance . "\n";
echo $student->totalMarks . "\n";

echo $student->totalMarks = 99 . "\n";

// Create a new instance of the class.
$student10 = new Student();

/*
Michael
1
89
99
 */

OOP PHP | Functions or Methods #4

<?php
/**
 * Student class
 */

class Student
{
    public $name;
    public $attendance;
    public $totalMarks;

    public function studentDetails($name, $attendance, $totalMarks)
    {
        $this->name = $name;
        $this->attendance = $attendance;
        $this->totalMarks = $totalMarks;
    }
}

$student10 = new Student();
$student10->studentDetails("Michael", false, 99);
echo $student10->name; // Michael

OOP PHP | Method Chaining #5

How to chain results of multiple methods.

<?php
/**
 * Bill class
 */

class Bill
{
    public $dinner = 20;
    public $dessert = 5;
    public $coldDrink = 3;
    public $bill = 0;

    /**
     * Dinner method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function dinner($person)
    {
        $this->bill += $this->dinner * $person;
        return $this;
    }

    /**
     * Dessert method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function dessert($person)
    {
        $this->bill += $this->dessert * $person;
        return $this;
    }

    /**
     * ColdDrink method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function coldDrink($person)
    {
        $this->bill += $this->coldDrink * $person;
        return $this;
    }
}

$bill = new Bill();
echo $bill->dinner(2)->dessert(2)->coldDrink(1)->bill; // 53

OOP PHP | Construct and Destruct #6

<?php
/**
 * Bill class
 */

class Bill
{
    public $dinner = 20;
    public $dessert = 5;
    public $coldDrink = 3;
    public $bill = 0;

    /**
     * __construct method adds 3 to the bill (entry fee)
     */
    public function __construct()
    {
        $this->bill = 3;
    }
    /**
     * Dinner method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function dinner($person)
    {
        $this->bill += $this->dinner * $person;
        return $this;
    }

    /**
     * Dessert method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function dessert($person)
    {
        $this->bill += $this->dessert * $person;
        return $this;
    }

    /**
     * ColdDrink method
     *
     * @param int $person Number attending the dinner
     *
     * @return int
     */
    public function coldDrink($person)
    {
        $this->bill += $this->coldDrink * $person;
        return $this;
    }

    /**
     * __destruct method (resets the bill)
     */
    public function __destruct()
    {
        echo $this->bill = 0;
    }

}

$bill = new Bill();
echo $bill->dinner(2)->dessert(2)->coldDrink(1)->bill; // 53
echo "\n";
// 0 (from the __destruct method)

Access Modifiers #7

<?php

class User
{
    public $name = "Michael";
    private $password = "123456";
    protected $email = "abc@example.com";

    public function getPass()
    {
        return $this->password;
    }

}

class Admin extends User
{
    public function __construct()
    {
        echo $this->email . "\n";
    }
    public function modifyPassword()
    {
        $this->password = "modified" . $this->password;
    }
}

$user = new User;
echo $user->name; // Michael

echo "\n";

// echo $user->password;
// Fatal error: Uncaught Error: Cannot access private property User::$password

// echo $user->email;
// Fatal error: Uncaught Error: Cannot access protected property User::$email

// password can only be accessed from inside the class.
// e.g. but using a get... method
echo $user->getPass(); // 123456

echo "\n";

// Child classes of the parent class can access the protected properties.
$admin = new Admin; // abc@example.com

// Child classes can access public methods from the parent.
echo $admin->getPass(); // 123456

// Child classes do not have access to parent private properties.
// echo $admin->password;
// Notice: Undefined property: Admin::$password

// Child classes do not have access to parent private properties even on methods.
// echo $admin->modifyPassword()
// Notice: Undefined property: Admin::$password;

Inheritance #8

The Apple and Mango class' can inherit the methods and properties of the parent, Fruits class.

<?php

/**
 * Fruits class
 */
class Fruits
{
    public $name;
    public function setName($name)
    {
        $this->name = $name;
    }
}

/**
 * Apple class
 */
class Apple extends Fruits
{
    public function Juice()
    {
        echo 'Juice' . "\n";
    }
}

/**
 * Mango class
 */
class Mango extends Fruits
{
}

$mango = new Mango;
$mango->setName("My Mango");
echo $mango->name; // My Mango

echo "\n";

$apple = new Apple;
$apple->setName("My Apple");
echo $apple->name; // My Apple

echo "\n";

echo $apple->Juice(); // Juice

Implements Interface #9

Example of a similar shape which has two different methods for retrieving the area of the shape. Someone familiar with one shape could easily use the wrong method for another shape.

<?php

class Triangle
{
    public function getArea()
    {
        echo 'Triangle Area';
    }
}

class Rectangle
{
    public function calculateArea()
    {
        echo 'Rectangle Area';
    }
}

$rect = new Rectangle;

// $rec->getArea(); // Error: Call to undefined method Rectangle::getArea()
$rect->calculateArea(); // Rectangle Area
echo "\n";
$triangle = new Triangle;
$triangle->getArea(); // Triangle Area

OOP PHP | Implements Interface #9

<?php

interface ShapeInterface
{
    public function getArea();
}

interface GeometryInterface
{
    public function getPerimeter($value1, $value2);
}

class Triangle implements ShapeInterface
{
    public function getArea()
    {
        echo 'Triangle Area' . "\n";
    }
}

class Rectangle implements ShapeInterface, GeometryInterface
{
    // Fatal error: Class Rectangle contains 1 abstract method and must
    // therefore be declared abstract or implement the remaining methods
    // (ShapeInterface::getArea)
    /*
    public function calculateArea()
    {
    echo 'Rectangle Area' . "\n";
    }
     */
    public function getArea()
    {
        echo 'Rectangle Area' . "\n";
    }
    public function getPerimeter($length, $breath)
    {
        echo 'Rectangle perimeter is the length of the four sides: ';
        echo $length * 2 + $breath * 2 . "\n";
    }
}

$rect = new Rectangle;

$rect->getArea(); // Rectangle Area
// $rect->calculateArea(); // Rectangle Area
$rect->getPerimeter(2, 3);

$tri = new Triangle;
$tri->getArea(); // Triangle Area
// More than one interface can be implemented per class.

OOP PHP | Abstract Classes ans Functions #10

car.php:

<?php

class Car
{
    public function getName()
    {
        return "I am a Car";
    }
}

bwm.php

<?php

class BMW extends Car
{
    public function calculateTankArea()
    {
        echo "Tank area for BMW is xyz" . "\n";
    }
}
<?php

require "car.php";
require "bmw.php";

// $car = new Car; // Error: Cannot instantiate abstract class Car
$car = new BMW; // I am a Car

echo $car->getName(); // I am a Car

// Before the calculateTankArea method was added to BMW class:
// Fatal error: Class BMW contains 1 abstract method and must therefore be
// declared abstract or implement the remaining methods (Car::calculateTankArea)

echo $car->calculateTankArea(); // Tank area for BMW is xyz

// abstract class can work like a normal class and like an interface.

What is Type Hinting #11

person.php:

<?php

class Person
{
    public function names()
    {
        return ["Fred Bloggs", "Joe Bloggs"];
    }
}
<?php
require "person.php";

class Book
{
    public $price;
    public $authorsNames;

    /**
     * authors function
     *
     * @param integer $price
     *
     * @return void
     */
    public function price(int $price)
    {
        $this->price = $price;
    }

    /**
     * authors function
     *
     * @param array $names
     *
     * @return void
     */
    public function authors(Person $person)
    {
        $this->authorsNames = $person->names();
    }
}

$book = new Book;
$book->price(20);
echo $book->price . "\n"; // 20

// $book->price("abc");
// Fatal error: Uncaught TypeError: Argument 1 passed to Book::price() must be
// of the type int, string given, ..
// TypeError: Argument 1 passed to Book::price() must be of the type int,
// string given, ..

// echo $book->price . "\n"; // without type hinting "abc"

// $book->authors(20); // with type hinting:

// Fatal error: Uncaught TypeError: Argument 1 passed to Book::authors()
// must be of the type array, int given, called in

// TypeError: Argument 1 passed to Book::authors() must be of the type array,
// int given, called in

$authorsName = new Person;

$book->authors($authorsName);

var_dump($book->authorsNames);
/*
array(2) {
[0] =>
string(11) "Fred Bloggs"
[1] =>
string(10) "Joe Bloggs"
}
/*

OOP PHP | Static Methods and Properties #12

by adding static keyword before a function that function can be accessed without the class being instantiated.

Normally the class is instantiated $user = new User;

Then the method can be accessed echo $user->getName(); // Fred

By using the static keyword the method can be accessed without being instantiated:

<?php

class User
{
    public $name;

    public static function getName()
    {
        return "Fred";
    }
}

// Normally the class is instantiated
// $user = new User;

// then the method can be accessed
// echo $user->getName(); // Fred

// By using the static keyword the method can be accessed without
// being instantiated:
echo User::getName(); // Fred
<?php

class User
{
    public static $name = "Fred Bloggs";

    public function updateName()
    {
        return $this->name = "Joe Bloggs";
    }
}
// note the '$' is required!!
echo User::$name; // Fred Bloggs

If the static keyword is removed a fatal error is thrown.

Fatal error: Uncaught Error: Access to undeclared static property: User::$name in ...

Error: Access to undeclared static property: User::$name in ...

To access the property and method they both need to be declared as static

<?php

class User
{
    public static $name = "Fred Bloggs";

    public static function updateName()
    {
        return self::$name = "Joe Bloggs";
    }
}

User::updateName();
echo User::$name; // Joe Bloggs

Static is considered bad practice as it can be accessed anywhere within the program and changed, it is normally used as utility purpose or as counters.

<?php

class User
{
    public static $name = "Fred Bloggs";
    public static $counter = 0;
    public static function updateName()
    {
        return self::$name = "Joe Bloggs";
    }
    public static function increaseCounter()
    {
        self::$counter++;
    }
}

User::increaseCounter();
echo User::$counter . "\n"; // 1
User::increaseCounter();
echo User::$counter . "\n"; // 2
User::increaseCounter();
echo User::$counter . "\n"; // 3
User::updateName();
echo User::$name; // Joe Bloggs

OOP PHP | Constant and Their Uses #13

const is used in initiate a constant, such as PI (alternatively use the built in function pi())

const can be accessed using self::, however it can not be changed.

<?php
class Circle
{
    const PI = 3.14159;
    public function area($radius)
    {
        return $radius * $radius * self::PI;
    }
}
$circle = new Circle;
echo $circle->area(5) . "\n"; // 78.53975

echo $circle::PI . "\n"; // 3.14159

$circle->PI = 3.141; // this is a different property!!

echo $circle::PI . "\n"; // 3.14159

echo $circle->PI; // 3.141

OOP PHP | Overriding Methods #14

<?php
class Book
{
    public $authorsName = "Fred";
    public function author()
    {
        return "The authors name is: " . $this->authorsName . "\n";
    }
}
class NewBook extends Book
{
    public function author()
    {
        return parent::author() . "The authors names is: Joe" . "\n";
    }
}

$book = new NewBook;
echo $book->author();
// The authors name is: Fred
// The authors names is: Joe

the parent class is used and extended, or it can be just overwritten.

OOP PHP | Early binding and Late Binding #15

Due to Early bindings, with statically defined properties, which are bound at compile time, therefore they can throw unexpected results.

<?php
class Book
{
    public static $authorsNames = "Fred Bloggs";
    public static function author()
    {
        return "The authors names are: " . self::$authorsNames . "\n";
    }
    public static function getAuthor()
    {
        echo self::author();
    }
}
class newBook extends Book
{
    public static function author()
    {
        return "The authors names are: " . self::$authorsNames . " and Joe Bloggs" . "\n";
    }
}

$book = new Book;
echo $book->getAuthor(); // The authors names are:Fred Bloggs

$newBook = new newBook;
echo $newBook->getAuthor(); // The authors names are:Fred Bloggs
// Expected: The authors names are:Fred Bloggs and Joe Bloggs

OOP PHP | Late Static Binding #16

The static:: is used to fix the above problem.

<?php
class Book
{
    public static $authorsNames = "Fred Bloggs";
    public static function author()
    {
        return "The authors names are: " . self::$authorsNames . "\n";
    }
    public static function getAuthor()
    {
        echo static::author();
    }
}
class NewBook extends Book
{
    public static function author()
    {
        return "The authors names are: " . self::$authorsNames . " and Joe Bloggs" . "\n";
    }
}

$book = new Book;
echo $book->getAuthor(); // The authors names are:Fred Bloggs

$newBook = new NewBook;
echo $newBook->getAuthor(); // The authors names are: Fred Bloggs and Joe Bloggs
// Expected: The authors names are:Fred Bloggs and Joe Bloggs
NewBook::getAuthor(); // The authors names are: Fred Bloggs and Joe Bloggs

OOP PHP | Final Method and Final class #17

When final is used in a method it can not be overwritten.

<?php
class Book
{
    public static $authorsNames = "Fred Bloggs";
    final public static function author()
    {
        return "The authors names are: " . self::$authorsNames . "\n";
    }
}
class NewBook extends Book
{
    public static function author()
    // Fatal error: Cannot override final method Book::author() in ...
    {
        return "The authors names are: " . self::$authorsNames . " and Joe Bloggs" . "\n";
    }
}

When final is used in a class it can not be overwritten either.

<?php
final class Book
{
    public static $authorsNames = "Fred Bloggs";
    public static function author()
    {
        return "The authors names are: " . self::$authorsNames . "\n";
    }
    public static function getAuthor()
    {
        echo static::author();
    }
}
// Fatal error: Class NewBook may not inherit from final class (Book) in
class NewBook extends Book
{
    public static function author()
    // Fatal error: Cannot override final method Book::author() in ...
    {
        return "The authors names are: " . self::$authorsNames . " and Joe Bloggs" . "\n";
    }
}

OOP PHP | Autoload Class #18

To auto load the class with the same file name as the class the autoloader can be used:

autoload.php

<?php

spl_autoload_register(
    function ($class) {
        $filename = strtolower($class . ".php");
        include_once $filename;
    });

It can be called from the script:

include "autoload.php";

Any classes that are implemented will automatically be loaded.

OOP PHP | Namespaces in PHP #19

Working with big project there is a possibility to have the same class name, especially when working with library packages.

Creating huge file name of the class may work but isn't realistic.

Namespace was introduced in PHP 5.3.

Namespaces are a virtual

fns.php is in the global name space:

<?php

class A
{
    public function __construct()
    {
        echo "I am at Global name space\n";
    }
}

sns.php is in the second name space

<?php
namespace second;

class A
{
    public function __construct()
    {
        echo "I am at second name space\n";
    }
}

If two class with the same name are loaded a fatal error will occur. (namespace second commented out) Fatal error: Cannot declare class A, because the name is already in use in ...

index.php is in the second name space, the class A in the global space can be instantiated with a backslash (\A), the class in the same namespace can be instantiated as normal.

<?php
namespace second;

include "fns.php";
include "sns.php";

$a = new \A; // fully qualified class name FQCN
// I am at Global name space

$sns = new A; // unqualified class name
// I am at second name space

Alternatively instead of having the index.php in the second namespace the use .. as .. keywords can be used to differentiate the same class names with an alias.

<?php
include "fns.php";
include "sns.php";

use second\A as NewA;

$a = new A; // fully qualified class name FQCN
// I am at Global name space

$sns = new NewA; // unqualified class name
// I am at second name space

OOP PHP | What is Traits and Why we need it #20

Traits are smiler class but it is only for grouping methods in a fine-grained and consistent way. It is not allowed to instantiate a trait on its own.

<?php

/**
 * Projector
 */
trait Projector
{
    public function range()
    {
        echo "Projector range: 2m\n";
    }
}
<?php

class Mobile
{
    public function battery()
    {
        echo "I'm a battery\n";
    }
}

Multiple traits can be used in the same class (PHP does not allow extending multiple class) by the use keyword for a trait.

<?php
include_once "mobile.php";
include_once "laser.php";
include_once "projector.php";

class Galaxy extends Mobile
{
    use Laser, projector;
    public function getGalaxy()
    {
        echo "I'm a galaxy";
    }
}

$phone = new Galaxy;

$phone->battery(); // I'm a battery

// $obj1 = new Laser;
// Fatal error: Uncaught Error: Cannot instantiate trait Laser
$phone->power(); // 10mW
$phone->range(); // Projector range: 2m

OOP PHP | Multiple Traits #21

If the projector has a power method, it will clash with the power method already existing in the laser trait.

<?php

/**
 * Projector
 */
trait Projector
{
    public function range()
    {
        echo "Projector range: 2m\n";
    }
    public function power()
    {
        echo "I am the Projector power\n";
    }
}

To set the default power method to the Laser power, but alias the Projector power method as follows:

<?php
include_once "mobile.php";
include_once "laser.php";
include_once "projector.php";

class Galaxy extends Mobile
{
    use Laser, projector {
        Laser::power insteadof Projector;
        Projector::power as projectorPower;
    }
    function getGalaxy()
    {
        echo "I'm a galaxy";
    }
}

$phone = new Galaxy;

$phone->battery(); // I'm a battery

// $obj1 = new Laser;
// Fatal error: Uncaught Error: Cannot instantiate trait Laser
$phone->power(); // 10mW
$phone->range(); // Projector range: 2m
$phone->projectorPower(); // I am the Projector power

Another way is to use the Projector trait inside the laser trait:

<?php
include_once "projector.php";

/**
 * Projector
 */
trait Projector
{
    use Projector;
    public function range()
    {
        echo "Projector range: 2m\n";
    }
    public function power()
    {
        echo "I am the Projector power\n";
    }
}

The Laser class will use the power method.

Order of inheritance:

  1. The current Galaxy class
  2. The trait use(ed) in the Galaxy class
  3. The trait use(ed) in the Laser class

OOP PHP | Traits: Abstract Functions and Properties #22

If an abstract function is defined in a trait it must be implemented in the class that use(es) it, otherwise a fatal error will be thrown:

Fatal error: Class Galaxy contains 1 abstract method and must therefore be declared abstract or implement the remaining methods (Galaxy::abc)

laser.php now includes the Projector trait and has the abc abstract method.

<?php
include_once "projector.php";

trait Laser
{
    use Projector;
    public function power()
    {
        echo "10 mW\n";
    }
    abstract public function abc();
}

The Laser trait is used in the Galaxy class, so will need to implement the abc method.

<?php
include_once "mobile.php";
include_once "laser.php";

class Galaxy extends Mobile
{
    use Laser;
    function getGalaxy()
    {
        echo "I'm a galaxy";
    }
    function abc()
    {}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment