TIP: Use Markdown or, <pre> for multi line code blocks / <code> for inline code.
These forums are read-only and for archival purposes only!
Please join our new forums at discourse.kohanaframework.org
Kohana 3.3, Session does not working with AJAX
  • Hello,

    I have big problem with Session with AJAX. Let say I need to add same items to comparison using AJAX, but nothing is saved in Session when I want to display saved content. I am using native driver..

    Thank you for advise!

  • Hello @AndyBrandy, session should work fine with AJAX. Would you like to show us some code?

  • Hello Enov,

    sure, here is my code:

    public function action_add2compare() {
            if (!empty($_GET['id'])) {
                $_compare_ad_ids = (array) Session::instance()->get('compare_ad_ids');
                if (count($_compare_ad_ids) < (int) Kohana::$config->load('mko3ads.max_compare_ads')) {
                    $_compare_ad_ids[(int) $_GET['id']] = (int) $_GET['id'];
                    echo '<a href="' . Link::get_link(array('request' => 'ads/compare', 'absolute' => true)) . '" onclick="this.target=\'_blank\'">' . __('mko3ads.In comparison') . '</a>';
                } else {
                    echo '<a href="javascript:void(0);" class="add2compare" id="add2compare_' . $item->id . '">' . __('mko3ads.Compare') . '</a> | alert("' . __('mko3ads.Too many items in comparison') . '");';
                }
                Session::instance()->set('compare_ad_ids', $_compare_ad_ids);
            }
            $this->auto_render = FALSE;
            exit;
        }
    

    In jQuery I call function load with action add2compare():

    $(this).load('controller/add2compare?id=' + add2compare_id, function(data) {});
    

    Thanx

  • Session::instance()->get('compare_ad_ids') returns always NULL...

  • Hey @AndyBrandy,

    Kohana writes the session on shutdown. Since you are exiting before proper shutdown, data you set wont be saved.

    Cheers!

  • Hello Enov,

    thank you for explanation! I have missed this Kohana point.. Going to test :)

    Many thanks!

  • Hey @enov,

    it works perfectly now!

    Cheers!

  • Hey @enov,

    I do not know what happened, but it does not work.. I changed function to:

    public function action_add2compare() {
            if (!empty($_GET['id'])) {
    
                $_compare_ad_ids = (array) Session::instance()->get('compare_ad_ids');
    
                if (count($_compare_ad_ids) < (int) Kohana::$config->load('mko3ads.max_compare_ads')) {
                    $_compare_ad_ids[(int) $_GET['id']] = (int) $_GET['id'];
                    echo __('mko3ads.In comparison');
                } else {
                    echo __('mko3ads.Too many items in comparison');
                }
    
                Session::instance()->set('compare_ad_ids', $_compare_ad_ids);
            }
    
            $this->auto_render = FALSE;
            return TRUE;
        }
    

    Any sugestions?

  • Hmmm...

    Now it's tricky. Perhaps because you set auto_render to false? And then you have echo? Which is sending headers and contents and not allowing the Session to write?

    I suggest you try to Session::instance()->write() just after the Session::instance()->set(). Let us know :)

    Cheers!

  • Maybe moving set to where $_compare_ad_ids is actually changed would be better?

    public function action_add2compare() {
            if (!empty($_GET['id'])) {
    
                $_compare_ad_ids = (array) Session::instance()->get('compare_ad_ids');
    
                if (count($_compare_ad_ids) < (int) Kohana::$config->load('mko3ads.max_compare_ads')) {
                    $_compare_ad_ids[(int) $_GET['id']] = (int) $_GET['id'];
                    Session::instance()->set('compare_ad_ids', $_compare_ad_ids);
                    Session::instance()->write();
                    echo __('mko3ads.In comparison');
                } else {
                    echo __('mko3ads.Too many items in comparison');
                }
            }
            $this->auto_render = FALSE;
            return TRUE;
    }
    
  • Hi,

    does not help, I moved set up and added write without effect.. :(

  • Maybe browser caching issues? try with $_POST

    $(this).load('controller/add2compare', {id:add2compare_id}, function(data) {});
    
    public function action_add2compare() {
            if (!empty($_POST['id'])) {
    
                $_compare_ad_ids = (array) Session::instance()->get('compare_ad_ids');
    
                if (count($_compare_ad_ids) < (int) Kohana::$config->load('mko3ads.max_compare_ads')) {
                    $_compare_ad_ids[(int) $_POST['id']] = (int) $_POST['id'];
                    Session::instance()->set('compare_ad_ids', $_compare_ad_ids);
                    Session::instance()->write();
                    echo __('mko3ads.In comparison');
                } else {
                    echo __('mko3ads.Too many items in comparison');
                }
            }
            $this->auto_render = FALSE;
            return TRUE;
    }
    
  • I do not think so, ID is changing, but it is impossible to store the value for next usage.

    I have working solution witch $_SESSION, but I really wonder, why it does not work with Session::instance()...:

    public function action_add2compare() {
    
            if (!empty($_GET['id'])) {
    
                // Load IDS
                if (Request::initial()->is_ajax())
                    $_compare_ad_ids = (array) Arr::get($_SESSION, 'compare_ad_ids', array());
                else
                    $_compare_ad_ids = (array) Session::instance()->get('compare_ad_ids');
    
                if (count($_compare_ad_ids) < (int) Kohana::$config->load('mko3ads.max_compare_ads')) {
    
                    $_compare_ad_ids[(int) $_GET['id']] = (int) $_GET['id'];
    
                    // Set IDS
                    if (Request::initial()->is_ajax())
                        $_SESSION['compare_ad_ids'] = $_compare_ad_ids;
                    else
                        Session::instance()->set('compare_ad_ids', $_compare_ad_ids);
    
                    echo '<a href="' . Link::get_link(array('request' => 'ads/compare', 'absolute' => true)) . '" onclick="this.target=\'_blank\'">' . __('mko3ads.In comparison') . '</a> | ';
                } else {
                    echo '<a href="javascript:void(0);" class="add2compare" id="add2compare_' . $_GET['id'] . '">' . __('mko3ads.Compare') . '</a> | <script type="text/javascript">alert("' . __('mko3ads.Too many items in comparison') . '");</script>';
                }
            }
    
            $this->auto_render = FALSE;
    
            return TRUE;
        }
    

    but it also needs SESSION regenerate in bootstrap:

    if (strlen(session_id()) < 1) {
        session_start();
        session_regenerate_id();
    }
    
  • Well, now that you have a working solution, allow me, and excuse me, to comment on some things:

    • You should not use Controller_Template when you don't need to. The small tweaks in there might get on your way. You might want to move this action to another clean controller, that perhaps extends some home-made Controller_Ajax.
    • You should prefer $_POST over $_GET in this case, as $_GET is, by convention, idempotent.
    • Validate and throw HTTP exceptions on the top. It will save you from nested ifs, and you can send error messages to your jQuery request handler. like this:
    
        if (!Request::initial()->is_ajax())
            throw HTTP_Exception::factory(500, "No AJAX, no go.");
        if (empty($_POST['id']))
            throw HTTP_Exception::factory(500, "No id? Why is that?");
        if (count...)
           throw HTTP_Exception::factory(500, "Well, you got the point...");
    
        .... // ... and you will have less nesting here
    
    
    • Returning JSON and some jQuery DOM manipulation in that JS function might be better than HTML code in your controller.
    • Also a pure Javascript solution might be an alternative, like saving to global JS variable or to a cookie.

    Sorry if I made this long to read.

    Cheers!

  • Hello @enov,

    thank you for your advice, I welcome them anytime and allow me to improve my code :)

    • Controller_Template will change to Ajax
    • $_POST over $_GET - sure, you are right
    • HTTP exceptions - not sure if I want to use them everywhere, but definitely will consider them and their output as error messages or so..
    • returning JSON - I prefer use returning HTML, where full block of code is expected and no more JS actions needed - than I am able to re-use views, however in this example there is just echo
    • pure JS variable is not possible in this case, while on this page there is only saving to SESSION, and on another page are these data represented..

    You are welcome, please you can write posts as long as you feel to be helpful!

    Thank you!

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

In this Discussion