Laravel 5.2 : Session values doesn't persist across different routes? - php

I'm using Laravel 5.2. (And i'm a new Laravel user)
I need to use Session. And of course, read the Session Values from different Routes/pages. Here is the simple concept, simply:
Save some session values from a route.
Retrieve the values from another different route.
Here's the code i used.
Route::get('write', function () {
session()->put('food', 'banana');
session()->save();
echo session()->get('food'); // <------ Shows: 'banana'
});
Route::get('read', function () {
echo session()->get('food'); // <------ Shows nothing*
});
What did i miss (or) what is the proper way to play with Sessions please?
Thanks all.

The reason is that session()->pull() actually pulls an element from the session and deletes it from session. So after /write called you'll have nothing in you session. That's why /read can not pull anything.
You should use session()->get('food') in your scenario instead of pull.
Also make sure that your routes use web middleware.
Route::group(['middleware' => ['web']], function () {
Route::get('write', function () {
session()->put('food', 'banana');
echo session()->get('food'); // <------ Shows: 'banana'
});
Route::get('read', function () {
echo session()->get('food'); // <------ Shows 'banana' too
});
});
Also check the official documentation for further read: https://laravel.com/docs/5.2/session.

use session()->save() after you put or modify something in it.
I usually do it via the facade Session::save();
If it isn't saved the session object wont know about it.

Related

Laravel 5.5 MDN Fetch API set session variable not working

I'm using Laravel 5.5
I am trying to set session variable on GET fetch('/ajax-get-save-session') request.
Route::get('/ajax-get-save-session', function() { session(['my_key', 'Saved Session']) });
And when I try to access the session variable my_key in different route.
Route::get('/access-session', function() { return session('my_key'); });
NULL value is returned.
This routes are registered on Laravel web.php and I'm using MDN fetch API
Anyone?
If i understand your problem. You are looking for this. Try this:-
Use Session; //if your are using laravel 5.2 then add in top in routes. php or laravel 5.2 > greater versions in web.php
// now put data in session
Route::get('/ajax-get-save-session', function() {
Session::put('my_key','Saved Session');
});
//Access the session
Route::get('/access-session', function() { echo Session::get('my_key') });
Hope it helps!
It's totally my mistake. I never thought fetch() API is the one causing my problem. It says the description
By default, fetch won't send or receive any cookies from the server, resulting in unauthenticated requests if the site relies on maintaining a user session (to send cookies, the credentials init option must be set).
By doing :
fetch(url, { credentials : 'include' }).then(response => response.json())
SOLVED MY PROBLEM!

I am trying to call a Controller Action using View::share

