One of the primary reasons developers use OOP is because of its ability to re-use existing code, yet, at the same time, add or override functionality. In PHP, the keyword extends is used to establish a parent/child relationship between classes.
child class, use the keyword extends to set up inheritance. In the example that follows, the Customer class extends the Base class. Any instance of Customer will inherit visible methods and properties, in this case, $id, getId() and setId():class Base
{
protected $id;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
}
class Customer extends Base
{
protected $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}abstract. In this example, the Base class defines as abstract the validate() method. The reason why it must be abstract is because it would be impossible to determine exactly how a child class would be validated from the perspective of the parent Base class:abstract class Base
{
protected $id;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
public function validate();
}Member, which inherits from Customer. Customer, in turn, inherits from Base:class Base
{
protected $id;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
}
class Customer extends Base
{
protected $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
}
class Member extends Customer
{
protected $membership;
public function getMembership()
{
return $this->membership;
}
public function setMembership($memberId)
{
$this->membership = $memberId;
}
}test() function, shown in the following code snippet, requires an instance of the Base class as an argument. Any class within the line of inheritance can be accepted as an argument. Anything else passed to test() throws a TypeError:function test(Base $object)
{
return $object->getId();
}In the first bullet point, a Base class and a Customer class were defined. For the sake of demonstration, place these two class definitions in a single file, chap_04_oop_extends.php, and add the following code:
$customer = new Customer();
$customer->setId(100);
$customer->setName('Fred');
var_dump($customer);Note that the $id property and the getId() and setId() methods are inherited from the parent Base class into the child Customer class:

To illustrate the use of an abstract method, imagine that you wish to add some sort of validation capability to any class that extends Base. The problem is that there is no way to know what might be validated in the inherited classes. The only thing that is certain is that you must have a validation capability.
Take the same Base class mentioned in the preceding explanation and add a new method, validate(). Label the method as abstract, and do not define any code. Notice what happens when the child Customer class extends Base.

If you then label the Base class as abstract, but fail to define a validate() method in the child class, the same error will be generated. Finally, go ahead and implement the validate() method in a child Customer class:
class Customer extends Base
{
protected $name;
public function getName()
{
return $this->name;
}
public function setName($name)
{
$this->name = $name;
}
public function validate()
{
$valid = 0;
$count = count(get_object_vars($this));
if (!empty($this->id) &&is_int($this->id)) $valid++;
if (!empty($this->name)
&&preg_match('/[a-z0-9 ]/i', $this->name)) $valid++;
return ($valid == $count);
}
}You can then add the following procedural code to test the results:
$customer = new Customer();
$customer->setId(100);
$customer->setName('Fred');
echo "Customer [id]: {$customer->getName()}" .
. "[{$customer->getId()}]\n";
echo ($customer->validate()) ? 'VALID' : 'NOT VALID';
$customer->setId('XXX');
$customer->setName('$%£&*()');
echo "Customer [id]: {$customer->getName()}"
. "[{$customer->getId()}]\n";
echo ($customer->validate()) ? 'VALID' : 'NOT VALID';
To show a single line of inheritance, add a new Member class to the first example of Base and Customer shown in the preceding step 1:
class Member extends Customer
{
protected $membership;
public function getMembership()
{
return $this->membership;
}
public function setMembership($memberId)
{
$this->membership = $memberId;
}
}Create an instance of Member, and notice, in the following code, that all properties and methods are available from every inherited class, even if not directly inherited:
$member = new Member();
$member->setId(100);
$member->setName('Fred');
$member->setMembership('A299F322');
var_dump($member);Here is the output:

Now define a function, test(), which takes an instance of Base as an argument:
function test(Base $object)
{
return $object->getId();
}Notice that instances of Base, Customer, and Member are all acceptable as arguments:
$base = new Base(); $base->setId(100); $customer = new Customer(); $customer->setId(101); $member = new Member(); $member->setId(102); // all 3 classes work in test() echo test($base) . PHP_EOL; echo test($customer) . PHP_EOL; echo test($member) . PHP_EOL;
Here is the output:

However, if you try to run test() with an object instance that is not in the line of inheritance, a TypeError is thrown:
class Orphan
{
protected $id;
public function getId()
{
return $this->id;
}
public function setId($id)
{
$this->id = $id;
}
}
try {
$orphan = new Orphan();
$orphan->setId(103);
echo test($orphan) . PHP_EOL;
} catch (TypeError $e) {
echo 'Does not work!' . PHP_EOL;
echo $e->getMessage();
}We can observe this in the following image:
