Inheritance lets a child class reuse everything a parent class already has, then add to it or change parts of it.
๐Every car model starts from the same chassis: wheels, engine, brakes. A sports car extends that chassis with a spoiler and a louder exhaust. Nobody re-invents the wheels.
How Laravel hands you superpowers
Free features
Write class Post extends Model and your empty class can already save, find and delete database rows.
Less duplication
Shared code lives once in the parent. Each child only contains what makes it different.
Customise by overriding
Don't like one default? Replace just that method in your child class and keep the rest.
A family tree of classes
Post is a Content. It gets every public and protected member automatically.Build a small class family
-
Extend a parent class
The
extendskeyword makes one class the child (or subclass) of another, the parent (or superclass). The child gets the parent's properties and methods without writing them again.<?php class Content { public function __construct( public string $title, public string $author, ) {} public function summary(): string { return "{$this->title} by {$this->author}"; } } class Page extends Content {} $about = new Page('About us', 'Ada'); echo $about->summary(); // About us by Ada (inherited!)PHP supports single inheritance: a class can extend only one parent. (You'll meet traits and interfaces as alternatives in Abstraction & Interfaces.)
-
Add new members in the child
A child can have extra properties and methods the parent knows nothing about.
class Post extends Content { private bool $published = false; public function publish(): void { $this->published = true; } } $post = new Post('Hello Laravel', 'Ada'); $post->publish(); // only posts can do this echo $post->summary(); // still inherited from Content -
Override a method and call
parent::To override a method, define one with the same name in the child. Use
parent::method()to run the parent's version too. PHP 8.3 adds the#[\Override]attribute, which errors if the parent method doesn't actually exist (great for catching typos).class Post extends Content { #[\Override] // PHP 8.3+; remove on 8.2 public function summary(): string { return '๐ ' . parent::summary(); } } echo (new Post('Hello Laravel', 'Ada'))->summary(); // ๐ Hello Laravel by Ada -
Extend the constructor
If the child needs extra constructor data, write its own constructor and pass the shared parts up with
parent::__construct(). Forget that call and the parent's properties are never set.class Post extends Content { public function __construct( string $title, string $author, public array $tags = [], ) { parent::__construct($title, $author); } } $post = new Post('Hello Laravel', 'Ada', tags: ['php', 'laravel']); -
Share with children using
protectedprivatemembers are invisible even to children. Mark somethingprotectedwhen children should use or customise it, but outside code shouldn't. This is the classic hook pattern: the parent calls a protected method that children override.class Content { public function url(): string { return '/' . $this->prefix() . '/' . strtolower(str_replace(' ', '-', $this->title)); } protected function prefix(): string { return 'pages'; } } class Post extends Content { protected function prefix(): string { return 'blog'; } } echo (new Post('Hello Laravel', 'Ada'))->url(); // /blog/hello-laravel -
Stop inheritance with
finalA
finalclass can't be extended, and afinalmethod can't be overridden. Use it when a class isn't designed for children, so nobody builds on assumptions you never promised.final class Slugger { public function make(string $text): string { /* ... */ } } class FancySlugger extends Slugger {} // Fatal error: cannot extend final class
Avoid this, do that
class Post extends Mailer
{
// Post isn't a kind of Mailer,
// it just wants to send email
}
Extending only to borrow a few methods creates a confusing "is a" relationship.
class PostPublisher
{
public function __construct(private Mailer $mailer) {}
}
If it's a "has a" or "uses a" relationship, pass the object in. This is called composition.
public function __construct(public array $tags)
{
// parent never initialised!
}
Overriding the constructor without calling the parent leaves inherited properties unset.
public function __construct(string $title, string $author, public array $tags)
{
parent::__construct($title, $author);
}
Pass the parent's data up with parent::__construct().
One or two levels of inheritance are easy to follow. Five levels means hunting through five files to understand one method. Prefer composition once a hierarchy starts getting deep.
- Create a
Userclass with promotednameandemail, plus agreeting(): stringmethod. - Create
Admin extends Userthat overridesgreeting()to prepend โ๐ โ usingparent::greeting(). - Give
Adminan extraarray $permissionsconstructor parameter and callparent::__construct(). - Add a
protected function role(): stringhook inUserreturning'member', override it inAdmin, and use it in a publicbadge()method. - Check: does
$admin instanceof Userreturntrue? Why?
- Models:
class Post extends Modelinheritssave(),find(),delete()and hundreds more (see Models). - Overriding protected properties: a model sets
protected $fillableorprotected $tableto customise the parent's defaults. - Users:
class User extends Authenticatablegets login abilities for free (see How Authentication Works). - Tests:
class PostTest extends TestCaseinherits all of Laravel's testing helpers (see Testing Basics).
Key takeaways
extendsmakes a child class inherit the parent's public and protected members.- Children can add new members and override existing methods.
parent::method()runs the parent's version;parent::__construct()sets up inherited data.protectedis for "children may use or customise this".finalblocks extending or overriding; PHP allows only one parent per class.- Use inheritance for real "is a" relationships, composition for "has a".