如何在PHP中覆盖特征?

时间:2017-05-02 15:21:30

标签: php inheritance traits

我有2个特质

TraitRunner.php

use Traits\Create;

class TraitRunner {
    ...
}

Controller.php这样

use TraitRunner;

class Controller {
    public function __construct()
        ...
        $this->something = app()->make(TraitRunner()::class);
        ...
    }
}

FooController.php

use Controller;

class FooController extends Controller {
    ...
}

我需要覆盖特征方法。我可以创建一个新的特性并编辑TraitRunner.php,添加:

use Create, MyCreate {
    MyCreate::fooMethod insteadof Create;
}

特征方法的实际使用在代码中更深处,因此我将其简化为清晰。

问题是我无法更改 TraitRunner.php Controller.php 文件,因为它们位于供应商目录中。如果我只能编辑 FooController.php ,请建议我添加的内容和位置。

3 个答案:

答案 0 :(得分:1)

其他特征是否覆盖了特征? 是!不,如果做错了; - )

trait t1 {
     function abc(){
        print __METHOD__.'<br>';
    }
}
class a {
    use t1;
}
trait t2 {
    function abc(){
        print __METHOD__.'<br>';
        //parent::abc();  //will call t1:abc() again, if exists and is called
    }
}
class b extends a {
    use t2;
}
//works
(new a)->abc();//prints t1::abc<br>
//works
(new b)->abc();//prints t2::abc<br>


//But this wont work. (Did not realay know why)
class c {
   use t1,t2;
}
//So this fails  (both traits are used in the same class definition)
(new c)->abc();
//Fatal error:  Trait method abc has not been applied, because there are collisions

特征可以实现其他特征。

trait t1 {
    function x(){}
}
trait t2 {
    use t1;
    function x(){}
}

度过愉快的一天

答案 1 :(得分:0)

您不需要创建差异特征来覆盖特征中的方法。

来自PHP Doc:

  

优先顺序是当前类的成员覆盖   特征方法,反过来覆盖继承的方法。

所以,例如,这段代码:

trait TraitRunner {
    public function sayHello() {
        echo 'TraitRunner method';
    }
}

class Controller {
    use TraitRunner;
}

class FooController extends Controller {
    public function sayHello() {
        echo 'FooController method ';
    }
}

$o = new FooController();
$o->sayHello();

会给:

FooController method

答案 2 :(得分:0)

通过实验,我发现了这种方法:

1.-使用覆盖方法fooMethod

创建一个新的特征MyCreate

2.-编辑FooController.php:

use vendor\Traits\Create
use app\Traits\MyCreate

class TraitRunner extends vendor\TraitRunner {
    use Create, MyCreate {
        MyCreate::fooMethod insteadof Create;
    }
}

class Controller extends vendor\Controller {
    // the following code is the place where TraitRunner is used, so we have to put it here
    public function __construct()
        ...
        $this->something = app()->make(TraitRunner()::class);
        ...
    }
}

class FooController extends Controller { ...

如果有更充分的方式,欢迎您提出建议。虽然这种方式很有效。