Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extending Slim-Http #95

Closed
adriansuter opened this issue Jun 5, 2019 · 3 comments
Closed

Extending Slim-Http #95

adriansuter opened this issue Jun 5, 2019 · 3 comments

Comments

@adriansuter
Copy link
Contributor

Hi there

I tried to develop an extension to the Slim-Http decorator. Unfortunately some useful properties are private. For my example, I had to change the following ones to be protected:

  • \Slim\Http\Response::$response
  • \Slim\Http\Response::$streamFactory
  • \Slim\Http\Factory\DecoratedResponseFactory::$responseFactory
  • \Slim\Http\Factory\DecoratedResponseFactory::$streamFactory

Once changed, I could write an extending class of \Slim\Http\Response. This new class \Slim\ExtendedHttp\Response would contain all methods of the Slim-Http library and defines additional ones (well one at the moment for proof-of-concept purposes):

declare(strict_types=1);

namespace Slim\ExtendedHttp;

use DOMDocument;
use Psr\Http\Message\ResponseInterface;

class Response extends \Slim\Http\Response
{
    /**
     * Note: This method is not part of the PSR-7 standard.
     *
     * @param DOMDocument $document
     * @param int         $status The HTTP status code.
     *
     * @return Response
     */
    public function withXml(DOMDocument $document, int $status = null): ResponseInterface
    {
        $response = $this->response
            ->withHeader('Content-Type', 'application/xml;charset=utf-8')
            ->withBody($this->streamFactory->createStream(
                $document->C14N()
            ));

        if ($status !== null) {
            $response = $response->withStatus($status);
        }

        return $response;
    }
}

In order to use that decorator, I needed to extend \Slim\Http\Factory\DecoratedResponseFactory too. So \Slim\ExtendedHttp\Factory\DecoratedResponseFactory would actually be the same as the Slim-Http one, but returns the extended response (defined above):

declare(strict_types=1);

namespace Slim\ExtendedHttp\Factory;

use Psr\Http\Message\ResponseInterface;
use Slim\ExtendedHttp\Response;

class DecoratedResponseFactory extends \Slim\Http\Factory\DecoratedResponseFactory
{
    /**
     * @inheritDoc
     */
    public function createResponse(int $code = 200, string $reasonPhrase = ''): ResponseInterface
    {
        $response = $this->responseFactory->createResponse($code, $reasonPhrase);

        return new Response($response, $this->streamFactory);
    }
}

Eventually my index.php-file became (for simplicity I declared the SlimExtendedHttpPsr17Factory class right here):

declare(strict_types=1);

use Nyholm\Psr7\Factory\Psr17Factory;
use Slim\ExtendedHttp\Response;
use Slim\Factory\AppFactory;
use Slim\Factory\Psr17\SlimHttpPsr17Factory;
use Slim\Http\ServerRequest;

require __DIR__.'/../vendor/autoload.php';

class SlimExtendedHttpPsr17Factory extends SlimHttpPsr17Factory
{
    protected static $responseFactoryClass = '\Slim\ExtendedHttp\Factory\DecoratedResponseFactory';
}

$psr17Factory = new Psr17Factory();
$app = AppFactory::create(
    SlimExtendedHttpPsr17Factory::createDecoratedResponseFactory(
        $psr17Factory, $psr17Factory
    )
);

$app->get('/', function (ServerRequest $request, Response $response, array $args) {
    $doc = new DOMDocument();
    $element = $doc->createElement('root');
    $element->nodeValue = 'Hello World';
    $doc->appendChild($element);

    return $response->withXml($doc);
});

$app->run();

Should we change the properties mentioned at the top to be protected instead of private?

Should we add the possibility to change the value of \Slim\Factory\Psr17\SlimHttpPsr17Factory::$responseFactoryClass? That way we would not have to create a new class just to change this string.

@l0gicgate
Copy link
Member

I'm fine with changing them to protected. I want to make all the software we produce as extensible as possible.

@adriansuter
Copy link
Contributor Author

What about a static method setResponseFactory(string $responseFactoryClass) in \Slim\Factory\Psr17\SlimHttpPsr17Factory?

@l0gicgate
Copy link
Member

Yea I think that's fine. Only on that particular factory though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants