从父级移除特征 Class

Remove Trait from Parent Class

场景如下

我有一个登录特征...

trait LoginTrait {

     public function login() {

         // some login code here
     }

     public function someOtherFunction() {

         // some elite code here
     }
}

我有一个基本(父)控制器...

class BaseUserController {

    use LoginTrait;
}

我有另一个特点,我正在覆盖登录功能...

trait MyLoginTrait {

     use LoginTrait {
          Traits\LoginTrait::login as oldLogin;
     }

     public function login() {

          // some new elite login code
     }
 }

我有一个扩展 BaseUsersController 的控制器...

class UsersController extends BaseUserController {

     use MyLoginTrait;
}

我的问题是,如何从 BaseUserController 中删除 LoginTrait?

现在,我正在尝试登录,LoginTrait 的登录功能正在启动,而不是具有新登录功能的 MyLoginTrait...

这可能对您有所帮助

<?php

trait LoginTrait
{
    public function login()
    {
        echo 'in LoginTrait::login()' . '<br />';
        // some login code here
    }

    public function someOtherFunction()
    {
        // some elite code here
    }
}

trait MyLoginTrait
{
    public function login()
    {
        echo 'in MyLoginTrait::login()' . '<br />';
        // some new elite login code
    }
}

class BaseUserController
{
    use LoginTrait;
}

class UsersController extends BaseUserController
{
    use LoginTrait, MyLoginTrait {
        MyLoginTrait::login as myLogin;
        LoginTrait::login insteadof MyLoginTrait;
    }
}

$user = new UsersController();
$user->login();// output: in LoginTrait::login()
$user->myLogin();// output: in MyLoginTrait::login()

或使用:

class UsersController extends BaseUserController
{
    use LoginTrait, MyLoginTrait {
        MyLoginTrait::login insteadof LoginTrait;
    }
}

$user = new UsersController();
$user->login(); // output: in MyLoginTrait::login()

很可能您的问题出在其他地方。用其他特征覆盖继承的特征应该是这样的:

<?php

trait A
{
  public function doIt()
  {
    echo "DoIt from A." . PHP_EOL;
  }
}

trait B
{
  public function doIt()
  {
    echo "DoIt from B." . PHP_EOL;
  }
}

class X
{
  use A;
}

class Y extends X
{
  use B;
}

$foo = new Y();
$foo->doIt();

输出(PHP 7.2): DoIt from B.

您甚至可以使用 parent::doIt();B::doIt 来调用相同的特征方法 A - 而不必 "rename" 使用 as 覆盖的方法.

直接回答您的问题:您不能"remove" super class 的特征-您必须使用继承的方法,但可以覆盖它。备选方案:更改您的继承层次结构。