skip to Main Content

As far as I know,
when a class extending another class, It’s should override all abstract methods of parent class and It can also override non-abstract methods
And also when a class implementing an interface, It’s should override all of the parent interface methods
but I’ve seen a Laravel project that didn’t do this

This is the parent interface:

<?php

interface MustVerifyEmail
{
    /**
     * Determine if the user has verified their email address.
     *
     * @return bool
     */
    public function hasVerifiedEmail();

    /**
     * Mark the given user's email as verified.
     *
     * @return bool
     */
    public function markEmailAsVerified();

    /**
     * Send the email verification notification.
     *
     * @return void
     */
    public function sendEmailVerificationNotification();

    /**
     * Get the email address that should be used for verification.
     *
     * @return string
     */
    public function getEmailForVerification();
}

this is the parent class:

<?php

class User extends Model implements
    AuthenticatableContract,
    AuthorizableContract,
    CanResetPasswordContract
{
    use Authenticatable, Authorizable, CanResetPassword, MustVerifyEmail;
}

and this is the child class:

<?php

use IlluminateContractsAuthMustVerifyEmail;
use IlluminateFoundationAuthUser as Authenticatable;

class User extends Authenticatable implements MustVerifyEmail
{
    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];

    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
    ];

    /**
     * The attributes that should be cast.
     *
     * @var array<string, string>
     */
    protected $casts = [
        'email_verified_at' => 'datetime',
        'password' => 'hashed',
    ];

    public function activeCode()
    {
        return //...
    }

    public function hasTwoFactor($key)
    {
        return //...
    }

    public function isTwoFactorAuthEnabled()
    {
        return //...
    }
}

How did this happen?

2

Answers


  1. In Laravel, you can implement interfaces without explicitly declaring all the methods of the interface in your class. Instead, Laravel uses "implicit implementation," where the framework dynamically resolves the implementation based on naming conventions and method signatures.

    Login or Signup to reply.
  2. TLDR: User model inherits the implementation from its parent model, while the later delegated the implementation to trait MustVerifyEmail.


    Hello mahdi_sheykh. These methods were actually explicitly implemented, just not on the class itself but on its traits.

    Traits are a mechanism for code reuse in single inheritance languages such as PHP. A Trait is intended to reduce some limitations of single inheritance by enabling a developer to reuse sets of methods freely in several independent classes living in different class hierarchies. (From PHP’s Traits)

    In this particular case you might be confused by two homonym oop structures: interface MustVerifyEmail vs trait MustVerifyEmail. Your User model states that the interface will be implemented by it, which is true but not strictly because the one actually implementing it is the parent class Authenticatable. But when did it implement it? That is where the use keyword gets into action:

    While implements is for Interfaces, the use is for Traits. Parent User class is "using" the trait MustVerifyEmail, in other words, it is attaching the trait to itself, thus "inheriting" all of its methods.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search