Reputation: 403
Considering this example from Slim PHP, which is used as middleware.
What's the difference between this,
$authenticateForRole = function ( $role = 'member' ) {
return function () use ( $role ) {
$user = User::fetchFromDatabaseSomehow();
if ( $user->belongsToRole($role) === false ) {
$app = \Slim\Slim::getInstance();
$app->flash('error', 'Login required');
$app->redirect('/login');
}
};
};
and this,
$authenticateForRole = function ( $role = 'member' ) {
$user = User::fetchFromDatabaseSomehow();
if ( $user->belongsToRole($role) === false ) {
$app = \Slim\Slim::getInstance();
$app->flash('error', 'Login required');
$app->redirect('/login');
}
};
Aren't those functions the same?
Upvotes: 1
Views: 139
Reputation: 204
In the context of the slim framework and middleware, and the particular example this question is associated with.
The logic is wrapped in a closure so it can be called at later point by the framework middleware logic and preserve the user argument for the $role.
for reference and context - Usage code for from original post
$app->get('/foo', $authenticateForRole('admin'), function () {
//Display admin control panel
});
understanding the calling context, you should see why these two are different.
from this point on when referring to the 2nd code you provided I will reference to it as $authenticateForRole2 in code.
Using the 2nd code as shown below: will result in an immediate execution of the function $authenticateForRole2 the return value(null) will be passed as the middlewere argument. The "middlewere" argument is expected to be an callable/invokable object, and that is why this code is incorrect.
$app->get('/foo', $authenticateForRole2('admin'), function () {
//Display admin control panel
});
Partially Works, not 100% same functionality it will use the default $role as set in the declaration of the function. And you can't provide a different $role parameter, when defining the api(setting up the paths)
$app->get('/foo', $authenticateForRole2, function () {
//Display admin control panel
});
This should work but it will require repeating the declaration for each $role value. for example if one path is for 'admin' and the other is for 'member'
note I moved the $role inside the function, because slim pass an object as argument to the middlewere function when it is called.
$app->get('/foo',
function() {
$role = 'admin'
$user = User::fetchFromDatabaseSomehow();
if ( $user->belongsToRole($role) === false ) {
$app = \Slim\Slim::getInstance();
$app->flash('error', 'Login required');
$app->redirect('/login');
}
} , function () {
//Display admin control panel
});
$app->get('/bar',
function (){
$role = 'member'
$user = User::fetchFromDatabaseSomehow();
if ( $user->belongsToRole($role) === false ) {
$app = \Slim\Slim::getInstance();
$app->flash('error', 'Login required');
$app->redirect('/login');
}
} , function () {
//Display admin control panel
});
The original example uses the closure wrapping trick to provide a DRY way for the role authentication method.
$app->get('/foo', $authenticateForRole('admin'), function () {
//Display admin control panel
});
$app->get('/bar', $authenticateForRole('member'), function () {
//Display member control panel
});
Upvotes: 1