《Thinkphp5入门系列课程》第四课:Trait 使用

Thinkphp5视频教程

require

PHP >= 5.4.0

介绍

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

以上来自 php.net 官方给出的介绍,地址为:http://php.net/manual/zh/language.oop5.traits.php

个人理解

Trait 其实是一个细粒度更细的代码复用方式,较之前的类设计逻辑,如果类 A 和 类 B 都存在这个方法,那么我们可以通过继承一个父类来实现代码复用。如果类 A 和 类 B 是父类的衍生子类倒也是没有问题,但是如果类 A 和 类 B 毫无相关的,他们唯一相似的就是有一个共同的 method ,这种情况下,A 和 B 共同继承一个父类就显得过度设计啦。所以,在这这种情况下,Trait 诞生了,它就是解决此类问题的。说的有些抽象,下面来看具体的实例:

  • 传统方法

类 A :

<?php
class A {
  public function eat () {
    echo '我有吃的技能';
  }
  public function ha () {
    //...
  }
}

类 B :

<?php
class B {
  public function eat () {
    echo '我有吃的技能';
  }
  public function hi () {
    //...
  }
}

如果相同的代码出现两次,就要考虑 DRY 啦,所以这里我们可以:

<?php
class P {
  public function eat () {
    echo '我有吃的技能';
  }
}

class A extends P {
  public function ha () {
    //...
  }
}

class B extends P {
  public function hi () {
    //...
  }
}

代码复用问题是解决了,但是如果 A 是美国队长,B 是蚂蚁,虽然他们都可以吃,但是这样继承真的好吗?显然是有点勉强的。

  • Trait 方法

Eat Trait:

<?php
trait Eat {
  public function eat () {
    echo '我有吃的技能';
  }
}
<?php
class A {
  use Eat;
  public function ha () {
    //...
  }
}

class B {
  use Eat;
  public function hi () {
    //...
  }
}

我们将一些公用的方法定义在 Trait 文件中,在需要使用的时候 use traitName 就可以,既解决了代码复用的问题,也避免了勉强的父类继承问题。

定义 Trait

和定义类基本相同,只是将 class 换成了 trait

<?php
trait TraitName {
  public function demo () {
    //...
  }
}

使用 Trait

Trait 的使用也非常简单,通过 use 语句引入就可以啦,如下:

<?php
trait DemoTrait {
  public function demo () {
    echo 'demo';
  }
}

class A {
  use DemoTrait;
  public function printer () {
    echo __METHOD__;
  }
}

$a = new A();
$a->demo();

多个 Trait 使用

use Trait1,Trait2;

Trait 注意点

  • 一、优先级
    Trait 方法 > extends 方法 > 类方法

  • 二、Trait 方法名冲突的解决

如下面的情况:

<?php
trait ta {
  public function demo () {
    echo 'ta';
  }
}

trait tb {
  public function demo () {
    echo 'tb';
  }
}

class A {
  use ta,tb;
}

$a = new A();
$a->demo();

运行会报错:

PHP Fatal error:  Trait method demo has not been applied, because there are collisions with other trait methods on A

Trait 方法名冲突了,解决方法有下:

  • insteadof
class A {
  use ta,tb {
    tb::demo insteadof ta;
  }
}

运行结果:

tb

tb::demo insteadof ta 这句代码的意思就是用 tb 中的 demo 方法替代 ta 中的 demo 方法。

Thinkphp5 Trait 的使用

thinkphp/library/think/Controller.php :

<?php
// +----------------------------------------------------------------------
// | ThinkPHP [ WE CAN DO IT JUST THINK ]
// +----------------------------------------------------------------------
// | Copyright (c) 2006~2017 http://thinkphp.cn All rights reserved.
// +----------------------------------------------------------------------
// | Licensed ( http://www.apache.org/licenses/LICENSE-2.0 )
// +----------------------------------------------------------------------
// | Author: liu21st <liu21st@gmail.com>
// +----------------------------------------------------------------------

namespace think;

\think\Loader::import('controller/Jump', TRAIT_PATH, EXT);

use think\exception\ValidateException;

class Controller
{
    use \traits\controller\Jump;
    //...
}

thinkphp/library/traits/controller/Jump.php :

<?php

/**
 * 用法:
 * load_trait('controller/Jump');
 * class index
 * {
 *     use \traits\controller\Jump;
 *     public function index(){
 *         $this->error();
 *         $this->redirect();
 *     }
 * }
 */
namespace traits\controller;

use think\Config;
use think\exception\HttpResponseException;
use think\Request;
use think\Response;
use think\response\Redirect;
use think\Url;
use think\View as ViewTemplate;

trait Jump
{
    /**
     * 操作成功跳转的快捷方法
     * @access protected
     * @param mixed     $msg 提示信息
     * @param string    $url 跳转的URL地址
     * @param mixed     $data 返回的数据
     * @param integer   $wait 跳转等待时间
     * @param array     $header 发送的Header信息
     * @return void
     */
    protected function success($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
    {
        //... 省略代码
    }

    /**
     * 操作错误跳转的快捷方法
     * @access protected
     * @param mixed     $msg 提示信息
     * @param string    $url 跳转的URL地址
     * @param mixed     $data 返回的数据
     * @param integer   $wait 跳转等待时间
     * @param array     $header 发送的Header信息
     * @return void
     */
    protected function error($msg = '', $url = null, $data = '', $wait = 3, array $header = [])
    {
        //... 省略代码
    }

    // ...
}

从上面可以看到,Thinkphp5 提供的 success()error() 方法都写在这个 Trait 文件中,那么我们就可以不通过继承 think\Controller 来获取这两个方法,直接 use \traits\controller\Jump; 就可以啦。

好了,今天的教程就到这里啦。本着快速学习的目的,本教程不会过多深入。如果想深入学习可以联系作者哦!

这是小滕的《Thinkphp5入门系列课程》第四课:Trait 使用。

喜欢的给个订阅呗!

    原文作者:小滕Tt
    原文地址: https://www.jianshu.com/p/e9feb128bfb3
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