Why cookie isn't set in Laravel Lumen - php

This question is the following of this question.
I have a message in my view who says : This site uses cookie [...] Close.
When user click on Close, an ajax request is send to the controller. The function is the following :
public function acceptCookie(Request $request)
{
if ($request->valid == 'accept') {
$response = new Response('acceptCookie');
if ($response->withCookie(cookie('acceptCookie', 'accepte', 44000))) {
return Response()->json(array('statut' => 'Succes'));
} else {
return Response()->json(array('statut' => 'Erreur'));
}
} else {
return Response()->json(array('statut' => 'Erreur'));
}
}
I haven't any error and JSON returns always {"statut":"Succes"}
Why the cookie isn't set ?

Based on the Lumen documentation, it appears as though you need to queue the cookie for a response such as the one in your example. Here's what the docs say:
Queueing A Cookie For The Next Response
If you would like to set a cookie before a response has been created,
use the Cookie::queue() method. The cookie will automatically be
attached to the final response from your application.
Cookie::queue($name, $value, $minutes);
My suggestion would be to try replacing the withCookie with queuing the cookie instead. But, you might need to rewrite the function a bit in order to accomodate because it appears as though you're trying to send to responses from one request.
Hope this works for you!

Based on Illuminate\Http\ResponseTrait line 28, the Illuminate\Http\Response::withCookie method returning $this.
/**
* Add a cookie to the response.
*
* #param \Symfony\Component\HttpFoundation\Cookie $cookie
* #return $this
*/
public function withCookie(Cookie $cookie)
{
$this->headers->setCookie($cookie);
return $this;
}
Means you have logic failure in your code.
// This always return Illuminate\Http\Response instance,
// thus it will never reach ELSE statement forever.
if ($response->withCookie(cookie('acceptCookie', 'accepte', 44000))) {
return Response()->json(array('statut' => 'Succes'));
} else {
return Response()->json(array('statut' => 'Erreur'));
}

Related

The GET method is not supported for this route. Supported methods: POST on Flutterwave implementation with laravel

I am implementing Flutterwave implementation as found on Medium but I am getting the error:
The GET method is not supported for this route. Supported methods: POST.
http://localhost:8000/rave/callback?resp=%7B%22name%22%3A%22opop%22%2C%22data%22%3A%7B%22data%22%3A%7B%22responsecode%22%3A%2200%22%2C%22responsetoken%22%3Anull%2C%22responsemessage%22%3A%22successful%22%7D%2C%22tx%22%3A%7B%22id%22%3A2424493%2C%22txRef%22%3A%22rave_611fc5fe12df9%22%2C%22orderRef%22%3A%22URF_1629472286526_3670035%22%2C%22flwRef%22%3A%22FLW-MOCK-44b7ecdb3a2183c971db03d669dc1554%22%2C%22redirectUrl%22%3A%22http%3A%2F%2Flocalhost%3A8000%2Frave%2Fcallback%22%2C%22device_fingerprint%22%3A%22888b449800a5003eaf1eeea02d5d52db%22%2C%22settlement_token%22%3_
I am implementing Post routes as shown in:
Route::post('/pay', 'RaveController#initialize')->name('pay');
Route::post('/rave/callback', 'RaveController#callback')->name('callback');
And on my controller, I've got:
public function initialize() {
//This initializes payment and redirects to the payment gateway
//The initialize method takes the parameter of the redirect URL
Rave::initialize(route('callback'));
}
/**
* Obtain Rave callback information
* #return void
*/
public function callback() {
$data = Rave::verifyTransaction(request()->txref);
dd($data); // view the data response
if ($data->status == 'success') {
//do something to your database
} else {
//return invalid payment
}
}
Please can anyone help me solve this problem? Especially since changing the route to get returns null. Thanks a whole lot!
that's because of you are calling the route again here that is mean you will go to this direction with get method
public function initialize(){
Rave::initialize(route('callback'));
}
the best solution to you you have to call this function without routing it as following
public function initialize(Request $request){
//here now you will not routing with get you will call the function inside it
Rave::initialize($this->callback($request->all()));
}
/**
* Obtain Rave callback information
* #return void
*/public function callback($request){
$data = Rave::verifyTransaction($request->txref);
dd($data); // view the data response
if ($data->status == 'success') {
//do something to your database
}
else {
//return invalid payment
}
}
I suppose Route::post('/rave/callback', 'RaveController#callback')->name('callback'); Is your problem. It should be Route::get
Hi. I am sorry for editing this directly as I cant find the reply button. Route::get() returns null for this particular implementation.

Laravel allow route to be accessible only from another route

