(Using v4)
I’m trying to make an (extremely basic) API project, that will handle looking up some small data from a database using Propel. This part works, a sample table row get works fine.
I’m trying to use Slim Framework to easily (heh) handle some GET and POST requests to CRUD data into the database, and eventually authenticate said requests to secure it.
So far, I’ve tried to set up a simple route group for my first controller (I think I’m doing it wrong, but the docs are incredibly sparse for this topic) like so:
<?php
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
use Slim\Exception\HttpNotFoundException;
use Slim\Factory\AppFactory;
use Slim\Routing\RouteContext;
require __DIR__ . '/vendor/autoload.php';
$app = AppFactory::create();
$app->addRoutingMiddleware();
$errorMiddleware = $app->addErrorMiddleware(true, true, true);
//Routes
$app->group('/scansession', function (Slim\Routing\RouteCollectorProxy $group) {
$group->get('/{id:[0-9]+}', function ($request, $response, $args) {
// Get specific scan session identified by $args['id']
$response->getBody()->write("Showing specific scan " . $args['id']);
return $response;
});
$group->get('', function ($request, $response, $args) {
// Get list of scan sessions
$response->getBody()->write("Showing list of scans ");
return $response;
});
});
$app->run();
I think this is incredibly inefficient, and somehow I’m going to need to make classes (I think), but in the docs it appears even using the groups function I still need to map each function call 1-1.
What am I missing here?
I’m coming from ASP.Net MVC, and this is throwing me for a loop…
I guess my question is, how do I hook up the routes automatically (i.e. this group is handled by ScanSessionClass)?
From the docs it looks like even if I put my functions into a class, I’d still need to come back here at the main init and hand-add them all into the route list, which (in my mind) seems to mostly defeat the purpose of having them out there in the class.
Slim invokes the request handler (controller action)
The (controller) action processes the request and returns a response
Slim emits the response to the client
Point 4 in detail: How to implement the request handler (action) is up to you. You have multiple options:
A class
A function (closure)
You are already using the closure to define the action. But using classes would be better for maintenance and (unit) tests. Classes will also make your life easier when using dependency injection and a dependency injection container (DIC). Personally, I would recommend using classes (single action controller) for your actions. Also in terms of SOLID, especially the Single Responsibility Principle, a single action controller makes the most sense (to me).
Look how lean and clean it is to define a route in your routes.php:
To make it work, the action class must be “invokable”. You achive this by adding the __invoke method. Example:
<?php
// src/Action/Home/HomeAction.php
namespace App\Action\Home;
use Psr\Http\Message\ResponseInterface as Response;
use Psr\Http\Message\ServerRequestInterface as Request;
final class HomeAction
{
public function __invoke(Request $request, Response $response, array $args = []): Response
{
$response->getBody()->write("Hello, World");
return $response;
}
}
It kinda helps. I’m just not used to making individual classes for a single action (remind I’m coming from ASP.Net’s MVC mentality).
I guess I’m just going to have to accept that I’m going to have a ton of extra files dividing functionality up into teeny parts, and have a massive list of them all in the index.php when all is said and done…
Edit: I’m also floundering making my classes visible to the framework. Supposedly there’s a magic “autoloader” that Composer provides, but it’s definitely not working for my stuff for whatever reason, but that’s probably another discussion on SO or something.