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:
- A typical Laravel Model extends
Model
. What's thatAuthenticatable
here? - 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 errorclass 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?
- app/Models/User extends Illuminate/Auth/User
- 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:
- You create your own
TaskRequest
class with some common rules - Then you create separate classes,
StoreTaskRequest
andUpdateTaskRequest
, that both extend the sameTaskRequest
but override/change some of its behavior in their own way.
No comments or questions yet...