I have /signup/select-plan which lets the user select a plan, and /signup/tos which displays the terms of services. I want /signup/tos to be only accessible from /signup/select-plan. So if I try to go directly to /signup/tos without selecting a plan, I want it to not allow it. How do I go about this?
In the constructor, or the route (if you are not using contructors), you can check for the previous URL using the global helper url().
public function tos() {
if ( !request()->is('signup/tos') && url()->previous() != url('signup/select-plan') ) {
return redirect()->to('/'); //Send them somewhere else
}
}
In the controller of /signup/tos which returns the tos view just add the following code:
$referer = Request::referer();
// or
// $referer = Request::server('HTTP_REFERER');
if (strpos($referer,'signup/select-plan') !== false) {
//SHOW THE PAGE
}
else
{
dd("YOU ARE NOT ALLOWED")
}
What we are doing here is checking the HTTP referrer and allowing the page access only if user comes from select-plan
You are need of sessions in laravel. You can see the following docs to get more info: Laravel Sessions
First of all you need to configure till how much time you want to have the session variable so you can go to your directory config/sessions.php and you can edit the fields 'lifetime' => 120, also you can set expire_on_close by default it is being set to false.
Now you can have following routes:
Route::get('signup/select-plan', 'SignupController#selectPlan');
Route::post('signup/select-token', 'SignupController#selectToken');
Route::get('signup/tos', 'SignupController#tos');
Route::get('registered', 'SignupController#registered');
Now in your Signupcontroller you can have something like this:
public function selectPlan()
{
// return your views/form...
}
public function selectToken(Request $request)
{
$request->session()->put('select_plan_token', 'value');
return redirect('/signup/tos');
}
Now in signupController tos function you can always check the session value and manipulate the data accordingly
public function tos()
{
$value = $request->session()->get('select_plan_token');
// to your manipulation or show the view.
}
Now if the user is registered and you don't need the session value you can delete by following:
public function registered()
{
$request->session()->forget('select_plan_token');
// Return welcome screen or dashboard..
}
This method will delete the data from session. You can manipulate this. You won't be able to use in tos function as you are refreshing the page and you want data to persist. So its better to have it removed when the final step or the nextstep is carried out. Hope this helps.
Note: This is just the reference please go through the docs for more information and implement accordingly.

How to validate a parameter for a class within a method and prevent use if invalid?

I am building a small class to handle api requests and I am running into an issue with error handling (I am also a novice at OOP so please with me) I need to restrict or throw an error with any methods in my class that require the user parameter to be set and I also need to samething if token has not been retreived and I can't seem to wrap my head around it.
This is what I have so far...
$user array is set in a config file outside of class like so (empty by default):
$user = array(
'user_email' = '',
'user_pass' = ''
);
Class for handling API (simplified for question)
class eventAPI {
private $user
private $token
public function __construct($user) {
$this->user = $user;
// if possible assign token when instantiated
$this->retrieve_token($user);
}
private function retreive_token($user) {
// Check if user parameter has been set
if($this->validate_user_parameter()) {
// use credentials to make HTTP request for token
$token = 'somerandomtoken';
// assign token property retreived value
$this->token = $token;
} else {
echo 'User parameter has not been set.' // Not real message just for testing
return FALSE;
}
}
public function show_all_events() {
// Check if token has been retreived
if($this->validate_token_retreived()) {
// Use token to retreive events list via HTTP request
} else {
echo 'API not active. No valid token detected'; // for testing purposes
return FALSE
}
}
// reduntant code... Can't wrap my head around another way for checking for token.
public function show_single_event() {
// Check if token has been retreived
if($this->validate_token_retreived()) {
// Use token to retreive events list via HTTP request
} else {
echo 'API not active. No valid token detected'; // for testing purposes
return FALSE
}
}
// This is mostly where I am confused how to solve.
private function validate_user_parameter() {
foreach($this->user as $key => $value) {
// Remove whitespace from value
$value = trim($value);
if(empty($value)) {
echo 'User credentials have not been set'; // for testing purposes
return FALSE;
}
}
}
private function validate_token_retreived() {
$result = FALSE;
// Bool value not sure if this is the best way to do this
if(isset($this->$token)) {
$result = TRUE;
}
return $result;
}
}
First issue: I need to validate the user parameter which is in an array so I can use with a private method to retrieve the token. I chose to use a foreach loop to check each value but it seems a little archaic.
Second Issue: I have a redundant check in place for each public method to check if token is valid. Is there a better way to do this with OOP? I have many methods that require the token.
In short, how can I make sure that once the class is instantiated a public method that will be used by end user will not fire if any validation fails. The user info only needs to be valid once when instantiated and then the token needs to be valid for most remaining methods.
You don't need to pass $user parameter to retreive_token function. You got it in class scope. Just use $this->user in the function to access it. Also you didn't use it in that function, so why u passed it?
You didn't send true in any function.
There's nothing wrong with for-each but you want to check array_map too. Atleast you're applying a function to every item in array. It can be usefull. ps: seems for-each still faster then array_map
Also you would want to check empty function on which cases it returns false
You can use multiple returns in a function. You dont need to set a variable to do that.
Example
private function validate_token_retreived()
{
if(isset($this->token))
return true;
return false;
}
You couldn't use else in most cases.
Example
public function show_all_events()
{
if($this->validate_token_retreived()) {
// Use token to retreive events list via HTTP request
// and return here
}
echo 'API not active. No valid token detected'; // for testing purposes
return FALSE; // do you really return here? seems you are just generating an output
}

