4

I am currently working on a website with a lot a of table. Almost all of the table have filters, and since the user don't want to lose all of his filters when he reloads, I am saving the filter in the session.

So far, all of this is working, I run an ajax call everytime the filter changes to save the new filter in the session. My issue is when I try to clear the filters.

When the user clicks on the clear button or closes the last filter box, the session key is emptied, and it prints null, but when I reload the page, that last filters are loaded, and the session prints them as if I never removed them.

The function that I use to fill/empty the session:

public function addPersistenceAction(Request $request)
{
    $parameters = $request->request->all();
    $session = $this->get('session');
    $session->start();//I tried removing/adding this line but it didn't change anything

    //if the key wasn't send, nothing happends
    if (!isset($parameters['storage'])){
        return new JsonResponse(0);
    }

    //if no data was send, it removes the key. 
    if(!isset($parameters['data'])) {
        $session->remove($parameters['storage']);
        // I also tried setting an empty array but it didn't work either
        //$session->set($parameters['storage'], []);
        return new JsonResponse($session->all()); // this prints the correct data
    }

    //if the data was sent, it is set. This works perfectly
    $session->set(
        $parameters['storage'],
        $parameters['data']
    );

    return new JsonResponse($session->get($parameters['storage']))
}

The function always returns what I expect it to, but everytime I reload the page, the session still have the last filter. I have tried with different filters and it's always the last one so it can't have been harcoded in my controller.

Funny thing, I have noticed that if I manually run the function that gets the filter data before reloading the page, it shows me the right value, and if I reload after that, the filter are correctly emptied.

So my question: Is there a reason why my session seems to not be saved and is there a way to programatically "force" symfony to save the session data?

some usefull code:
The function that gets the session data:

/**
 * @param Request $request
 * @return JsonResponse
 */
public function getSessionDataAction(Request $request){
    $parameters = $request->request->all();
    $session = $this->get('session');
    $session->start();

    if (!empty($parameters['storage'])) {
        $data = $session->get($parameters['storage'])?:[];
        return new JsonResponse($data);
    }else{
        return new JsonResponse(array('status' => 'failed', 'message' => 'storage is mandatory'));
    }
}

My controller function:

/**
 * @param Request $request
 * @return Response
 */
public function indexAction(Request $request)
{
    $this->denyAccessUnlessGranted(RoleVoterHelper::SECTION_USER_VIEW);

    $session = $request->getSession();

    //I checked and the session key I use is not touched in this function
    $filterWidgets = $this->get('dmt.filter.manager')->getWidgetData('user_filter');

    if (!$this->get('dmt.role_voter')->getExtGranted(RoleVoterHelper::SECTION_USER_VIEW)) {
        $filterWidgets['company'] = $this->getDoctrine()->getRepository('BugTrackerModelBundle:Company')->findByAuthorities($this->getUser()->getAuthorities());
    }
    $authorities = $this->getDoctrine()->getRepository('BugTrackerModelBundle:Authority')->findAll();
    return $this->render('DMTBundle:User:index.html.twig', [
        'filter_widgets' => $filterWidgets,
        'usersColumns'   => $session->get('usersColumns'),
        'usersSort'      => $session->get('usersSort'),
        'isSuperAdmin'   => $this->isGranted(UserHelper::ROLE_SUPER_ADMIN),
        'authorities'     => $authorities,
    ]);
}

The javascript called when the page opens:

$.post(dependencies.bridgeGetUrl, {
    // something like "project_page_filter", the key for the session.
    storage : dependencies.storage
}).success(function(response){
    dependencies.filterManager.hook(function(app){
        app.scheme = response;
        app.readScheme();
    });
    run(dependencies);
    if(typeof dependencies.callback == "function"){
        dependencies.callback(dependencies.params);
    }
});

the javascript that sends any modification to the session:
App.scheme is always the current value of the filters

dependencies.filterManager.setLifecycle(["add", "change-value"], function(app) {
    $.post(dependencies.bridgeUrl, {
        storage : dependencies.storage,
        data : app.scheme
    });
}).setLifecycle(["remove-all", "remove"], function(app) {
    $.post(dependencies.bridgeUrl, {
        storage : dependencies.storage,
        data : app.scheme
    });

    $("#filterSubmit").click();
});
tftd
  • 16,203
  • 11
  • 62
  • 106
