For an API I am writing, in my routes file I have:
$app->get('item/{id}', 'ApiController#item');
$app->get('groupitems/{group}', 'ApiController#groupItems');
In my Controller I have the relevant two functions:
public function item($id, Request $request)
{
if ($this->isAuthorised($request->input('tenant_id'), $request->input('api_code'))) {
$item = Line::find($id);
if ($item) { ...
public function groupItems($id, Request $request)
{
if ($this->isAuthorised($request->input('tenant_id'), $request->input('api_code'))) {
$items = Line::where('tenant_id', $request->input('tenant_id'))->where('publish', true) ...
The calls are both made in exactly the same way, for example:
http://api.artlook.com/groupitems/29?tenant_id=2&api_code=o9rty43
Please don't try that as the URL is only on a local server at the moment.
My first function runs perfectly. The second one returns an error exception
Argument 2 passed to groupItems() must be an instance of Illuminate\Http\Request, string given
But they are identical and in the same controller. Help?
The problem here, is that you have declared the parameter name as {group}. Therefore, you need to set the argument variable to that name:
public function groupItems($group, Request $request)
...
Related
This is my code:
require APPPATH . '/libraries/REST_Controller.php';
class Login extends REST_Controller
{
function __construct($config = 'rest')
{
parent::__construct($config);
}
public function index_post()
{
echo "Post";
}
public function index_get()
{
echo "Get";
}
}
But I use Postman to test:
When I use Post method:
When I use Get method
I use different method, but it work only with index_get. If I remove function index_get and use post method on Postman, it will be unknow method.
How to fix it? I need use post method.
you are using the same function name, change the function name. It might be different(_post,_get) while you are coding, But when you are accessing through url you have to remove the method(_post,_get) which means both are of same function name. So it returns the first function return value
I am trying to redirect request if authorization is failed for it. I have following code:
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){ /* ... */}
public function failedAuthorization() {
return redirect('safepage');
}
}
By default I am redirected to the 403 error page, but I would like to specify some specific route. I noticed that method failedAuthorization() is run, but redirect() method does not work...
Previously this code worked well with Laravel 5.1 but I used forbiddenResponse() method to redirect wrong request. How can I fix it with new LTS version?
Looks like it is impossible to redirect() directly from the custom ValidateRequest class. The only solution that I found is create custom exception and than handle it in the Handler class. So, now it works with following code:
Update: The method redirectTo() was updated to make solution work on Laravel 6.x and higher
app/Requests/ValidateRequest.php
class ValidateRequest extends Request{
public function authorize(){
// some logic here...
return false;
}
public function rules(){
return [];
}
public function failedAuthorization() {
$exception = new NotAuthorizedException('This action is unauthorized.', 403);
throw $exception->redirectTo("safepage");
}
}
app/Exceptions/NotAuthorizedException.php
<?php
namespace App\Exceptions;
use Exception;
class NotAuthorizedException extends Exception
{
protected $route;
public function redirectTo($route) {
$this->route = $route;
abort(Redirect::to($route));
}
public function route() {
return $this->route;
}
}
and app/Exceptions/Handler.php
...
public function render($request, Exception $exception){
...
if($exception instanceof NotAuthorizedException){
return redirect($exception->route());
}
...
}
So, it works, but much more slower than I expected... Simple measuring shows that handling and redirecting take 2.1 s, but with Laravel 5.1 the same action (and the same code) takes only 0.3 s
Adding NotAuthorizedException::class to the $dontReport property does not help at all...
Update
It runs much more faster with php 7.2, it takes 0.7 s
If you are revisiting this thread because in 2021 you are looking to redirect after failed authorization here's what you can do:
You cannot redirect from the failedAuthorization() method because it is expected to throw an exception (check the method in the base FormRequest class that you extend), the side effect of changing the return type is the $request hitting the controller instead of being handled on FormRequest authorization level.
You do not need to create a custom exception class, neither meddle with the Laravel core files like editing the render() of app/Exceptions/Handler.php, which will pick up the exception you threw and by default render the bland 403 page.
All you need to do is throw new HttpResponseException()
In the Laravel reference API we can see its job is to "Create a new HTTP response exception instance." and that is exactly what we want, right?
So we need to pass this Exception a $response. We can pass a redirect or JSON response!
Redirecting:
protected function failedAuthorization()
{
throw new HttpResponseException(response()->redirectToRoute('postOverview')
->with(['error' => 'This action is not authorized!']));
}
So we are creating a new instance of the HttpResponseException and we use the response() helper, which has this super helpful redirectToRoute('routeName') method, which we can further chain with the well known with() method and pass an error message to display on the front-end.
JSON:
Inspired by this topic
throw new HttpResponseException(response()->json(['error' => 'Unauthorized action!'], 403));
Thats'it.
You don't have to make ANY checks for validation or authorization in your controller, everything is done in the background before it hits the controller. You can test this by putting a dd('reached controller'); at the top of your controller method and it shouln't get trigered.
This way you keep your controller thin and separate concerns :)
Sidenote:
forbiddenResponse() has been replaced after lara 5.4 with failedAuthorization()
You can do through a middleware/policy i think. I don't know if you can do it from the validation.
You can override the function from FormRequest like this below:
/**
* Handle a failed authorization attempt.
*
* #return void
*
* #throws \Illuminate\Auth\Access\AuthorizationException
*/
protected function failedAuthorization()
{
throw new AuthorizationException('This action is unauthorized.');
}
And redirect where you want.
I'm trying to create a ZF1 plugin to centralize my Authentication system. So far here is what I did :
class Application_Plugin_Auth extends Zend_Controller_Plugin_Abstract {
private $_whitelist;
protected $_request;
public function __construct() {
$this->_whitelist = array(
'default'
);
}
public function preDispatch(Zend_Controller_Request_Abstract $request) {
$this->_request = $request;
$module = strtolower($this->_request->getModuleName());
if (in_array($module, $this->_whitelist)) {
return;
}
$auth = Zend_Auth::getInstance();
if (!$auth->hasIdentity()) {
$this->_request->setModuleName('admin');
$this->_request->setControllerName('auth');
$this->_request->setActionName('login');
return;
}
}
}
It works perfectly to avoid people to access the backend if there are not logged. Now, I would like to implement a login function with no parameters which will grab the current request, check the param (getPost) and then do the login job :
public function login(){
// Here will check the request data and then try to login
}
My question is how can I get the current request object in this function? Also, how to use this login function in my controller?
Thanks a lot
This is what you want when you don't want to pass the request as argument to your function:
$request = Zend_Controller_FrontController::getInstance()->getRequest();
$postData = $request->getPost();
However, usually you do want to pass arguments to your function. Mostly because you want your object that operates with the login functionality to be independent from the rest of your system. There are only few cases I can think of that disagree from this methodology.
When you like to get the Request from your front controller, you can just issue:
$request = $this->getRequest();
I have troubles to do REST application in CakePHP, requesting GET /admin/quote_authors/1.json sends me to the 'view' action, not 'admin_view'.
route.php:
Router::parseExtensions('json');
Router::mapResources(array(':controller'), array('prefix' => '/admin/'));
QuoteAuthorsController.php:
public $components = array('RequestHandler');
public function admin_view($id) {
var_dump('admin view');
}
public function view($id) {
var_dump('view');
}
Thanks.
Answering because I can't comment.
You seem to be missing the action part of the request /admin/quote_authors/view/1.json
So for other request it would be like /admin/:controller/:action/:params in general.
And, of course, like thaJeztah said, remove the slashes of the prefix (that's why it's giving you that error, it's considering the parameter "1" as the action it has to execute)
I'm trying to set up a route in Zend Framework (version 1.11.11) in a routes.ini file, which would allow be to match the following url:
my.domain.com/shop/add/123
to the ShopController and addAction. However, for some reason the parameter (the number at the end) is not being recognized by my action. The PHP error I'm getting is
Warning: Missing argument 1 for ShopController::addAction(), called in...
I know I could set this up using PHP code in the bootstrap, but I want to understand how to do this type of setup in a .ini file and I'm having a hard time finding any resources that explain this. I should also point out that I'm using modules in my project. What I've come up with using various snippets found here and there online is the following:
application/config/routes.ini:
[routes]
routes.shop.route = "shop/add/:productid/*"
routes.shop.defaults.controller = shop
routes.shop.defaults.action = add
routes.shop.defaults.productid = 0
routes.shop.reqs.productid = \d+
Bootstrap.php:
...
protected function _initRoutes()
{
$config = new Zend_Config_Ini(APPLICATION_PATH . '/configs/routes.ini', 'routes');
$router = Zend_Controller_Front::getInstance()->getRouter();
$router->addConfig( $config, 'routes' );
}
...
ShopController.php
<?php
class ShopController extends Egil_Controllers_BaseController
{
public function indexAction()
{
// action body
}
public function addAction($id)
{
echo "the id: ".$id;
}
}
Any suggestions as to why this is not working? I have a feeling I'm missing something fundamental about routing in Zend through .ini files.
Apparently I'm more rusty in Zend than I thought. A few minutes after posting I realized I'm trying to access the parameter the wrong way in my controller. It should not be a parameter to addAction, instead I should access it through the request object inside the function:
correct addAction in ShopController:
public function addAction()
{
$id = $this->_request->getParam('productid');
echo "the id: ".$id;
}
I also realized I can simplify my route setup quite a bit in this case:
[routes]
routes.shop.route = "shop/:action/:productid"
routes.shop.defaults.controller = shop
routes.shop.defaults.action = index