I need to terminate laravel app in class method, not in route handler.
I use custom Exception and method render() it work fine but I think it is not best way.
Second way I use:
redirect()->back()->with(...)->send();
die();
but by this way dont work with() method and Session flush, work only redirect...
when I dump session it empty...
What the best way to solve this issue?
When you to use die() function, you stop the execution and Laravel does not write in session the data added during the execution, you will need use session()->save() to force write in session, but don't is the better way.
Maybe you can just put a return in your code:
return redirect()->back()->with(...)->send();
Related
First code working. See Below
The second code not working. See Below
Anyone can help provide the documentation for this code Redirect::to('/')->send();
The ->send() method should only be used in places where you cannot return a response directly. And even then, it should be used as few times as possible.
Normally, a request will go through a list of middlewares, end up in a controller which will return a response and exit through another list of middlewares. This is the normal way of returning a response.
When you use the send() function, you interrupt the pipeline and send the response back immediately.
Now, the reason only send() works in your case is because you are redirecting from a constructor and a constructor cannot have a return value. Because of this, the second example will never work.
I would encourage you to use a middleware for this check instead. This way the check is reusable and you can return a redirect response without interrupting the pipeline.
I'm using Laravel 5.5 and trying to store a variable into the session. I'm using the global helper session().
So I do this:
session(['a' => 'b']);
dd(session()->all())
just for testing, and there it is, however, when I refresh, and I remove the first line, the a variable is gone?
Also, forget(), flush(), and all other methods just work once in the request. Once you refresh, it's all gone.
dd Helper function in Laravel will dump the variable and end the execution of the script. So, you are ending this execution
session(['a' => 'b']);
This script does not execute at all.
Try returning the script or try using PHP native functions like var_dump() or print_r()
As far as I remember you shouldn't use dd() for such tests. Just use var_dump and everything should work as expected.
Also if it still doesn't work make sure you are testing it inside web middleware group
I am using laravel 5.4. In a method of a controller I have setting a value in session. If I call the dd() right after setting the session the dd() is showing all the session with the session I have just set. But if I fetch the session from another method the session is not available. If I remove the dd() from session setter method, I am getting the session properly.
My Code is as below:
public class TestController{
public function setSession(){
session(['test_key' => 'test_value']);//setting up the session
dd(session()->all());//getting the session properly here
}
public function showSession(){
dd(session()->all());//Here we are not getting the session
}
}
If we remove the dd() from setSession() session it works properly. Is it a bug of Laravel or it's intentional. I am interested to know the root cause of this fact. Thanks
dd() means "dump & die" and uses die() in its implementation, which immediately terminates the framework and does not allow Laravel to correctly complete the request and save the session. You can use dump() to display information like dd() does and do not shut down the kernel after.
Remove this line dd(session()->all())
from setSession() and try it again.
What is the correct way to stop code execution after sending Response headers, but without using exit()?
I know the script SHOULD return a Response, but how can I force it to be returned from outside of a Controller, for example from a service?
Lets say my service's method does return a Response this way:
return RedirectResponse($url)->send();
But in another place it can return other things. So what I can do is to check what it does actually return:
$result = $myService->doSomething();
if ($result instanceof RedirectResponse) {
return $result;
}
What I want to achieve is to avoid checking result type in every place where I use my service, BUT I would like to see the returned response in Profiler/logs (if I use exit() I can't).
Is there a way to force kernel terminate?
EDIT:
Actually the service is used in event before any controller, so I want to do redirect before any controller execution. So maybe a way to omit controller execution?
A controller is a PHP callable you create that takes information from the HTTP request and creates and returns an HTTP response (as a Symfony Response object).
The only concern for a Controller is to process a request and return a response. Having a Service handle a Response object is probably a bad design choice.
In any case, you could just die/exit your controller and use Kernel events to hook in the Request/Response flow and inspect the returned Response. Probably the terminate event is the right choice http://symfony.com/doc/current/components/http_kernel/introduction.html
Ok, I found a way to do it. All I had to do is to terminate the kernel before exit - it does dispatch all after-response events (like profiling, logging etc.).
$response = new RedirectResponse($url);
$response->send();
$kernel->terminate($request, $response);
exit();
If anyone would found better way do to this, please answer so I can switch the mark.
In a PHP MVC framework, how can I cleanly and elegantly exit from the current controller/action, but continue normal script execution?
For example, let's say my framework normally follows this outline:
Map URL to Controller/Action
Instantiate Controller, call Action (capturing output)
Do stuff
Render View
At end of Action method, continue normal operation
Process output if necessary
Send output to browser
Now, let's say I want to stop "normal" execution somewhere in the "Do Stuff" step to, say, render a different view, or do a header redirect, and I want to stop processing the rest of the body of the Action, but continue onto the "Process output" step
How can I achieve this the best way? My only ideas are:
//in controller
protected function redirect($url) {
header("Location: $url");
exit();
}
but this entirely skips the rest of the framework's execution, and dumps whatever was in the output buffer straight to the user. An alternative:
//in dispatcher
call_user_func_array(array($controller,$action),$params);
afterwards:
...
//in controller
protected function redirect($url) {
header("Location: $url");
goto afterwards;
}
However, this makes me twitch and goes against everything I've learned, especially because the label it's referencing is in another file completely.
So, is there any other way to achieve this?
Note: The redirect example probably should use the exit() way, because we're just redirecting to another page anyway and don't care about output. I'm looking for a general-use solution.
In your Action method, you can collect all of your output in a string rather than printing it out. Print it out only at the end of the method. If you need to redirect or bail out, then you haven't output anything yet and you can either redirect or return from the method.
Perhaps you could write a custom exception to represent a "Stop normal execution in the 'Do Stuff'" step? It's messy... but it would work.
you need to abstract much more things. dont just output inside a action! dont set headers as there can go so much wrong before. have different handlers. response handler. handle respons and act depending what you respond. dont just output inside actions. if you have errors throw exceptions catch them with a exceptionhadler and so on.
basic controller action
public function view(int $user_id): ResponseHandler {
$this->validate($user_id); //throws exception
if (1 == 2) throw new ControllerInvalidArgumentException();
$view = new View('nameof view');
return new ResponseHandler($view);
}
just have a look at existing frameworks they have very good implemntations of design patterns like laravel or symfony. not sure what you try just dont write your own framework. if you want to learn read and learn from others if you understand whyt they do you will know how to do.