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
}