SneakyShrike
SneakyShrike

Reputation: 823

PHP Slim 3 - Accessing class object instances within a slim route

So I’m learning how to write a Slim 3 PHP authentication app and I'm using an example code structure to get me started. The example code has a file called dependencies.php which has a series of functions that create object instances of other classes. These are then assigned to a $container variable with a name for each function. An example of these functions in the dependencies.php file can be seen here:

$container['view'] = function ($container) {
    $view = new \Slim\Views\Twig(
        $container['settings']['view']['template_path'],
        $container['settings']['view']['twig'],
        [
            'debug' => true // This line should enable debug mode
        ]
    );

    $basePath = rtrim(str_ireplace('index.php', '', $container['request']->getUri()->getBasePath()), '/');
    $view->addExtension(new Slim\Views\TwigExtension($container['router'], $basePath));

    $view->addExtension(new \Twig_Extension_Debug());

    return $view;
};

$container['validate_sanitize'] = function ($container)
{
    $class_path = $container->get('settings')['class_path'];
    require $class_path . 'ValidateSanitize.php';
    $validator = new ValidateSanitize();
    return $validator;
};

$container['hash_password'] = function($container)
{
    $class_path = $container->get('settings')['class_path'];
    require $class_path . 'HashPassword.php';
    $hash = new HashPassword();
    return $hash;
};

These functions are then somehow called in my slim routes. For example in my register.php slim route the validate_sanitize class object is called with a simple

$this->get(‘validate_sanitize’); 

and assigned to a variable which I can then use to call methods from the validate_sanitize class.

However what I don’t understand is how this get method works on calling a class object from the dependencies.php file.

Here is the aforementioned register route that is a post request for incoming form data:

$app->post('/register', function(Request $request, Response $response)
{
    $arr_tainted_params = $request->getParsedBody();

    $sanitizer_validator = $this->get('validate_sanitize'); //here for example
    $password_hasher = $this->get('hash_password');

    $tainted_email = $arr_tainted_params['email'];
    $tainted_username = $arr_tainted_params['username'];
    $tainted_password = $arr_tainted_params['password'];

    $model = $this->get('model');
    $sql_wrapper = $this->get('sql_wrapper');
    $sql_queries = $this->get('sql_queries');
    $db_handle = $this->get('dbase');

    $cleaned_email = $sanitizer_validator->sanitize_input($tainted_email, FILTER_SANITIZE_EMAIL);
    $cleaned_username = $sanitizer_validator->sanitize_input($tainted_username, FILTER_SANITIZE_STRING);
    $cleaned_password = $sanitizer_validator->sanitize_input($tainted_password, FILTER_SANITIZE_STRING);
 });

All my routes are contained within a routes.php file that looks like this:

 <?php

require 'routes/change_password.php';
require 'routes/forgot_password.php';
require 'routes/homepage.php';
require 'routes/login.php';
require 'routes/logout.php';
require 'routes/register.php';

There is also a bootstrap file that creates a new Slim container, Slim App instance and also includes necessary files. I’m also not entirely sure what a Slim\Container is or what it does. This bootstrap file looks like this:

<?php

session_start();

require __DIR__ . '/../vendor/autoload.php';

$settings = require __DIR__ . '/app/settings.php'; //an array of options containing database configurations and the path to twig templates

$container = new \Slim\Container($settings); //not sure what this does

require __DIR__ . '/app/dependencies.php';

$app = new \Slim\App($container);

require __DIR__ . '/app/routes.php';

$app→run();

I’ve tried reading a number of articles as well as watching various YouTube videos but they do things differently with controllers which just adds more complexity and confusion for me. I’d much rather an explanation on this specific example as I find the code structure fairly simple.

Thanks.

Upvotes: 2

Views: 1992

Answers (1)

Zamrony P. Juhara
Zamrony P. Juhara

Reputation: 5262

Inside route callable, $this will point to $container instance.

In Slim 3.0, if you take a look at map() method of Slim\App class, you will see following code:

if ($callable instanceof Closure) {
   $callable = $callable->bindTo($this->container);
}

bindTo() is what makes you have access to container inside route callable using $this variable.

If you want to use class as route handler and want access to container instance inside class, you need to pass it manually. For example

<?php 
namespace App\Controller;

class MyPostRegisterController
{
    private $container;

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

    public function __invoke(Request $request, Response $response)
    {
        $sanitizer_validator = $this->container->get('validate_sanitize'); 
        //do something
    }
}

Then you can define route as following

$app->post('/register', App\Controller\MyPostRegisterController::class);

If Slim can not find MyPostController class in dependency container, it tries to create them and pass container instance.

Update

To call other method, append method name after class name separated by colon. For example, following route registration will call method home() in MyPostRegisterController class.

$app->post('/register', App\Controller\MyPostRegisterController::class . ':home');

Upvotes: 1

Related Questions