XF 2.0 "Persist" data across pages

AGPR

Active member
Hi,

I have a page which handles data of NON logged in users and I would like to pass that data to other pages in the background. I could use $_SESSION to achieve that but I'd like to use XF's built-in functionality, if such exists for this specific thing.

What is the proper way to achieve this in XF? From my tests, $this->session(); is not behaving as I want, unless I am missing something. The data does not persist once you leave the page on which it was initialised.

Thanks in advance.
 

Mike

XenForo developer
Staff member
The XF session system does this exact thing -- it's how we track someone as being logged in (primarily), but it is also used for guests (see things like registration).

If your data isn't persisting, then either it's not being set properly -- you can check that in the DB -- or your session isn't being maintained across page views. You can check that by looking at the browser dev tool's network pane to see if you're getting a different session on each page. If you are, then that would almost certainly be a reverse proxy IP issue.
 

AGPR

Active member
On page A (external page) I am using:

PHP:
$app = XF::setupApp('XF\Pub\App');
$session = $app->session();
$session->set("user_cup_selected","1");
When I vardump $session on Page A I can see it as set.

On page B(xenforo controller) I am using:
PHP:
$session = $this->session();
$cup_selected = $session->keyExists('user_cup_selected');  // or $session->get("user_cup_selected");
When I vardump $session on Page B it is not there.

I've checked Session ID and it's the same across all pages.
 
Last edited:

Mike

XenForo developer
Staff member
Oh, you're not building within the usual XF flow. I assumed you were using standard controllers in all cases.

You need to explicitly save the session at the end. (This is done for you if you "run" the app.) Strictly speaking, you also need to apply the session to the response in case there is a newly created session. See \XF\Pub\App::complete().
 

AGPR

Active member
heh yes, soon after my last post I realised I wasn't saving the session.

$session->save(); on the external page did the trick.

I will check also check \XF\Pub\App::complete() as you suggested.

Thanks
 

AGPR

Active member
Sorry for bringing this up again but upgrading to XF 2.1 broke my implementation. (was previously on 2.0.12).

Now this does not persist on other pages:

PHP:
$app = XF::setupApp('XF\Pub\App');
$session = $app->session();
$response = $app->response();
$session->set("timeout",time());
$app->complete($app->response());
I assume something has changed?
 

Mike

XenForo developer
Staff member
What broke? I don't believe 2.1 has changed anything in particular in this area that would affect that code.

We no longer save empty sessions to reduce the overall write load, though given that you're setting a value, that shouldn't be it.

Now that I think about it though, at a guess you had a bug that perhaps wasn't exposed as clearly before. If you are creating a new session for a user, you need to set the cookie on the response -- this is part of what passing the response into the complete() method is for. If you are using the response object directly (which is what this code expects), then it's done for you. Otherwise, you'll have to call getCookies() on the response and manually set any that we try to set for this request.
 

AGPR

Active member
What broke? I don't believe 2.1 has changed anything in particular in this area that would affect that code.

We no longer save empty sessions to reduce the overall write load, though given that you're setting a value, that shouldn't be it.

Now that I think about it though, at a guess you had a bug that perhaps wasn't exposed as clearly before. If you are creating a new session for a user, you need to set the cookie on the response -- this is part of what passing the response into the complete() method is for. If you are using the response object directly (which is what this code expects), then it's done for you. Otherwise, you'll have to call getCookies() on the response and manually set any that we try to set for this request.
Thanks for your reply.

By broke I mean that sessions set in external file A are not available in class on external page B which is using $session = $this->session();

It used to be ok before the upgrade.

I'll check again based on your input
 

AGPR

Active member
File A
PHP:
$app = XF::setupApp('XF\Pub\App');
$session = $app->session();
$response = $app->response();
$session->set("timeout",time());
$app->complete($app->response());
var_dump($app) // returns the correct full session data
File B
PHP:
namespace Text\Demo\Pub\Controller;

use XF\Pub\Controller\AbstractController;
use XF\App;

class fUser extends AbstractController
{
   public function actionIndex()
   {
    $session = $this->session();
    var_dump($session); // returns different (and much less) data than $session in external file A
    }
}
(Manually setting session variables ($_SESSION['test']) works)

The exact same code on XF2.0.12 works. What am I missing?

Edit: I added:
$session->save(); before app->complete() and it worked only once. All subsequent requests are still failing.
 
Last edited:

Mike

XenForo developer
Staff member
Your example isn't outputting the response anywhere, so you're not setting the session cookie for the user (which would have the session actually be associated with them).

The code you show here would only work if they already had a session allocated to them. If they hit file A only, then file B wouldn't have worked in 2.0 either. In 2.0, visiting the forum would always give a guest a session; 2.1 only gives them one if they actually need it.

Since I assume you're building your own response in the real application, you need to call getCookies() on the response object and then send any cookies that are sent. They are in the argument order for setcookie, so you can do that via call_user_func_array('setcookie', $cookie);
 

AGPR

Active member
I assume it's not normal for $app->response()->getCookies(); to be returning array(0) { } on page A?
 
Top