Reputation: 823
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
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