In one sentence

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.

Why it matters

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.

The big picture

A family tree of classes

Content (parent) $title, $author summary(), url() extends Post (child) + $tags, + publish() overrides url() Page (child) + $menuOrder inherits url() as-is
A child "is a" kind of its parent: a Post is a Content. It gets every public and protected member automatically.
Step by step

Build a small class family

  1. Extend a parent class

    The extends keyword 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.)

  2. 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
            
  3. 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
            
  4. 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']);
            
  5. Share with children using protected

    private members are invisible even to children. Mark something protected when 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
            
  6. Stop inheritance with final

    A final class can't be extended, and a final method 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
            
Common mistakes

Avoid this, do that

โŒ Avoid

          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.

โœ… Do

          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.

โŒ Avoid

          public function __construct(public array $tags)
          {
              // parent never initialised!
          }
        

Overriding the constructor without calling the parent leaves inherited properties unset.

โœ… Do

          public function __construct(string $title, string $author, public array $tags)
          {
              parent::__construct($title, $author);
          }
        

Pass the parent's data up with parent::__construct().

๐Ÿ’ก Pro tip: keep trees shallow

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.

๐Ÿ‹๏ธ Try it yourself
  1. Create a User class with promoted name and email, plus a greeting(): string method.
  2. Create Admin extends User that overrides greeting() to prepend โ€œ๐Ÿ‘‘ โ€ using parent::greeting().
  3. Give Admin an extra array $permissions constructor parameter and call parent::__construct().
  4. Add a protected function role(): string hook in User returning 'member', override it in Admin, and use it in a public badge() method.
  5. Check: does $admin instanceof User return true? Why?
โ„น๏ธ Where you'll see this in Laravel
  • Models: class Post extends Model inherits save(), find(), delete() and hundreds more (see Models).
  • Overriding protected properties: a model sets protected $fillable or protected $table to customise the parent's defaults.
  • Users: class User extends Authenticatable gets login abilities for free (see How Authentication Works).
  • Tests: class PostTest extends TestCase inherits all of Laravel's testing helpers (see Testing Basics).
Recap

Key takeaways

Check yourself

Mini quiz