Development

Work around “unsafe usage of new static()”

During a recent update of some of my library dependencies I found that one of my dependencies had marked their constructors as final. When I asked if it was possible to de-finalize them, they told me to remove it and run static analysis. It turns out that the answer lies in phpstan’s rule for Unsafe usage of new static(). I’m sure the intent behind this rule was/is to help developers from shooting themselves in the foot, but I’m one of those developers that wants to be able to extend classes if needed. When something blows up, it’s the developers fault, as there should have been form of testing done anyway.

In my case I had extended the Slim\Http\Response class to allow the StreamFactoryInterface to be null on the constructor. When it is null it was being initialized it using the middlewares/utils Factory. This made it easy to extend for my usages where I didn’t need the stream, as I was wrapping a response any way.

class CustomResponse
	extends \Slim\Http\Response
{
	public function __construct(
		ResponseInterface $response, 
		?StreamFactoryInterface $streamFactory = null
	) {
		$this->response      = $response;
		$this->streamFactory = $streamFactory ?? Factory::getStreamFactory();
	}
}

For those times when you can’t convince a library author to remove final from a class. The not-so-good-but-best-option when extending the class is to create a static method, call the constructor, and then finish your initialization.

class CustomResponse
	extends \Slim\Http\Response
{
	public static function create(ResponseInterface $response)
	{
		return new self($response, Factory::getStreamFactory());
	}}

This works just as well as extending the constructor, and the code coupling is not really any different.

Leave a reply