2017-08-18 1 views
1

Je suis nouveau sur SLIM3 et j'ai suivi le tutoriel pour obtenir des fonctions dans le conteneur auquel je veux accéder depuis n'importe où dans le code. Voici donc mon dossier index.php où j'initalise tout:Meilleure méthode de conception pour accéder aux fonctions du conteneur

<?php 
use \Psr\Http\Message\ServerRequestInterface as Request; 
use \Psr\Http\Message\ResponseInterface as Response; 

// Require for loading the vendor libraries installed by composer 
require 'vendor/autoload.php'; 


$config['displayErrorDetails'] = true; 
$config['addContentLengthHeader'] = false; 

$app = new \Slim\App(["settings" => $config]); 
$container = $app->getContainer(); 

// Monolog initalisation. To use it write: $this->logger->addInfo("what you want to write here"); 
$container['logger'] = function($c) { 
    $logger = new \Monolog\Logger('eq_logger'); 
    $file_handler = new \Monolog\Handler\StreamHandler("logs/app.log"); 
    $logger->pushHandler($file_handler); 
    return $logger; 
}; 

// Database connections 
$container['dbteacher'] = function ($c) { 
    $pdo = new PDO($_SERVER['PGSQL_CONNECTION_STR']); 
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 
    return $pdo; 
}; 
$container['dbagent'] = function ($c) { 
    $pdo = new PDO($_SERVER['PGSQL_CONNECTION_STR_AGENT']); 
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC); 
    return $pdo; 
}; 

$app->post('/{controller}/{function}', function (Request $request, Response $response) { 
    $headers = $request->getHeaders(); 
    $params = $request->getParsedBody(); 

    $classname = $request->getAttribute('controller'); 
    $controller = new $classname($this->logger); 
    $function = $request->getAttribute('function'); 

    $result = $controller->$function($params); 

    $response->getBody()->write($result); 
    return $response; 
}); 

$app->run(); 

Ici, je peux accéder à logger en tapant $this->logger, même pour le dbteacher et dbagent, mais je peux seulement faire qu'à l'intérieur où ces conteneurs sont créés, quand je suis J'appelle une autre fonction d'une classe différente Je veux pouvoir y accéder aussi mais je ne veux pas les passer dans le paramètre car ça sera difficile à maintenir, je pense aussi à avoir une classe config.php qui initalise ces conteneurs et la variable $app et l'étendre dans toutes les classes que j'utilise mais cela ne sonne pas bien. Quelle est la meilleure façon d'aborder cela?

Répondre

5

Vous devez utiliser les fonctions du conteneur d'injection de dépendance (Pimple) utilisé par Slim3. Cela étant dit, je tiens à dire que la création dynamique de "contrôleur" n'est pas très agréable, cette abstraction ne devrait pas être là et vous devriez juste faire $response->getBody()->write($result); ou la méthode plus simple dans chaque manette. Aussi, je ne vois pas pourquoi un framework de routage complet est nécessaire pour cette construction.

Mais de toute façon, si vous ne voulez pas rester avec cette solution, vous pouvez utiliser Pimple, je vais vous expliquer cela sur un exemple.

Vous avez plusieurs classes avec différents paramètres contructor:

class A { 
    public function __construct($logger) {} 
} 

class B { 
    public function __construct($logger, $myHelper) {} 
} 

Tout d'abord, vous les ajouter au conteneur Piple:

$container['A'] = function($c) { // or $container[A::class] for type safety 
    return new A($c['logger']); 
}; 
$container['B'] = function($c) { 
    return new A($c['logger'], $c['myHelper']); 
}; 

Et vous pouvez les obtenir dans votre itinéraire en appelant obtenir sur le conteneur sur l'instance de l'application.

$app->post('/{controller}/{function}', function (Request $request, Response $response) { 
    $headers = $request->getHeaders(); 
    $params = $request->getParsedBody(); 

    $classname = $request->getAttribute('controller'); 
    $controller = $this->getContainer()->get($classname); 
    $function = $request->getAttribute('function'); 

    $result = $controller->$function($params); 

    $response->getBody()->write($result); 
    return $response; 
}); 
+0

Merci pour la réponse, l'API se connecte à une application angulaire qui a différents modules (par exemple le tableau de bord, vue de classe, view..etc étudiant) chacun a différents points d'extrémité de l'API. Ce que je construis vers est d'avoir une classe pour chaque module (le contrôleur) et une fonction à l'intérieur de cette classe que le client appelle, ce qui aiderait les développeurs à identifier où ils devraient écrire une nouvelle fonction. En plus de cela, ce simple $ app-> post me permettrait de valider les données avant qu'elles ne passent par la fonction, ou par exemple authentifier l'utilisateur. Sachant que ... –

+0

... recommandez-vous toujours d'avoir un app-> poste pour chaque fonction de point final api et pourquoi? –

+1

@NaguibIhab jup, vous pouvez faire [une structure comme celle-ci] (https://stackoverflow.com/a/45197291/4244993), alors vous avez encore les fonctions sur une classe. Pour des choses comme l'authentification, vous pouvez utiliser [middleware] (https://www.slimframework.com/docs/concepts/middleware.html) – jmattheis