PHP 新特性 Trait 在 Laravel 中的应用


Trait 是什么?

Trait 是为类似 PHP 的单继承语言而准备的一种代码复用机制。Trait 为了减少单继承语言的限制,使开发人员能够自由地在不同层次结构内独立的类中复用 method。Trait 和 Class 组合的语义定义了一种减少复杂性的方式,避免传统多继承和 Mixin 类相关典型问题。

Trait 和 Class 相似,但仅仅旨在用细粒度和一致的方式来组合功能。 无法通过 trait 自身来实例化。它为传统继承增加了水平特性的组合;也就是说,应用的几个 Class 之间不需要继承。

简单来说trait就是解决php不能实现多继承的。

具体的案例

如我们定义类的时候,很多都要做成单例模式,因此我们只需要定一个trait在需要单例的时候use trait就可以了。下面看下代码


trait Singleton {
    protected static $_instance;

    final public static function getInstance() {
        if(!isset(self::$_instance)) {
            self::$_instance = new static();
        }

        return self::$_instance;
    }

    private function __construct() {
        $this->init();
    }

    protected function init() {}

}

class Db {
    use Singleton;
    protected function init() {

    }
}

Trait在Laravel中的应用

laravel中大量的使用到了trait,下面我来拿比较那用的的Laravel Auth来看,首先执行

php artisan make:auth

然后到app/Http/Controllers/Auth/ 目录下找到LoginController,你会发现LoginController中的代码比较少,只定义了一个use AuthenticatesUsers; 处理数据,登录之类的核心功能都不在这个控制器中。我们然后打开这个AuthenticatesUsers,你会发现所有有关login的功能都在这个文件里面。

那有同学就会感到疑问了,为什么不直接写到LoginController呢?下面我来给大家说下

AuthenticatesUsers 这个里面实现了根login的业务逻辑,但是呢?所有的可配置的参数,可重写改的方法你都可以在LoginController中就实现重写,这样代码不久简洁了嘛。我们随意找一个举例,我们重写login的验证加入极验验证。


namespace App\Http\Controllers\Auth;

use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use Illuminate\Validation\ValidationException;
use Illuminate\Foundation\Auth\AuthenticatesUsers;

class LoginController extends Controller
{

    use AuthenticatesUsers;

    protected function redirectTo()
    {
        return '/';
    }

    protected $gee;

    public function __construct(GeeCaptchaController $gee)
    {
        $this->gee = $gee;
        $this->middleware('guest')->except('logout');
    }

    /**
     * 重写login验证逻辑,增加极验验证
     *
     * @param  \Illuminate\Http\Request  $request
     * @return void
     */
    protected function validateLogin(Request $request)
    {
        $this->validate($request, [
            $this->username() => 'required|string',
            'password' => 'required|string',
        ]);

        if (!$this->gee->verify()) {
            throw ValidationException::withMessages([
                'captcha' => '无效的验证码失效!',
            ]);
        }

    }
}

示例代码下载链接


Vote Vote Cancel Collect Collect Cancel

<< 上一篇: Eloquent ORM 中的 find 方法的实现流程

>> 下一篇: 为什么 Laravel 没有规划 models 目录?