Liora Haydont
  • 1,252
  • 1
  • 12
  • 25
  • Please could you add the javascript that sends the ajax calls? – Philippe-B- Apr 28 '18 at 15:40
  • Symfony version? – Arleigh Hix Apr 28 '18 at 19:46
  • I use symfony 2.8. I don't have the js right now, I'll add it later, but I know my request are send because they are showed in the network tab of chrome's inspector – Liora Haydont Apr 28 '18 at 19:50
  • 1
    You are using `$this->get('session')` and `$request->getSession()` also? I would try with using the same approach both sides of the code – Tarun Lalwani Apr 29 '18 at 07:41
  • Do you use any "http caching" logic? Do you have FOSHttpCacheBundle installed or set http cache header with a Listener? It could be that the clear request is cached by the browser, meaning it was already cleared in the past and the 2nd time it returns the cached response without actually making a request. – Jannes Botis Apr 29 '18 at 21:48
  • 1
    @TarunLalwani Both methods return the same object. – Philippe-B- Apr 30 '18 at 09:48
  • I know that, but one solution mentioned to use `$request->getSession()`, thats why I wanted you to give it a shot – Tarun Lalwani Apr 30 '18 at 09:49
  • @LioraHaydont It's not to know _if_ it's sent, but _what_ and _how_. ;) – Philippe-B- Apr 30 '18 at 09:56
  • @Philippe-B- I added the js, le me know if you need more code. – Liora Haydont Apr 30 '18 at 13:37
  • @TarunLalwani I tried changing to `$this->get('session')` everywhere but it didn't change anything. – Liora Haydont Apr 30 '18 at 13:37
  • 1
    Possible to share a minimal reproduce example? This may need debugging the symfony code itself – Tarun Lalwani Apr 30 '18 at 13:42
  • @JannesBotis I don't use any http caching logic. The filters are always loaded via js, to make sure it's not reloading the cached data, and since the get function doesn't return the same thing in the 1st and second loading I don't think it's cached – Liora Haydont Apr 30 '18 at 13:45
  • @TarunLalwani humm well symfony is a pretty bug framework, and this is a really big project, I can add the part of the view that calles the js and it should be runnable, but you'd still have to install and setup symfony – Liora Haydont Apr 30 '18 at 13:48
  • If you pack it in a single page simple project which reproduce the issue, I might be able to help – Tarun Lalwani Apr 30 '18 at 13:49
  • @LioraHaydont which browser are you testing? It can be that either addPersistent or get routes are cached. If it is not much effort, can you check if your requests are cached, see https://stackoverflow.com/questions/13140318/check-whether-network-response-is-coming-from-server-or-chrome-cache . Also note that post requests can also be cached occasionally: https://stackoverflow.com/a/14255492/4448410 – Jannes Botis Apr 30 '18 at 14:42
  • @JannesBotis I use chrome,on windows. The disable cache checkbox is also checked, and the request take long enough for me to be sure it is not cached. – Liora Haydont Apr 30 '18 at 14:54
  • @LioraHaydont Tanks for the code. Would it be possible for you to add a console log of the data sent please? – Philippe-B- Apr 30 '18 at 14:56
  • @LioraHaydont can you add the cookie settings in the config? More important, can you add a screenshot of the cookie under chrome developer tools(Name, domain, path, httpOnly options etc)? Although I have no idea if this will help. Try printing the session id for all requests, maybe in a response header, eg header('test-session-id: ' . $session->getId()); – Jannes Botis Apr 30 '18 at 17:03
  • Try force saving the session with `$session->save()` before the `return` in your `addPersistenceAction` function. Other than that I don't believe we will be able to easily "guess" what's wrong here without a re-producible example. I see that you are trying to `$session->start()` which doesn't make sense to me, because usually you would have `session.auto_start = 1` in your `php.ini` which should be starting the session for you. The only other thing I can think of is read/write permission issues in the path where the session is saved, but that doesn't look like the issue here. – tftd May 01 '18 at 12:59
  • p.s. Symfony is quite bug free framework. They have tests coverage for pretty much everything so I highly doubt it is a Symfony bug but rather a misconfiguration or misusage. – tftd May 01 '18 at 13:01
  • I don't think it's a symfony bug either but I haven't work with symfony's sessions enough to know what could make a session revert/no persist a change. I tried making a reproductible example but once I had removed everything superfluous the example worked as expected – Liora Haydont May 01 '18 at 13:31
  • Good news! Would you mind posting the working example as an answer? That might help people facing the same kind of issue. – Philippe-B- May 01 '18 at 14:12
  • Well it doesn't really resolve my issue since I still don't know what is preventing/reverting the save of my session. I'm trying to add code until I find what part is causing trouble – Liora Haydont May 01 '18 at 15:10
  • I bet it won't take long. :) Wish I could help. – Philippe-B- May 01 '18 at 15:33

0 Answers0