Getting lost in the weeds, and I haven't even begun

(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…

Looks good so far. What is your actual question / error message?

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.

This is how it works:

  1. The request comes in
  2. The router will find a matching route
  3. Slim invokes the request handler (controller action)
  4. The (controller) action processes the request and returns a response
  5. 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:

  1. A class
  2. 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:

$app->get('/', \App\Action\Home\HomeAction::class);

$app->get('/users', \App\Action\User\ListUserAction::class);

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;
    }
}

Here you can find more examples

I hope it helps :slight_smile:

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.

I think I know what you mean. In ASP.NET you have controller classes with multiple action methods. This reduces the number of classes.

have a massive list of them all in the index.php

Don’t put everything into a single index.php file. Instead create a special file for the routes (config/routes.php).

there’s a magic “autoloader” that Composer provides

In ASP.NET you don’t need an autoloader. In a PHP application / website this is the most important setup step to use classes in PHP.

1 Like

Whether it’s in the main index.php file or a separate one, it’s still a gigantic list that mostly hand-maps routes to individual classes. :stuck_out_tongue_winking_eye:

Yeah, I’m still in PHP 5 world where you just included stuff, not used to PHP 7 yet at all and it’s causing much stumbling…