I'm trying to pass a variable to every view when a user is logged in, and I put the action in my routes.php file;
//functions only execute when the user is logged in
Route::group(array('before' => 'auth'), function(){
View::share('ctxr', 'user is authenticated');
});
I am currently using Laravel 4.2 and using a static variable the share function works as expected. If I call the {{ $ctxr }} from any partial or view, it displays correctly, but the problem is, when I have an action on the basecontroller and I'm thinking of doing something similar to this:
View::share('ctxr', BaseController#getStatistics);
Which returns the stats generated to every view. but I keep getting an error, please what is the best way to call controller functions from a View::share function. I am trying to avoid using sessions, since Laravel has made this available...
Thanks in anticipation.
The second parameter needs to be a string or an array. A callback function won't work, from what I can tell. But what you can do is assign the returned value to a variable and pass that along:
Route::group(array('before' => 'auth'), function(){
$bc = new BaseController();
$stats = $bc->getStatistics();
// Or if getStatistics is defined as a static function
$stats = BaseController::getStatistics();
View::share('ctxr', $stats);
});

Detect if action is show or edit in Laravel 5.2

I have a middleware that detects if a user owns a tournament.
So, if user want to edit a tournament he doesn't own, he will get a 403.
Thing is I can't make difference between laravel.dev/tournament/1/edit, and laravel.devl/tournament/1
Off course, I could check the "edit" word in URL, but I would prefer other better param...
I tried method param in Request Object, but it is giving me GET for both, so I can't make difference...
Any Idea???
In your case, you can do like this:
$request->route()->getName();
Now you can do your logic based on this.
What about using a different HTTP method for edit, e.g PATCH or PUT and declaring two different routes, something like:
Route::get('laravel.devl/tournament/1', 'TournamentController#showTournament');
Route::put('laravel.dev/tournament/1/edit', 'TournamentController#editTournament');
Then in the TournamentController you can check if the user has rights to edit.
It sounds like you should just use route specific middleware instead of global middleware. See https://laravel.com/docs/master/middleware#assigning-middleware-to-routes. Then you can just do:
Route::get('/tournament/{id}/edit', ['middleware' => ['tournamentOwner'], function () {
//
}]);
Route::get('/tournament/{id}', ['middleware' => [], function () {
//
}]);
If it's a RESTful route, you can just do:
public function __construct()
{
$this->middleware('tournamentOwner', ['only' => ['edit']]);
}

Laravel and routes with multiple "nested" tasks and parameters

I have just started tinkering with Laravel (PHP newbie alert) and I have a doubt on how to implement my REST JSON APIs on this framework.
The desired URL path should be:
http://api.mysite.com/APIKEY/FUNCTION/(ARGUMENTS)*
But what is the best way to do it?
I did not find any enough explanatory guide, because it is assumed that each feature (authentication, search, and so on) are on different routes.
At the moment I managed to create migrations and models for the needed data and I also set a route this way:
Route::get('/{apikey}/{function}/{arg1}/{arg2}/{arg3?}',
//The first two arguments are mandatory, the 3rd optional
function($apikey,$function,$arg1,$arg2)
{
return Response::json(array(
'status'=>'200'),
200);
})
->where(array('function'=>'[A-Za-z]+'));
This should be the correct action flow, but I have some doubts.
Check that apikey is valid, if not return a 404 json response. How do I call such function, where do I define it?
If key check is successful, understand which function is needed (should I use a switch construct or is there a better way to implement this, like a route group? In all examples with Route::group there is a static prefix, but here the prefix is apikey, a variable)
Return data - if available - getting it from the database. I suppose that for each function i should code a specific controller that gets data from the database using the Models.
#1. I think I'd probably use a route filter for this, like so:
Route::filter('apikey', function(){
if (Shared\API::checkIfKeyIsValid(Input::get('key') != true){
return Shared\Errors::handleError("bad-api-key");
}
});
You can see this filter checks to make sure some session variables are set and match, and if it returns ANYTHING, that's failing, and it won't send the user where the route normally goes. You'd call it in the route like so:
Route::get('play/{id}', array('before' => 'loggedin', 'uses' => 'ThingController#doThing'));
#2. I think a route group is how I'd structure this (if I understand what you're asking).
Edit: You've changed the question since I answered, regarding the prefix being a variable. I'd reorder your arguments so the API key is at the end, or you could take a look at this, which might do what you want: https://github.com/jasonlewis/enhanced-router
Route::group(array('prefix' => 'api'), function()
{
//the routes for all API calls
Route::group(array('prefix' => '/v1'), function()
{
//for version 1
Route::group(array('prefix' => '/thing', 'before' => 'loggedin'), function()
{
//for things only
Route::get('/getThing/{id}', 'APIController#getThing');
Route::get('/getDifferentThing/{id}/{aux}/{optional?}', 'APIController#getDifferentThing');
});
});
});
#3. The returning of the data should be done via your controller with the data coming from the model. Either return it as a view, or just return it as JSON like so:
return Response::json($data);

Accessing route::resource using https in Laravel 4

To force HTTPS on a named route, the Laravel docs say do the following:
Route::get('foo', array('https', function()
{
return 'Must be over HTTPS';
}));
Now, on my first Laravel app, I have been using resource controllers. I don't think I will be using them for my second app, going on what I have since read, but for now they sit happily in my router.php file.
I wanted to force the back office part of my app to use HTTPS. So, my opening gambit was as follows:
Route::resource('backoffice', array('https','BackofficeController'));
Laravel didn't like the array.
So, instead I thought I would try putting at the next parameter:
Route::resource('backoffice', 'BackofficeController', 'https'));
But the next parameter needs to be an array. I could find no documentation on this, but I converted it to array. It still didn't work.
Route::resource('backoffice', 'BackofficeController', array('https')));
I even tried:
Route::resource('backoffice', 'BackofficeController', array('https'=>true)));
However, that failed too. So, how do I force a resource to use https?
Route::filter('forceHttps', function($req){
if (! Request::secure()) {
return Redirect::secure(Request::getRequestUri());
}
});
Route::group(['before' => 'forceHttps'], function(){
Route::resource('backoffice', 'BackofficeController');
});
Assuming you have a filter function like the one Andreyco suggested, which seems fine, you could do something similar to this:
//Andreyco's filter
Route::filter('forceHttps', function($req){
if (! Request::secure()) {
return Redirect::secure(Request::getRequestUri());
}
});
//backoffice group routing
Route::group(array('prefix' => 'backoffice', 'before' => 'forceHttps'), function()
{
Route::any('/', 'App\Controllers\BOindexController#index');
Route::resource('otherBackOfficeURI', 'App\Controllers\OtherBOController');
//other routes & controllers here...
});
This way, everything starting with site.tld/backoffice will go through the https filter (and most probably through a isAdmin filter) and then check inner function route rules. I think this will be more convenient.

Categories