Laravel - return a redirectResponse selectively generated in a function

Part of my application is a multi-stage checkout process; during the latter pages of this I first run a sanity check on each request to verify the user actually has some items in their basket: if not they're sent back to the beginning.
I have a controller function like this which is called from multiple routes for DRY purposes.
private function checkBasketFull($request)
{
if (self::isBasketEmpty($request)) {
return redirect('/')->with('status', config('app.empty_basket_message'));
}
}
When I call it, I can't just do:
self::checkBasketFull($request);
because without a return the redirect doesn't fire, only the session data is sent.
And I can't do:
return self::checkBasketFull($request);
because that will give an error if there's no redirect or abort the method if checkBasketFull returns anything else.
My current (working) code is:
$check = self::checkBasketFull($request);
if ($check) {
return $check;
}
Is there an alternative way of writing this on a single line, or modifying the checkBasketFull function, so the redirect will occur if the basket is empty but execution will continue as normal if it isn't?
Either use this:
if ($redirect = self::checkBasketFull($request)) return $redirect;
Or throw an error and catch it in the global error handler.
However, instead of returning and checking that for a redirect like that, I'd much rather keep it as two completely separate methods:
public function someRoute(Request $request)
{
if ($this->isBasketEmpty($request)) return $this->redirectBasketEmpty();
// Continue processing this request...
}
protected function isBasketEmpty(request)
{
// run your login here...
}
protected function redirectBasketEmpty()
{
return redirect('/')->with('status', config('app.empty_basket_message'));
}
Feels cleaner to me.

Laravel redirect from private method with errors

I have the following code:
public function store(Request $request)
{
$this->validateData($request->all());
// store something
return redirect()->action('controller#index')->withMessage( 'Saved Successfully' );
}
private function validateData($requestParams)
{
try
{
$validator->validate( $requestParams );
}
catch ( ValidationException $e )
{
redirect()->action('controller#create')->withInput()->withErrors( $e->get_errors() )->send();
exit(); // this causes the withErrors to not be there
}
}
If I remove the exit();, the error messages will appear, but also the store function will be executed (see // store something). I know I can rewrite my code like:
if($this->validateData($request->all()))
{
// store something
return redirect()->action('controller#index')->withMessage( 'Saved Successfully' );
}
But I don't want the ugly if statement here. There must be a way to redirect with the flash messages without it.
tl;dr
Update your private method code like this to make the redirection work with $errors variable visible:
private function validateData($requestParams)
{
try
{
$validator->validate( $requestParams );
}
catch ( ValidationException $e )
{
$resp = redirect()->action('WelcomeController#index')->withInput()->withErrors($e->get_errors());
\Session::driver()->save();
$resp->send();
exit();
}
}
explaination
When exiting in the middle of your controller, there are some job which is executed in the application termination will not be execute anymore. In your case, the Session middleware terminate method will not be called. Let see its content (ref):
public function terminate($request, $response)
{
if ($this->sessionHandled && $this->sessionConfigured() && ! $this->usingCookieSessions())
{
$this->manager->driver()->save();
}
}
Now, look at the save method of our Session driver (ref)
public function save()
{
$this->addBagDataToSession();
$this->ageFlashData();
$this->handler->write($this->getId(), $this->prepareForStorage(serialize($this->attributes)));
$this->started = false;
}
As you can see, your flash data is only be saved when the Session middleware terminates successfully. With your old code, the flash data will be lost!
What I do with my code is calling the save method manually before sending our response to the browser. However, I still recommend you bring the redirection to the public controller method.
Well I don't see any problem using the if statement there. Basically you do not stop the code execution, so thats why the store function is executed, even if your validation fails. The redirect function just sends a header with the redirect location, it does not abort the code after it to be executed. It works with exit(), because it sends the redirect headers and stop the rest of the code to be exeuted.
This is not ugly, it is clean and clear and I suggest you to use this. This is a good example of right if statement usage - if one conditions i met then do this. In your case if your validation passes, just store the object. (Just remember to modify your validate function to return true or false)
if($this->validateData($request->all()))
{
// store something
return redirect()->action('controller#index')->withMessage( 'Saved Successfully' );
}
The other possible solution is to use try .. catch block like this
public function store(Request $request)
{
try {
$this->validateData($request->all());
// store something
return redirect()->action('controller#index')->withMessage( 'Saved Successfully' );
} catch ( ValidationException $e ) {
return redirect()->action('controller#create')->withInput()->withErrors( $e->get_errors() );
}
}
private function validateData($requestParams)
{
// Your validation logic here
$validator->validate( $requestParams );
}
you just forgot to 'return' after the validation exception :D, then you would not have to 'exit;'

Categories