The variable $user is null in this closure function. I don't understand why.
Routes.php
require_once(__DIR__ . '/classes/user.php');
$user = User::getInstance(); // returns a $_SESSION user or a new User()
This does not work
$app->group('/user', function () use ($app, $user) {
$app->post('/activate', function(Request $request, Response $response) {
$parsedBody = $request->getParsedBody();
$result = $user->activate($parsedBody); // error user is null
return $response->withJson($result);
});
});
This does
$app->group('/user', function () use ($app) {
$app->post('/activate', function(Request $request, Response $response) {
$parsedBody = $request->getParsedBody();
$user = User::getInstance();
$result = $user->activate($parsedBody);
return $response->withJson($result);
});
});
You need to inherit that variable into your function.
http://php.net/manual/en/functions.anonymous.php - #3
$app->group('/user', function () use ($app, $user) {
$app->post('/activate', function(Request $request, Response $response) use ($user) {
$parsedBody = $request->getParsedBody();
$result = $user->activate($parsedBody); // now it shouldn't
return $response->withJson($result);
});
});
Related
I would like to call a route middleware with a parameter passed from the route when added. How is it possible?
$app->get('/path', function($request, $response, $lvlreq = 1) {
$oViewParams = new \lib\ViewParams("referencia", "", "", "", "");
$params = array('viewp' => $oViewParams->getMassParams());
return $this->get('view')->render($response, 'some.html', $params);
})->add($authenticate)
->add($tmhasaccess);
First middleware doesn't need params, thats going well.
$authenticate = function (Request $request, RequestHandler $handler) {
if (!isset($_SESSION['param'])) {
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$redirect = $route->getPattern();
$_SESSION['urlRedirect'] = $redirect;
$this->get('flash')->addMessage('error', 'error');
$response = $handler->handle($request);
return $response->withStatus(302)->withHeader('Location', '/login');
} else {
$response = $handler->handle($request);
return $response;
}
};
$tmhasaccess = function (Request $request, RequestHandler $handler) {
###I need $lvlreq value inside here to work with it. This won't work:
$routeContext = RouteContext::fromRequest($request);
$route = $routeContext->getRoute();
$lvlreq = $route->getArgument('lvlreq');
};
Middleware changed to class:
class TMHasAccessMiddleware
{
protected $lvlreq;
private $container;
function __construct($container, $lvlreq = 0) {
$this->lvlreq = $lvlreq;
$this->container = $container;
}
public function __invoke(Request $request, RequestHandler $handler): Response
{
##$this->lvlreq now accessible.
}
}
Can be called from route:
->add(new TMHasAccessMiddleware($container, 1));
I'm using postman to test my API, but right now I have a problem with the put routes.
So this is a put route I wrote:
$app->put('/setting/{id}/settingvalue', function (ServerRequestInterface $request, Response
Interface $response, $args) {
try {
$user = new \Riecken\PBS\controller\SettingsValueController();
$result = $user->updateOneSettingsValueinDetail( $args['id'], $request->getParsedBody());
$response = $response->withJson($result);
$response = $response->withStatus(200);
return $response;
}catch(Exception $e) {
$response->getBody()->write($e->getMessage());
return $response->withStatus($e->getCode());
}
});
And this is the function which you see above (updateOneSettingsValueinDetail):
public function updateOneSettingsValueinDetail ($settingsvalueIdToUpdate, $body) {
try {
return $this->SettingsValueDao->update($settingsvalueIdToUpdate, $body);
}catch(DAOException $e) {
throw new \Exception($e->returnErrorMessage(), $e->returnHttpCode());
}catch(\Exception $e) {
throw new \Exception("System Error", 500);
}
}
The problem is that Postman tells me that the Method is not allowed, only POST and GET is allowed:
enter image description here
Does anybody know what type of problem that is and what the solution could be?
This response is come from Slim's NotAllowedHandler. And it is not only POST and GET as default. This response is not related to your mentioned above code.
Are you sure you don't customize "NotAllowedHandler" and you don't bind to app as middleware?
I wrote this code that containing that would create the same situation:
<?php
use Psr\Http\Message\ResponseInterface;
use Psr\Http\Message\ServerRequestInterface;
use Slim\App;
require __DIR__ . '/../vendor/autoload.php';
$app = new App([]);
$container = $app->getContainer();
$app->add(function ($request, $response, $next) {
$allowed = ['GET', 'POST'];
if (!in_array($request->getMethod(), $allowed)) {
$notAllowed = new \Slim\Handlers\NotAllowed();
return $notAllowed($request, $response, $allowed);
}
$next($request, $response);
});
$app->put('/setting/{id}/settingvalue', function (ServerRequestInterface $request, ResponseInterface $response, $args) {
die("Expected Context via PUT");
});
$app->get('/setting/{id}/settingvalue', function (ServerRequestInterface $request, ResponseInterface $response, $args) {
die("Expected Other Context via GET");
});
$app->run();
I hope to it help you.
I have created a simple rest api which handles some POST data. I would like to add some functions to sanitize the data before sending a response.
I am new to Slim and PHP so unsure if this is possible / i am solving the problem using the "correct" approach.
Here is my attempt so far (which does not work!) The middleware is called, but the process function always returns NULL
<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require __DIR__ . '/../vendor/autoload.php';
$app = new \Slim\App();
// add function to $app
$app->process = function ($request, $response, $next) use($app) {
return 'process';
};
$process = $app->process;
// middleware
$mw = function ($request, $response, $next) {
$response = $next($request, $response);
// should return string from above function
$variable = $process
$data = array('name' => $name, 'process' => $variable);
$newResp = $response->withJson($data);
return $newResp;
};
$app->post('/api/name', function (Request $request, Response $response, array $args) {
$parsed= $request->getParsedBody();
$response = $response->withStatus(200);
})->add($mw);
$app->run();
There were several issues:
Added function to $app which results in a BadMethodCallException
$appalready has a method called process
Missed ; after $variable = $process
This code gives your desired result:
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;
require __DIR__ . '/../vendor/autoload.php';
// turn error logging on!
$app = new \Slim\App(['settings' => ['displayErrorDetails' => true]]);
// your function
$sanitize = function(){
return 'process';
};
// middleware + pass function
$mw = function ($request, $response, $next) use($sanitize) {
$response = $next($request, $response);
$variable = $sanitize(); // execute function
$data = array('name' => $name, 'process' => $variable);
$newResp = $response->withJson($data);
return $newResp;
};
$app->get('/api/name', function (Request $request, Response $response, array $args) {
$parsed= $request->getParsedBody();
$response = $response->withStatus(200);
})->add($mw);
$app->run();
When you don't need to use the functions in other middleware, you could simply define the functions in your middleware, like this:
// middleware
$mw = function ($request, $response, $next) use($sanitize) {
$response = $next($request, $response);
// your function
function sanitize(){
return 'process';
}
$data = array('name' => $name, 'process' => sanitize());
$newResp = $response->withJson($data);
return $newResp;
};
I am trying to handle errors in slim framework custom middle ware but dont know how to do this like in my code i am doing that if the request is not of four specific types then through an error that i want to handel in errorHandler with appropriate message and status but currently this code is just returning the status in postman with a blank screen in response body. I am not very much familiar with SLIM. Thanks in advance
<?php
require 'vendor/autoload.php';
use \Slim\App;
$c = new \Slim\Container();
$c['notAllowedHandler'] = function ($c) {
return function ($request, $response, $methods) use ($c) {
return $c['response']
->withStatus(405)
->withHeader('Allow', implode(', ', $methods))
->withHeader('Content-type', 'application/json')
->write(json_encode(array("c_status"=>"405","message"=>"Bad Request")));
};
};
$c['notFoundHandler'] = function ($c) {
return function ($request, $response) use ($c) {
return $c['response']
->withStatus(404)
->withHeader('Content-type', 'application/json')
->write(json_encode(array("c_status"=>"404","message"=>"Not Found")));
};
};
$c['errorHandler'] = function ($c) {
return function ($request, $response, $exception) use ($c) {
$data = [
'c_status' => $response->getStatus(),
'message' => $exception->getMessage()
];
return $container->get('response')->withStatus($response->getStatus())
->withHeader('Content-Type', 'application/json')
->write(json_encode($data));
};
};
$app = new App($c);
$app->add(function ($request, $response, $next) {
if($request->isGet() || $request->isPost() || $request->isPut() || $request->isDelete()){
$response = $next($request, $response);
}else{
$response = $response->withStatus(403);
}
return $response;
});
require 'API/routes.php';
$app->run();
Throw an exception:
$app->add(function ($request, $response, $next) {
if($request->isGet() || $request->isPost() || $request->isPut() || $request->isDelete()){
$response = $next($request, $response);
}else{
throw new \Exception("Forbidden", 403);
}
return $response;
})
How can I get the param in this case?
$this->get('/{id}', function($request, $response, $args) {
return $response->withJson($this->get('singleSelect'));
});
$this->appContainer['singleSelect'] = function ($id) {
return $this->singleSelect($id);
};
public function singleSelect($id) {
return $id;
}
Thanks in advance.
UPDATE
Solution in my case:
$app->group('/id', function () {
$this->get('/{id}', function($request, $response, $args) {
$this['container'] = $args; //work with $args inside the container
return $this->singleSelect($id);
});
});
If I right understand services have not access to routes parameters. All you can access is container itself but it could be tricky to get information about arguments from it (something like $container->getRoutes()['<routename>']->getArguments() where <routename> router could have subroutes, etc.)
IMHO your code should look like:
$container = new \Slim\Container;
$app = new \Slim\App($container);
class Example {
public function singleSelect($id) {
return $id;
}
}
$container['example'] = function () {
return new Example();
};
$app->group('/id', function () {
$this->get('/{id}', function($request, $response, $args) {
return $response->withJson($this->example->singleSelect($args['id']));
});
});
$app->run();