There is a PHP library of classes (generated from a WSDL) that cannot be changed. These look like the below for simplicity.
class System extends \SoapClient
{
public function __construct(array $options = array(), $wsdl = 'http://example.com/system?wsdl')
{
// Do configuration and include required classes.
parent::__construct($wsdl, $options);
}
}
class Report extends \SoapClient
{
public function __construct(array $options = array(), $wsdl = 'http://example.com/report?wsdl')
{
// Do configuration and include required classes.
parent::__construct($wsdl, $options);
}
}
Custom code needs to do some configuration (e.g. setting some SOAP headers and the SOAP version) whenever a System or Report object is required. The current implementation is as below.
class mySystem extends System
{
public function __construct($wsdl, $configuration) {
$options = array(
'soap_version' => SOAP_1_2,
);
// Do more stuff here.
parent::__construct($options, $wsdl);
}
}
class myReport extends mySystem
{
public function __construct($wsdl, $configuration) {
parent::__construct($options, $wsdl);
}
}
The above works but my IDE is screaming at me every time I do anything on myReport
(cannot find method etc.) and I think it only works because PHP doesn't care about type very much, and any actual methods are passed to the SoapClient->__doRequest()
method. Any over, more concrete, thoughts on why this is bad are welcome.
I want to refactor this to a better design. The first thing is that mySystem
correctly extends System
but myReport
should also extend Report
. This means that the constructor code needs to be duplicated in mySystem
and myReport
. Is there a way around this?
My thoughts so far:
- Have a "setup" trait that both
mySystem
andmyReport
use and call the appropriate "setup" method in their constructors. The major blocker here is PHP version on some systems is 5.3 although there are plans to upgrade these. - Have a factory method that can instantiate the required classes. Not 100% sure how this would look though.