简体   繁体   中英

PHP 7.1 usage with Traits in Cake PHP 2 application throws collision errors

I'm coding within a Cake PHP 2 application running PHP 7.1, I cannot upgrade the PHP version or Cake version due to business constraints, I'm building out a custom "module" system which has a Traits folder using PHP traits, my controller is calling these Traits and each Trait includes other traits as this means I'm easily able to reuse code.

The issue I have is that up until PHP 7.3, PHP throws a fatal error for "collissions with other trait methods", now I don't recall having any duplicate method names in each trait, is there a way I can quietly turn off this specific PHP error or slightly modify my code so that I don't have to rename every single function/method differently in all of the traits that I have?

My dashboard controller is

<?php

App::uses('AppController', 'Controller');
App::uses('CakeEvent', 'CakeEventManager', 'Event');

// traits
App::uses('Settings', 'modules/QueueManagerModule/Traits');
App::uses('Presenters', 'modules/QueueManagerModule/Traits');
App::uses('Statistics', 'modules/QueueManagerModule/Traits');
App::uses('Jobs', 'modules/QueueManagerModule/Traits');
App::uses('Dates', 'modules/QueueManagerModule/Traits');

class QueueController extends AppController
{
    use Settings, Presenters, Statistics, Jobs, Dates;

    /**
    * View: Queue/dashboard
    */
    public function dashboard()
    {
        // dashboard
    }

}

And one, of 7 traits I have called Jobs :

<?php

App::uses('ClassRegistry', 'Utility');

// Traits
App::uses('Helpers', 'modules/QueueManagerModule/Traits');
App::uses('Settings', 'modules/QueueManagerModule/Traits');

trait Jobs {
    use Helpers, Settings;

    // methods
}

I don't recall having any duplicate method names in each trait

This is not the issue here. The issue is that you're doing this:

trait Jobs {
    use Helpers, Settings;
}

and then this:

class QueueController extends AppController
{
    use Settings, Presenters, Statistics, Jobs, Dates;
}

The fact that the Jobs trait uses the Settings trait, and the QueueController class uses both the Jobs and Settings traits is creating the issue.

More generally, applying a trait that is already using some other trait, and then including that other trait directly as well causes the issue.

Consider this simpler example:

<?php

trait FooTrait {
    function foo()
    {}
}

trait BarTrait {
    function bar()
    {}
}

trait BazTrait {
    use FooTrait, BarTrait;

    function baz()
    {}
}

class Test {
    use FooTrait, BarTrait, BazTrait;

    function doSomething()
    {}
}

$test = new Test;

var_dump(get_class_methods($test));

If you execute it, you will see that the same error is thrown:

Fatal error: Trait method foo has not been applied, because there are collisions with other trait methods on Test in /in/H54W0 on line 20

There is no way to "quietly turn off this specific PHP error", this isn't a warning or notice that you can simply ignore. It's a fatal error that will always show up, and the only way to solve it is by changing your code so that you don't apply the same trait twice to a class (even indirectly , as in your case).

So, four your example, the solution is to remove the Settings trait from the QueueController class, because it's already included in the Jobs trait (and do the same for all the other traits that use traits inside themselves):

<?php

App::uses('AppController', 'Controller');
App::uses('CakeEvent', 'CakeEventManager', 'Event');

// traits
App::uses('Settings', 'modules/QueueManagerModule/Traits');
App::uses('Presenters', 'modules/QueueManagerModule/Traits');
App::uses('Statistics', 'modules/QueueManagerModule/Traits');
App::uses('Jobs', 'modules/QueueManagerModule/Traits');
App::uses('Dates', 'modules/QueueManagerModule/Traits');

class QueueController extends AppController
{
    use Presenters, Statistics, Jobs, Dates;

    /**
    * View: Queue/dashboard
    */
    public function dashboard()
    {
        // dashboard
    }

}
<?php

App::uses('ClassRegistry', 'Utility');

// Traits
App::uses('Helpers', 'modules/QueueManagerModule/Traits');
App::uses('Settings', 'modules/QueueManagerModule/Traits');

trait Jobs {
    use Helpers, Settings;

    // methods
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM