I'm trying to do some very basic key validation for my API, simply checking a provided key attribute against a key stored in the database.
I've got a middleware class that i'm adding to the slim object using
$app->add(new auth());
where auth.php is my class.
I have it working and i'd like to split the code in to functions however I can't seem to call functions from within __invoke without getting a Slim Application Error.
Right now I have
public function __invoke($request, $response, $next){
try {
$user_key = $request->getAttribute('route')->getArguments()['key'];
...
//fetch key from database code
...
if($user_key==$api_key){
$response = $next($request, $response);
}
else{
$response->getBody()->write("Invalid API Key");
}
}
catch (PDOException $e) {
$response->getBody()->write("An error has occurred");
}
return $response;
}
Which works, but i'd like to move the fetch code in to its own function e.g
public function fetchKey(){
...
//return key
...
}
and call $api_key = fetchKey(); however this causes a Slim error.
This is probably really simple but does anyone know what causes this?
Related
Im currently using Lumen 8. Im having issues with routing. The controllers work fine for get methods without parameters but I get a "Bad Routes exception" when I pass parameters
$router->get('/accounts', 'AccountsController#index');
$router->get('/accounts/{id:[\d]+}', 'AccountsController#show');
For example for the first route, localhost/accounts it displays the required data. The second route however when localhost:8002/accounts/1 it returns the error.
The routes are defined in an AccountsController
public function index(){
$data = $this->collection(Account::all(), new AccountsTransformer());
return response()->json($data);
}
public function show($id){
try{
return $this->item(Account::query()->findOrFail($id), new AccountsTransformer());
} catch (ModelNotFoundException $e){
response()->json(['error'=>['message'=>'Account not found']]);
}
}
As I'm beggining with Laravel, this should be a simple one:
How can I define a custom view to be rendered when my route model binding just can't find the given ID?
Here's my route:
Route::get('/empresa/edit/{empresa}', 'EmpresaController#edit');
Here's my controller's method:
public function edit(Empresa $empresa)
{
if ((!isset($empresa)) || ($empresa == null)):
//I get that this won't work...
return 'Empresa não encontrada';
endif;
return view('Empresa.dadosEmpresa')->with('empresa', $empresa)->with('action', URL::route('empresa_update', ['id', $empresa->id]))->with('method', 'PATCH');
}
Here's my "attempt" to use an error handler:
public function render($request, Exception $exception)
{
if ($e instanceof ModelNotFoundException)
{
//this is just giving me a completely blank response page
return 'Empresa não encontrada';
}
return parent::render($request, $exception);
}
How is this really done?
1. The formal way (but would it be really needed to customize in this way?)
First of all, what Laravel does is, if there is not Model Row in DB with the given id, it sends 404 response, automatically.
If a matching model instance is not found in the database, a 404 HTTP response will be automatically generated.
So if you wanna show your customized view, you need to customize error handling.
So in RouteServiceProvider file, make sure it throws custom exception using 3rd param like follwoing:
public function boot()
{
parent::boot();
Route::model('empresa', App\Empresa::class, function () {
throw new NotFoundEmpresaModelException;
});
}
And then do same thing in the render function as you tried before.
2. The casual way - Pretty easy to go
I d rather suggest that you do not use model injection ability, but handle the request yourself.
So take the empresa id value as it is, and then try to find the right data, and if not found, then make your custom logic. That should be pretty easy to go.
public function edit(Request $request, $empresa)
{
$empresaObj = Empresa::find($empresa);
if (!$empresa) {
return 'Empresa não encontrada';
}
return view('Empresa.dadosEmpresa')->with('empresa', $empresa)->with('action', URL::route('empresa_update', ['id', $empresa->id]))->with('method', 'PATCH');
}
I am returning Json response from zend controller.
This is my code
Controller Code
public function get()
{
$result = //calling other function and getting response in array
print("value in controller before calling toJsonModel");
print_r($result);
$temp = $this->toJsonModel($result);
var_dump($temp);
return $temp;
}
toJsonModel function
public function toJsonModel($data = array())
{
$data['requestId'] = $this->getHeader('RequestId');
print("Value just before returning to controller");
print_r($data);
return new JsonModel($data);
}
Response
First and second print displays correct values. But after getting values from toJsonModel when I try to displays wrong values and adds some other values like "captureTo", "terminate" and "children" as protected.
I don't know why it's giving me wrong message.
Can any one guide me to right path and tell me what the problem is ?
Thanks in advance.
EDIT
I am adding new screenshot to display full message.
ERROR :
{"name":"Email Not Found","message":"No account found with this email
address.","code":404,"requestId":"12","reason":"error-controller-cannot-dispatch","display_exceptions":true,"controller":"RSMobile\Controller\ForgotPassword","controller_class":null}
I finally solved this problem.
I was throwing some error from controller whenever there is a problem. I used to throw 404 when email not found. That was causing this error.
At first i thought that this is a problem related to JSON model. But thanks to #Bilal who helped me in figuring out the problem.
When I throw 404 from controller it by default appends all these data at the end. But when i throw any error other than 404, it works.
This is because you are returning an object of JsonModel from method toJsonModel.
return new JsonModel($data);
So, every object has some properties that you can use to manipulate data. See the docs of Zend\View\Model\JsonModel here
So actually the values are not wrong but there is a way to access properties of an object.
Update
Attaching dispatch event
public function onBootstrap($e)
{
// some stuff
$eventManager = $e->getApplication()->getEventManager();
$eventManager->attach("dispatch", function($e) {
echo "Dispatch!";
});
// some stuff
}
I just upgraded to Laravel 4.1 and can no longer use a function I was using in the past. I wrote a function to redirect an incoming request to another route, get the result, and replace the current route with the original incoming route. I used this on my frontend controllers to consume my own API which is defined in the same application.
Here is the function:
public static function redirectRequest($newRoute, $verb, $args = null)
{
// store the original request data and route
$originalInput = Request::input();
$originalRoute = Route::current();
$request = $args === null ? Request::create($newRoute, $verb) : Request::create($newRoute, $verb, $args);
// replace the request input for the new route...
Request::replace($request->input());
try
{
$response = Route::dispatch($request);
return $response;
}
catch (\Exception $e)
{
throw $e;
}
finally
{
// replace the request input and route back to the original state
Request::replace($originalInput);
Route::setCurrentRoute($originalRoute);
}
}
And I would use it like:
Helpers::redirectRequest('/api/v1/someroute', 'GET');
The problem is that, when I try to return things to the way they were before the redirect, I can't. setCurrentRoute has been removed from 4.1 and I can't figure out how to reset the current route.
One thing that I have done in the past is used the actual routes.php to handle that. If you register a "catchall" route as:
Route::get('api/v1', 'ApiController#route');
As long as this is after all other routes (Laravel uses the first matching route) you can then handle that within your ApiController as
public function route($uri) {
// Handle your API route using the $uri variable
}
This may not be the solution that you are looking for, but I have found it very convenient.
I'm creating a service to fetch some user data
class ExampleService{
// ...
public function getValueByUser($user)
{
$result = $this->em->getRepository('SomeBundle:SomeEntity')->getValue($user);
if (!$result instanceof Entity\SomeEntity) {
throw new Exception\InvalidArgumentException("no value found for that user");
}
return $result;
}
}
Then in my controller I have
// ...
$ExampleService = $this->get('example_serivce');
$value = $ExampleService->getValueByUser($user);
Should I be using an exception here to indicate that no value was found for that user in the database?
If I should, how do I handle what is returned from $ExampleService->getValueByUser($user) in the controller - let's say I just want to set a default value if nothing is found (or exception returned)
Here is how I do it. Let's use a user service and a controller as an example. It's not an exceptional condition in the service layer — it just returns the result without checking it:
class UserService
{
public function find($id)
{
return $this->em->getRepository('UserBundle:User')->find($id);
}
}
But in the controllers layer I throw an exception if the requested user not found:
class UserController
{
public function viewAction($id)
{
$user = $this->get('user.service')->find($id);
if (!$user) {
throw $this->createNotFoundException(
$this->get('translator')->trans('user.not_found')
);
}
// ...
}
}
Where you want to handle the exception is kind of up to you, however I would handle it in the controller (and throw it in the model). I usually try to call a different template if there is an error so as to avoid a bunch of conditionals, but sometimes you just have to put extra logic in your template instead.
Also, you have to ask yourself if this is really an exceptional condition - it might be easier to return null and handle that return value in your controller. I can't really tell from the data objects (value, service, and user) whether this is something that will happen all the time or not.