Classes

The basics: class Student

  • Open classes/Student.php
<?php
namespace classes;

class Student
{
    private $name;
    private $gender;

//    public function __construct()
//    {
//    }

    public function getGender()
    {
        return $this->gender;
    }

    public function getName()
    {
        return $this->name;
    }

    public function setGender($gender)
    {
        $this->gender = $gender;
    }

    public function setName($name): void
    {
        $this->name = $name;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
  • We assume you have (basic) knowledge on OOP (object-oriented programming) and concepts like classes, objects, constructors, mutators, ...

NAMING CONVENTIONS

  • The name of a PHP class starts with a capital letter (Student)
  • The name of the class definition file equals the name of the class with the extension .php (Student.php)
  • The class file starts with the statement namespace classes;, used to uniquely identify the class Student. By using namespaces, we can have a class with the same name (Student) in another namespace.
    In our example, the class definition file Student.php is located in the folder classes and, as such, the namespace corresponds to the folder structure. This approach (namespaces that correspond to the folder structure) is - although it's not mandatory in PHP - considered to be best practice.

TIP

If you generate a new PHP class (definition file) by right-clicking a folder in PhpStorm and choose New -> PHP Class, namespacing is automatically taken care of

  • The class Student contains two class variables or properties ($name and $gender)
    • It's common practice to precede the properties of a class with the access modifier private, indicating that these properties are only accessible from within the class that defines it
  • The class Student also contains four class functions or methods, i.e. two "getters" to get/retrieve the value of the properties and two "setters" to set/change the property values
    • These get and set methods are often referred to as mutator methods
    • It's common practice to precede (get and set) methods with the access modifier public, indicating that these methods are also accessible from outside the class
    • Within (these) methods, the $gender and $name properties are addressed as $this->gender and $this->name
      • The keyword $this refers to the calling/current object, i.e., the object to which the method belongs
      • The arrow symbol -> is a PHP construction to access properties (and methods) of a given object
    • When you use auto-completion to implement a setter, the return type : void will be added after the function name. This is a new, but not obliged feature since PHP 7.1. to emphasize that a function should not return any value.
  • The constructor method public function __construct() is called when new objects (or instances) of the Student class are made (with the keyword new, see further on). If its implementation is not included (the code is commented out), it is created automatically.
  • Open course/classes_student.php

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 


<div class="margin-3">
    <?php
    include_once '../classes/Student.php';  // include the class
    use classes\Student; // use the namespace

    $students[0] = new Student();
    $students[0]->setName('John Doe');
    $students[0]->setGender('M');

    $students[1] = new Student();
    $students[1]->setName('Jane Doe');
    $students[1]->setGender('F');

    foreach ($students as $i => $student) {
        echo "<p>Name of student $i = {$student->getName()}</p>\n";
        echo "<p>Gender of student $i = {$student->getGender()}</p>\n";
    }
    ?>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19

Student class example

  • We start the script by including the class definition file (include_once '../classes/Student.php';)
  • The use statement use classes\Student; (a shorthand for use classes\Student as Student;) defines an alias for the class Student, so that we can use the class without having to write its Fully Qualified Name \classes\Student
  • Objects of the class Student are made with the keyword new, followed by the name of the class. The constructor method will be called.
  • The properties of these Student objects are filled in and retrieved using the public mutator (set and get) methods, which are accessed through the arrow operator ->

REMARK

Notice the use of single curly braces ({$student->getName()}) in order to isolate $student->getName() from the surrounding text for interpolation (and get an error-free echo statement)

A second example: class Teacher

  • Open classes/employees/Teacher.php
<?php
namespace classes\employees;

class Teacher
{
    private $name;
    private $gender;

    public function __construct($name, $gender)
    {
        $this->name = $name;
        $this->gender = $gender;
    }

    public function getName()
    {
        return $this->name;
    }

    public function getGender()
    {
        return $this->gender;
    }

    public function setName($name): void
    {
        $this->name = $name;
    }

    public function setGender($gender): void
    {
        $this->gender = $gender;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
  • Open course/classes_teacher.php

 
 
 
 
 
 
 
 
 
 
 
 


<div class="margin-3">
    <?php
    include_once '../classes/employees/Teacher.php';  // include the class
    use classes\employees\Teacher; // use the namespace

    $teachers[0] = new Teacher('Michaël Cloots', 'M');
    $teachers[1] = new Teacher('Jan Janssen', 'M');
    $teachers[2] = new Teacher('Patrick Verhaert', 'M');

    foreach ($teachers as $i => $teacher) {
        echo "<p>Teacher $i = {$teacher->getName()} ({$teacher->getGender()})</p>\n";
    }
    ?>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14

Teacher class example

  • In the previous example, making and initializing a new (Student) object required three statements
$students[0] = new Student();
$students[0]->setName('John Doe');
$students[0]->setGender('M');
1
2
3
  • In this example, we coded this (making and initializing objects) more efficiently by implementing a new constructor with two parameters, which can be called e.g. with the statement $teachers[1] = new Teacher('Jan Janssen', 'M');
public function __construct($name, $gender)
{
    $this->name = $name;
    $this->gender = $gender;
}
1
2
3
4
5
  • Unfortunately, (constructor) overloading is unsupported in PHP, which means that you can't use the statements (and constructors) new Teacher('Jan Janssen','M') and new Teacher() interchangeably. Per class, only one constructor can be defined and used!
  • In this example, we also used a more complex namespace (and corresponding include_once and use statements) with an additional folder level

Method chaining: class Number

  • Open classes/Number.php
<?php
namespace classes;

class Number
{
    private $x;

    public function __construct($x)
    {
        $this->x = $x;
    }

    public function add($y){
        $this->x += $y;
        return $this;       // make method chainable
    }

    public function multiply($y){
        $this->x *= $y;
        return $this;       // make method chainable
    }

    public function printInfo(){
        echo "<p>\$x = $this->x</p>\n";
        return $this;       // make method chainable
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
  • Open course/classes_number.php

 
 
 
 
 
 
 
 
 
 
 
 
 
 


<div class="margin-3">
    <?php
    include_once '../classes/Number.php'; // include the class
    use classes\Number;  // use the namespace

    echo "<blockquote>Execute the statements <code>\$number = new Number(10);</code> and <code>\$number->printInfo();</code></blockquote>\n";
    $number = new Number(10);
    $number->printInfo();

    echo "<blockquote>Execute the statement <code>\$number->add(90)->multiply(3)->printInfo();</code></blockquote>\n";
    $number->add(90)->multiply(3)->printInfo();

    echo "<blockquote>Execute the statement <code>\$number->printInfo()->multiply(0.1)->printInfo()->add(5)->printInfo();</code></blockquote>\n";
    $number->printInfo()->multiply(0.1)->printInfo()->add(5)->printInfo();
    ?>
</div>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

Number class example

  • In the (simple) class Number, we wrote (besides a constructor) three methods (add(), multiply() and printInfo()) that all return $this (the current object). By doing so, we can apply method chaining as in $number->add(90)->multiply(3)->printInfo();.
    • At the end of the execution of $number->add(90), the current (adjusted) object ($number) is returned
    • We call the method multiply(90) on this returned object ($number). The last statement of this method multiply(90) again returns the (adjusted) object ($number).
    • We call the method printInfo() on this returned object ($number)

Static methods/properties: class Drawer

  • Open classes/Drawer.php
<?php
namespace classes;

class Drawer
{
    // default values
    private static $type = 'circle';
    private static $diameter = 100;
    private static $color = 'purple';
    const PI = 3.14;

    public static function circle($diameter = null, $color = null)
    {
        self::$type = 'circle';
        // Default values for circle
        self::$diameter = $diameter ?? 100;
        self::$color = $color ?? 'blue';
        return __CLASS__;      // make static method chainable
    }

    public static function square($diameter = null, $color = null)
    {
        self::$type = 'square';
        // Default values for square
        self::$diameter = $diameter ?? 100;
        self::$color = $color ?? 'green';
        return __CLASS__;      // make static method chainable
    }

    public static function draw()
    {
        $width = self::$diameter;
        $color = self::$color;
        if (self::$type == 'circle') {
            $radius = self::$diameter / 2;
            echo <<<CIRCLE
                <p>
                    <svg height="$width" width="$width">
                      <circle cx="$radius" cy="$radius" r="$radius" fill="$color" />
                    </svg>
                </p>
            CIRCLE;
        } else {
            echo <<<RECT
                <p>
                    <svg height="$width" width="$width">
                      <rect x="0" y="0" width="$width" height="$width" fill="$color" />
                    </svg>
                </p>
            RECT;
        }
        return __CLASS__;      // make static method chainable
    }

    public static function surface()
    {
        if (self::$type == 'circle'){
            $surface = (self::PI * self::$diameter**2) / 4;
        }
        else{
            $surface = self::$diameter**2;
        }
        return $surface;
    }

    public static function printInfo()
    {
        echo "<p><b>" . self::$color . " " . self::$type . "</b> with diameter <b>" . self::$diameter .
            " px</b> and surface <b>" . self::surface(). " px²</b></p>\n";
        return __CLASS__;      // make static method chainable    
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
  • In this last example, we wrote a class Drawer to include colored circles and squares (with additional info) on a web page
  • We don't want to make new objects of this class every time we want to draw something, so we resort to the (somewhat complex) concept of static methods/properties
    • Static properties and methods are accessible without needing an object of the class
      • A property declared as static is shared among all objects of that class
      • A method declared as static can only access static properties
    • Static methods and properties (and class constants) are accessed using the class name, followed by the scope resolution operator ::
  • The static properties $type, $diameter and $color all get a default value
  • We can change these default property values by calling one of the static methods circle() or square(). The parameters of both these methods have a default value (null) when they are omitted.
  • The keyword self is used to refer to the current class. It is never preceded by the dollar sign $ and always followed by the :: operator.
  • The static method draw() draws the shape, while the static method printInfo() prints out some info (color, type, size and surface of the shape). Within the latter method, the static method surface() is called.
  • The method surface() uses the class constant PI, which can be accessed through self::PI

NAMING CONVENTIONS

Names of (class) constants are in uppercase, without a preceding $

  • Notice that the static methods circle(), square(), draw() and printInfo() all end with the statement return __CLASS__;, returning the name of the Drawer class. As such, we can use static method chaining as in Drawer::circle(150, 'lime')::draw()::printInfo();
    • At the end of the execution of Drawer::circle(150, 'lime'), the class name (Drawer) is returned
    • We call the static method draw() on the returned class name (Drawer). The last statement of this method draw() again returns the class name (Drawer).
    • We call the method printInfo() on the returned class name (Drawer)
  • Open course/classes_drawer.php
<?php
include_once '../classes/Drawer.php'; // include the class
use classes\Drawer;  // use the namespace

// Draw some objects
Drawer::draw();
echo "<hr>\n";
Drawer::circle(150, 'lime')::draw()::printInfo();
echo "<hr>\n";
Drawer::square(null, 'gold')::printInfo()::draw();
echo "<hr>\n";
Drawer::square()::draw()::printInfo();
echo "<hr>\n";
Drawer::circle()::draw();
?>
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

Drawer class example

Last Updated: 9/13/2019, 9:23:14 PM