Skip to main content

Aliases and Multi-Level "extends": User Model

Lesson 02/16 3 min read
Autoplay

Lesson Overview

- Explore multi-level class inheritance
- Understand class naming and namespace conflicts
- Learn about PHP's class extension mechanisms
- Examine inheritance hierarchies in Laravel framework

Now let's look at a specific Eloquent Model called User. It has some extra features on top of the regular Model.

Here's the code of the default Laravel 10 User model:

use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Laravel\Sanctum\HasApiTokens;
 
class User extends Authenticatable
{
use HasApiTokens, HasFactory, Notifiable;
 
// ... properties like $fillable, $hidden, $casts
}

Potential questions to be asked here:

  1. A typical Laravel Model extends Model. What's that Authenticatable here?
  2. What's inside those use XXXXX files? Are those PHP classes?

Classes with Same Names: What to Do?

In addition to the public app/Models/User class, Laravel has its own "core" User class, in the Illuminate/Foundation/Auth namespace.

So, our User Model class should extend that Illuminate User class. And we have a naming conflict!

// That would throw an error
class User extends User
{
// ...
}

That's why we need to assign a different "alias" name to the extended class, on top in the "use" section, using the "as" keyword. Laravel creators called it "Authenticatable":

use Illuminate\Foundation\Auth\User as Authenticatable;
 
class User extends Authenticatable
{
// ...
}

Multi-level "extends"

Let's look at what's inside that User class inside the Laravel framework.

Illuminate/Foundation/Auth/User.php

use Illuminate\Auth\Authenticatable;
use Illuminate\Auth\MustVerifyEmail;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Auth\Access\Authorizable;
 
class User extends Model...
{
use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

You have already seen both syntaxes:

  • extends Model means the "parent" class to inherit properties/classes from it
  • use Authenticatable, Authorizable, ... are all Traits to include behavior from them

But have you noticed the hierarchy of classes here?

  1. app/Models/User extends Illuminate/Auth/User
  2. Illuminate/Auth/User extends Model

So yes, it is important to understand this fundamental OOP principle. You can build a "tree" of such classes, extending each other and expanding the properties/methods of each other.


Another Example of "inheritance": FormRequest

Another example of this hierarchy is Laravel validation with FormRequest classes.

If you run:

php artisan make:request StoreTaskRequest

You will end up with a class something like this:

app/Http/Requests/StoreTaskRequest.php:

use Illuminate\Foundation\Http\FormRequest;
 
class StoreTaskRequest extends FormRequest
{
public function authorize()
{
return false;
}
 
public function rules()
{
return [
//
];
}
}

See that extends FormRequest? If we click it in our IDE and see what's inside, we land on this class in the Laravel framework, from the /vendor folder:

Illuminate/Foundation/Http/FormRequest.php:

namespace Illuminate\Foundation\Http;
 
use Illuminate\Http\Request;
 
class FormRequest extends Request ...
{
use ValidatesWhenResolvedTrait;
 
// ...

Ok, another extends? Let's dive deeper: what's inside of that Request?

Illuminate/Http/Request.php:

use Symfony\Component\HttpFoundation\Request as SymfonyRequest;
 
class Request extends SymfonyRequest
{
use Concerns\CanBePrecognitive,
Concerns\InteractsWithContentTypes,
Concerns\InteractsWithFlashData,
Concerns\InteractsWithInput,
Macroable;
 
// ...

Ok, so this Laravel class actually extends the Symfony class with the same name!

Here, we have a 3-level hierarchy, which may be even deeper if we dive into the underlying Symfony source.

So, you get the idea of hierarchy, so-called "inheritance"?

A practical non-framework example for this could be this:

  1. You create your own TaskRequest class with some common rules
  2. Then you create separate classes, StoreTaskRequest and UpdateTaskRequest, that both extend the same TaskRequest but override/change some of its behavior in their own way.

Comments & Discussion

No comments yet…

We'd Love Your Feedback

Tell us what you like or what we can improve

Feel free to share anything you like or dislike about this page or the platform in general.