PHP Object-Oriented Programming
In object-oriented programming (OOP), an object is a collection of information and descriptions of how to process that information, serving as an abstraction of the real world.
In the real world, everything we deal with is an object, such as computers, televisions, bicycles, etc.
Three main characteristics of an object:
Object behavior: What operations can be performed on the object, such as turning on or off a light.
Object state: How the object responds when certain methods are applied, such as color, size, and shape.
Object identity: The identity of an object is like an ID card, distinguishing it from others with the same behavior and state.
For example, Animal is an abstract class, which can be specifically represented by a dog and a sheep. Both are concrete objects with color attributes and behaviors like writing and running.
Object-Oriented Content
-
Class: Defines the abstract characteristics of a thing. A class includes the data structure and operations on the data.
-
Object: An instance of a class.
-
Member variable: Variables defined within a class. The values of these variables are not visible externally but can be accessed through member functions. Once the class is instantiated into an object, these variables become attributes of the object.
-
Member function: Functions defined within a class, used to access the object's data.
-
Inheritance: Inheritance is a mechanism where a subclass automatically shares the data structure and methods of its parent class. This is a relationship between classes. When defining and implementing a class, it can be based on an existing class, incorporating its defined content and adding new content.
-
Parent class: A class that is inherited by other classes is called a parent class, base class, or superclass.
-
Subclass: A class that inherits from other classes is called a subclass or derived class.
-
Polymorphism: Polymorphism is the ability for the same function or method to operate on multiple types of objects and produce different results. Different objects receiving the same message can produce different results, a phenomenon known as polymorphism.
-
Overloading: Simply put, overloading refers to functions or methods with the same name but different parameter lists. These functions or methods with the same name but different parameters are called overloaded functions or methods.
-
Abstraction: Abstraction involves abstracting objects with consistent data structures (attributes) and behaviors (operations) into classes. A class is such an abstraction, reflecting important properties relevant to the application while ignoring irrelevant details. Any classification of classes is subjective but must be related to specific applications.
-
Encapsulation: Encapsulation involves binding the attributes and behaviors of an entity in the real world together and placing them within a logical unit.
-
Constructor: Primarily used to initialize an object when it is created, assigning initial values to the object's member variables. It is always used with the new operator in object creation statements.
-
Destructor: The destructor is the opposite of the constructor. It is automatically executed by the system when an object ends its lifecycle (e.g., when the function containing the object has finished executing). The destructor is often used for "cleanup" tasks (e.g., releasing memory allocated with new before exiting).
In the diagram below, we create three objects using the Car class: Mercedes, Bmw, and Audi.
$mercedes = new Car();
$bmw = new Car();
$audi = new Car();
PHP Class Definition
The typical syntax for defining a class in PHP is as follows:
<?php
class phpClass {
var $var1;
var $var2 = "constant string";
function myfunc($arg1, $arg2) {
[..]
}
[..]
}
?>
Explanation:
A class is defined using the class keyword followed by the class name.
Variables and methods within the class are defined inside the curly braces ({}).
Class variables are declared using var, and they can also be initialized with values.
Function definitions within the class are similar to regular PHP function definitions but are only accessible through the class and its instantiated objects.
Example
<?php
class Site {
/* Member variables */
var $url;
var $title;
/* Member functions */
function setUrl($par){
$this->url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
?>
The variable $this represents the object itself.
PHP_EOL is the newline character.
Creating Objects in PHP
After defining a class, you can instantiate objects of that class using the new operator:
$tutorialpro = new Site;
We have created three objects in the code above, each of which is independent. Next, let's see how to access member methods and member variables.
Calling Member Methods
After instantiating an object, we can use that object to call its member methods, which can only operate on the object's member variables:
// Call member functions to set the title and URL
$tutorialpro->setTitle("tutorialpro.org");
$taobao->setTitle("淘宝");
$google->setTitle("Google 搜索");
$tutorialpro->setUrl('www.tutorialpro.org');
$taobao->setUrl('www.taobao.com');
$google->setUrl('www.google.com');
// Call member functions to get the title and URL
$tutorialpro->getTitle();
$taobao->getTitle();
$google->getTitle();
$tutorialpro->getUrl();
$taobao->getUrl();
$google->getUrl();
Here is the complete code:
Example
<?php
class Site {
/* Member variables */
var $url;
var $title;
/* Member functions */
function setUrl($par){
$this->url = $par;
}
function getUrl(){
echo $this->url . PHP_EOL;
}
function setTitle($par){
$this->title = $par;
}
function getTitle(){
echo $this->title . PHP_EOL;
}
}
$tutorialpro = new Site;
$taobao = new Site;
$google = new Site;
// Call member functions to set the title and URL
$tutorialpro->setTitle("tutorialpro.org");
$taobao->setTitle("淘宝");
$google->setTitle("Google 搜索");
$tutorialpro->setUrl('www.tutorialpro.org');
$taobao->setUrl('www.taobao.com');
$google->setUrl('www.google.com');
// Call member functions to get the title and URL
$tutorialpro->getTitle();
$taobao->getTitle();
$google->getTitle();
$tutorialpro->getUrl();
$taobao->getUrl();
$google->getUrl();
?>
Executing the above code will produce the following output:
tutorialpro.org
淘宝
Google 搜索
www.tutorialpro.org
www.taobao.com
www.google.com
PHP Constructor
A constructor is a special method primarily used to initialize an object when it is created, setting initial values for the object's member variables. It is used in conjunction with the new
operator in object creation statements.
PHP 5 allows developers to define a method as a constructor within a class. The syntax is as follows:
void __construct ([ mixed $args [, $... ]] )
In the example above, we can initialize the $url and $title variables using the constructor method:
function __construct($par1, $par2) {
$this->url = $par1;
$this->title = $par2;
}
Now we no longer need to call the setTitle and setUrl methods:
Example
$tutorialpro = new Site('www.tutorialpro.org', 'tutorialpro.org');
$taobao = new Site('www.taobao.com', '淘宝');
$google = new Site('www.google.com', 'Google 搜索');
// Call member functions to get the title and URL
$tutorialpro->getTitle();
$taobao->getTitle();
$google->getTitle();
$tutorialpro->getUrl();
$taobao->getUrl();
$google->getUrl();
$google->getUrl();
Destructor
The destructor is the opposite of the constructor. It is automatically executed by the system when the object ends its lifecycle (e.g., when the function where the object resides has finished execution).
PHP 5 introduced the concept of destructors, similar to other object-oriented languages. Its syntax is as follows:
void __destruct ( void )
Example
<?php
class MyDestructableClass {
function __construct() {
print "Constructor\n";
$this->name = "MyDestructableClass";
}
function __destruct() {
print "Destroying " . $this->name . "\n";
}
}
$obj = new MyDestructableClass();
?>
Executing the above code will output:
Constructor
Destroying MyDestructableClass
Inheritance
PHP uses the keyword extends to inherit a class. PHP does not support multiple inheritance. The format is as follows:
class Child extends Parent {
// Code section
}
Example
In this example, the Child_Site class inherits from the Site class and extends its functionality:
<?php
// Child class extending the Site class
class Child_Site extends Site {
var $category;
function setCate($par){
$this->category = $par;
}
function getCate(){
echo $this->category . PHP_EOL;
}
}
Method Overriding
If the inherited method from the parent class does not meet the needs of the child class, it can be rewritten. This process is called method overriding.
In this example, the getUrl and getTitle methods are overridden:
function getUrl() {
echo $this->url . PHP_EOL;
return $this->url;
}
function getTitle(){
echo $this->title . PHP_EOL;
return $this->title;
}
Access Control
PHP controls the access to properties or methods by adding the keywords public (public), protected (protected), or private (private) in front of them.
public (public): Public class members can be accessed from anywhere.
protected (protected): Protected class members can be accessed by the class itself, its child classes, and its parent classes.
private (private): Private class members can only be accessed by the class in which they are defined.
Property Access Control
Class properties must be defined as public, protected, or private. If defined with var, they are considered public.
<?php
/**
* Define MyClass
*/
class MyClass
{
public $public = 'Public';
protected $protected = 'Protected';
private $private = 'Private';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj = new MyClass();
echo $obj->public; // This line will execute normally
echo $obj->protected; // This line will cause a fatal error
echo $obj->private; // This line will also cause a fatal error
$obj->printHello(); // Outputs Public, Protected, and Private
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// Can redefine public and protected, but not private
protected $protected = 'Protected2';
function printHello()
{
echo $this->public;
echo $this->protected;
echo $this->private;
}
}
$obj2 = new MyClass2();
echo $obj2->public; // This line can be executed normally
echo $obj2->private; // Undefined private
echo $obj2->protected; // This line will cause a fatal error
$obj2->printHello(); // Outputs Public, Protected2, and Undefined
?>
Method Access Control
Methods within a class can be defined as public, private, or protected. If these keywords are not set, the method defaults to public.
<?php
/**
* Define MyClass
*/
class MyClass
{
// Declare a public constructor
public function __construct() { }
// Declare a public method
public function MyPublic() { }
// Declare a protected method
protected function MyProtected() { }
// Declare a private method
private function MyPrivate() { }
// This method is public
function Foo()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate();
}
}
$myclass = new MyClass;
$myclass->MyPublic(); // This line can be executed normally
$myclass->MyProtected(); // This line will cause a fatal error
$myclass->MyPrivate(); // This line will cause a fatal error
$myclass->Foo(); // Public, protected, and private methods can all be executed
/**
* Define MyClass2
*/
class MyClass2 extends MyClass
{
// This method is public
function Foo2()
{
$this->MyPublic();
$this->MyProtected();
$this->MyPrivate(); // This line will cause a fatal error
}
}
$myclass2 = new MyClass2;
$myclass2->MyPublic(); // This line can be executed normally
$myclass2->Foo2(); // Public and protected methods can be executed, but private cannot
class Bar
{
public function test() {
$this->testPrivate();
$this->testPublic();
}
public function testPublic() {
echo "Bar::testPublic\n";
}
private function testPrivate() {
echo "Bar::testPrivate\n";
}
}
class Foo extends Bar
{
public function testPublic() {
echo "Foo::testPublic\n";
}
private function testPrivate() {
echo "Foo::testPrivate\n";
}
}
$myFoo = new foo();
$myFoo->test(); // Bar::testPrivate
// Foo::testPublic
?>
Interfaces
Using interfaces, you can specify which methods a class must implement, but you do not need to define the details of these methods.
Interfaces are defined using the interface keyword, similar to defining a standard class, but all methods defined within are empty.
All methods defined in an interface must be public, which is a characteristic of interfaces.
To implement an interface, use the implements operator. A class must implement all methods defined in the interface, otherwise, a fatal error will occur. A class can implement multiple interfaces, separated by commas.
<?php
// Declare an 'iTemplate' interface
interface iTemplate
{
public function setVariable($name, $var);
public function getHtml($template);
}
// Implement the interface
class Template implements iTemplate
{
private $vars = array();
public function setVariable($name, $var)
{
$this->vars[$name] = $var;
}
public function getHtml($template)
{
foreach($this->vars as $name => $value) {
$template = str_replace('{' . $name . '}', $value, $template);
}
return $template;
}
}
Constants
Values that remain constant throughout the class can be defined as constants. No $ symbol is required when defining or using constants.
The value of a constant must be a fixed value and cannot be a variable, class property, result of a mathematical operation, or function call.
Since PHP 5.3.0, a class can be dynamically called using a variable. However, the value of this variable cannot be a keyword (such as self, parent, or static).
Example
<?php
class MyClass
{
const constant = 'constant value';
function showConstant() {
echo self::constant . PHP_EOL;
}
}
echo MyClass::constant . PHP_EOL;
$classname = "MyClass";
echo $classname::constant . PHP_EOL; // Since 5.3.0
$class = new MyClass();
$class->showConstant();
echo $class::constant . PHP_EOL; // Since PHP 5.3.0
?>
Abstract Classes
Any class that contains at least one method declared as abstract must also be declared as abstract.
An abstract class cannot be instantiated.
Abstract methods only declare their calling signature and cannot define their specific functionality.
When inheriting from an abstract class, the subclass must define all the abstract methods from the parent class; additionally, these methods must have the same (or a more relaxed) visibility. For example, if an abstract method is declared as protected, the implementing method in the subclass should be declared as protected or public, but not private.
<?php
abstract class AbstractClass
{
// Forces subclasses to define these methods
abstract protected function getValue();
abstract protected function prefixValue($prefix);
// Regular method
public function printOut() {
print $this->getValue() . PHP_EOL;
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue() {
return "ConcreteClass1";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass1";
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2";
}
public function prefixValue($prefix) {
return "{$prefix}ConcreteClass2";
}
}
$class1 = new ConcreteClass1;
$class1->printOut();
echo $class1->prefixValue('FOO_') . PHP_EOL;
$class2 = new ConcreteClass2;
$class2->printOut();
echo $class2->prefixValue('FOO_') . PHP_EOL;
?>
Executing the above code will output:
ConcreteClass1
FOO_ConcreteClass1
ConcreteClass2
FOO_ConcreteClass2
Additionally, subclass methods can include optional parameters that are not present in the parent class's abstract methods.
For example, if a subclass defines an optional parameter that is not in the parent class's abstract method declaration, it will still function correctly.
<?php
abstract class AbstractClass
{
// Our abstract method only needs to define the required parameters
abstract protected function prefixName($name);
}
class ConcreteClass extends AbstractClass
{
// Our subclass can define optional parameters that are not in the parent class's signature
public function prefixName($name, $separator = ".") {
if ($name == "Pacman") {
$prefix = "Mr";
} elseif ($name == "Pacwoman") {
$prefix = "Mrs";
} else {
$prefix = "";
}
return "{$prefix}{$separator} {$name}";
}
}
$class = new ConcreteClass;
echo $class->prefixName("Pacman"), "\n";
echo $class->prefixName("Pacwoman"), "\n";
?>
Output:
Mr. Pacman
Mrs. Pacwoman
Static Keyword
Declaring class properties or methods as static allows them to be accessed without instantiating the class.
Static properties cannot be accessed through an instantiated object of the class (but static methods can).
Since static methods can be called without an object instance, the pseudo-variable $this is not available within the method declared as static.
Static properties cannot be accessed through the object operator ->.
As of PHP 5.3.0, it is possible to reference the class using a variable. The variable's value cannot be a keyword (e.g., self, parent, or static).
<?php
class Foo {
public static $my_static = 'foo';
public function staticValue() {
return self::$my_static;
}
}
print Foo::$my_static . PHP_EOL;
$foo = new Foo();
print $foo->staticValue() . PHP_EOL;
?>
Output:
foo
foo
Final Keyword
PHP 5 introduced the final keyword. If a method in the parent class is declared as final, it cannot be overridden by the child class. If a class is declared as final, it cannot be extended.
The following code will result in an error:
<?php
class BaseClass {
public function test() {
echo "BaseClass::test() called" . PHP_EOL;
}
final public function moreTesting() {
echo "BaseClass::moreTesting() called" . PHP_EOL;
}
}
class ChildClass extends BaseClass {
public function moreTesting() {
echo "ChildClass::moreTesting() called" . PHP_EOL;
}
}
// Fatal error: Cannot override final method BaseClass::moreTesting()
?>
Calling the Parent Class Constructor
PHP does not automatically call the parent class constructor from the child class's constructor. To execute the parent class constructor, you need to call parent::__construct() within the child class's constructor.
<?php
class BaseClass {
function __construct() {
print "BaseClass class constructor" . PHP_EOL;
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct(); // The child class constructor does not automatically call the parent class constructor
print "SubClass class constructor" . PHP_EOL;
class OtherSubClass extends BaseClass {
// Inherits the constructor method from BaseClass
}
// Calls the constructor method of BaseClass
$obj = new BaseClass();
// Calls the constructor methods of BaseClass and SubClass
$obj = new SubClass();
// Calls the constructor method of BaseClass
$obj = new OtherSubClass();
?>
Executing the above program, the output is:
Constructor method in BaseClass
Constructor method in BaseClass
Constructor method in SubClass
Constructor method in BaseClass