Finglish
Finglish

Reputation: 9976

How to structure route controllers in slim framework 3 (mvc pattern)

I am working on a Slim Framework based API. Following the mvc pattern, I want my routes to be controller driven with logger and renderer injected to every controller.

As a start point I checked out a number of example mvc slim skeletons, and decided to base my structor on one particular tutorial and sample project ( http://jgrundner.com/slim-oo-004-controller-classes/ )

In this setup, injection is done by adding the router controllers to the app container like this:

$container = $app->getContainer();

$container['\App\Controllers\DefaultController'] = function($c){
    return new \App\Controllers\DefaultController(
        $c->get('logger'),
        $c->get('renderer')
    );
};

This then allow for a nice clean route and controller:

route e.g.:

$app->get('/[{name}]', '\App\Controllers\DefaultController:index');

controller e.g.:

namespace App\Controllers;

use Psr\Log\LoggerInterface;
use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;

    class DefaultController{
        private $logger;
        private $renderer;

        public function __construct(LoggerInterface $logger, $renderer){
            $this->logger   = $logger;
            $this->renderer = $renderer;
        }

        public function index(RequestInterface $request, ResponseInterface $response, $args){
            // Log message
            $this->logger->info("Slim-Skeleton '/' route");

            // Render index view
            return $this->renderer->render($response, 'index.phtml', $args);
        }

        public function throwException(RequestInterface $request, ResponseInterface $response, array $args){
            $this->logger->info("Slim-Skeleton '/throw' route");
            throw new \Exception('testing errors 1.2.3..');
        }
    }

Extending the default controller keeps the controllers neat, but requires adding every new controller object to the app container first, which seems inefficient and messy when you have a lot of classes.

Is there a better way?

Upvotes: 2

Views: 6346

Answers (1)

tirta keniten
tirta keniten

Reputation: 427

You can make basecontroller that contain the acontainer.

<?php

namespace App\Controller;

use Slim\Container;

class Controller
{
    var $container;

    public function __construct(Container $container)
    {
        $this->container = $container;
    }

    public function __get($var)
    {
        return $this->container->{$var};
    }
}

and the container:

<?php

$container['App\Controller\Controller'] = function ($c) {
    return new App\Controller\Controller($c);
};

And the controller

<?php

namespace App\Controllers;

use Psr\Http\Message\RequestInterface;
use Psr\Http\Message\ResponseInterface;
use App\Controller\Controller;

class DefaultController extends Controller{

}

Upvotes: 1

Related Questions