How to implement a custom response factory?

I want to create my own response factory class but I am confused about the right way to do it. Should I implement the ResponseFactoryInterface? I just want to return my response as formatted json data since my app is an api.

ResponseFactoryInterface::class => function (ContainerInterface $container) {
 // should I add my factory class here in the container?
},

You may need the ResponseFactory DI container definition if you have a custom class that declares this Interface as dependeny within the constructor.

To return a custom (Json) response, you have multiple options.

  • Manually Json encoding
  • Using the DecoratedResponseFactory of the slim/http package.
  • Using a custom Response class class for each response type, e.g. JsonResponse, HtmlResponse
    extends from a generic Response class. For example, the laminas/laminas-diactoros PSR-7 package contains such Response classes. This concept works not so well in combiniation with the existing $response object that you get from Slim.
  • Creating a custom “ResponseRenderer” class that takes your $response object and a data array and returns a Response object with the encoded body content and the required HTTP response headers.

@odan thank you so much for your reply.
I’ve just discovered there is a new setResponseFactory method but I couldn’t make it work actually.

Even I’ve set my own response factory it doesn’t work or give any errors.
I think there is no documentation about it

Here is my container.php

use Slim\App;
use Slim\Factory\AppFactory;
use App\Factory\ResponseFactory;
use Illuminate\Database\Connection;
use App\Handler\DefaultErrorHandler;
use Slim\Middleware\ErrorMiddleware;
use Psr\Container\ContainerInterface;
use Psr\Http\Message\ResponseFactoryInterface;
use Illuminate\Database\Connectors\ConnectionFactory;
use Illuminate\Container\Container as IlluminateContainer;

return [
    'settings' => function () {
        return require __DIR__ . '/settings.php';
    },

    App::class => function (ContainerInterface $container) {
        AppFactory::setContainer($container);
        AppFactory::setResponseFactory(new ResponseFactory());

        return AppFactory::create();
    },

    ResponseFactoryInterface::class => function (ContainerInterface $container) {
        return $container->get(App::class)->getResponseFactory();
    },

    ErrorMiddleware::class => function (ContainerInterface $container) {
        $settings = $container->get('settings')['error'];
        $app = $container->get(App::class);

        $errorMiddleware = new ErrorMiddleware(
            $app->getCallableResolver(),
            $app->getResponseFactory(),
            (bool)$settings['display_error_details'],
            (bool)$settings['log_errors'],
            (bool)$settings['log_error_details']
        );

        $errorMiddleware->setDefaultErrorHandler(DefaultErrorHandler::class);

        return $errorMiddleware;
    },

    Connection::class => function (ContainerInterface $container) {
        $factory = new ConnectionFactory(new IlluminateContainer());

        $connection = $factory->make($container->get('settings')['db']);

        // Disable the query log to prevent memory issues
        $connection->disableQueryLog();

        return $connection;
    },

    PDO::class => function (ContainerInterface $container) {
        return $container->get(Connection::class)->getPdo();
    },
];

Here is my response factory class:

namespace App\Factory;

use Psr\Http\Message\ResponseFactoryInterface;
use Psr\Http\Message\ResponseInterface;
use Slim\Psr7\Response;

class ResponseFactory implements ResponseFactoryInterface
{
    public function createResponse(
        int $code = 200,
        string $reasonPhrase = ''
    ): ResponseInterface {
        $res = new Response($code);

        if ($reasonPhrase !== '') {
            $res = $res->withStatus($code, $reasonPhrase);
        }

        return $res;
    }
}

According to PSR-17 the ResponseFactoryInterface implementation “has the ability to create responses.”
So I’m not sure if the ResponseFactoryInterface is the right “tool” to build a JSON response.

Have you tried to use a JsonRenderer?