Ad

Binding Implementations To Request/Response In Laravel?

- 1 answer

The Problem

I'm currently building a small library that will allow me to pass information to a Factory class, which then makes a 'RestfulResponse' instance.

I'm attempting to build this library to be framework agnostic, meaning I can use this in projects other than Laravel.

The RestfulResponse is concerned with handling the Response to the client. I want to use Laravel/Symfony's Response class, however, to keep it framework agnostic, the Response class can't be concrete.

I could use Laravel's IoC Container to import the class, however for that to work the Response class needs to implement an interface, which it does not.

Is there any way, either through Laravel's IoC container, or through some other PHP trickery, I can get this to work? Note: I am using constructor dependency injection, not Facades.


Code examples

This code example works, but is not framework-agnostic.

Essentially, I need to find a way to make it framework agnostic, while still relying on Laravel's Response class.

Laravel's Response Class

namespace Illuminate\Http;

class Response
{}

My Factory Class

namespace App\Restful;

class RestfulResponseFactory
{

    protected $restfulResponse;

    public __constructor(RestfulResponse $restfulResponse)
    {
        $this->restfulResponse = $restfulResponse;
    }

}

The RestfulResponse Class

namespace App\Restful;

use Illuminate\Http\Response;

class RestfulResponse
{

    protected $response;

    public __constructor(Response $response)
    {
        $this->response = $response;
    }

}

Static dependency injection (Laravel's Container handles this)

namespace App\Restful;

use Illuminate\Http\Response;

$factory = new RestfulResponseFactory(
    new RestfulResponse(new Response)
);
Ad

Answer

So I finally have a working implementation of this, and the solution is fairly straight forward. Laravel has built in support for PSR-7 interfaces, which define a standardized way for representing HTTP messages.

This means that you can 'switch on' PSR-7 request/response interfaces by simply requiring two additional packages in composer:

composer require symfony/psr-http-message-bridge
composer require zendframework/zend-diactoros

These packages allow you to use PSR-7 interfaces to generate Requests and Responses. The best part about it is that Laravel has already set up a service provider to bind requests for PSR-7 interfaces with the zend implementation. If you're interested the service provider is class is Illuminate\Routing\RoutingServiceProvider.

To implement a PSR-7 response interface simply include Psr\Http\Message\ResponseInterface as a dependency and let Laravel's container handle the concrete implementation.

The final framework-agnostic result will look something like this:

namespace App\Restful;

use Psr\Http\Message\ResponseInterface;

class RestfulResponse
{

    protected $response;

    public __constructor(ResponseInterface $response)
    {
        $this->response = $response;
    }

}

The main issue I came across while trying to implement PSR-7 responses is that the API is different to Laravel's, which takes a little bit of a learning curve. However, it is very well documented through comments so you can use those to learn the API.

Creating a response requires the first parameter of the constructor to be a Stream, not a string. You can easily create a stream by using fopen:

$stream = fopen('php://memory, 'wb+');
fwrite($stream, 'Hello, world.');

Thanks to Cerad for pointing me in the right direction of using PSR-7 with Symfony Framework's bridge.

Ad
source: stackoverflow.com
Ad