Cake 3: Remember request data then authenticating a user

Hi all,

I wonder this isn’t a more frequently asked issue, but maybe I just use the wrong keywords and didn’t find the solution because of that. Anyway, here is my issue:

  1. I list a bunch of objects on my page together with a form and a “book now” button.
  2. Whenever someone want’s to book, the ID of the object will be passed together with the form to the controller action “a”
  3. Controller action “a” however, requires authentication for which I use the cake authentication component (very easy setup, it only checks if a user is logged in and in case he isn’t, he will be forwarded to the login page)
  4. Issue: Once a user has logged in, the request data as well as the session data is plain empty though, hence the object he wants to book can’t be identified in the follow up action anymore, it is completely lost.

Question: What is best practice to NOT LOSE form data when authenticating a user?

EDIT: I use form authentication and session as storage.

Thanks,
Christian

handling login redirects changed in 3.4. What version are you speaking about?

Hi, it is 3.3.10. Cheers

There are many options.

  1. At your step #2 use http get method to store the booking form. In that case all information will be in the url. Than your login.ctp should start the login form like this.

    <?= $this->Form->create( 'Users', [ 'url' => [ 'controller' => 'Users', 'action' => 'login', 'redirect' => $this->request->getQuery('redirect') ] ] ) ?>
  2. If you do not want to put these information to the url you can store it in your databse or in a file. In this case you should add the id of the databse record, or the nam eof the file to the redirect call.

  3. There are other ways, like out all the infos into hidden inputs, etc, but I think the 1 or 2 serves the best. Also it worth to try to directly save it to the session, as it should not missed on authentication.

Hi,

Thanks for the ideas. GET doesn’t work since there is a textfield in the booking form which easily exceeds the max length of an URL.

Saving the data manually is another option, but since the redicrect to the login form happens automatically I wonder where in the controller this could happen?

Edit: just saw my typo in the initial question and corrected it, now my question makes more sense I think ;). The question is how not to lose the previously submitted data when authenticating a user (no matter if POST or GET).

Cheers

I think the best option would be to use the session. I have tested and it should not be missed.

In a controller what you can access without login:

    $this->request->session()->write([
        'Test.theme' => 'blue',
        'Test.language' => 'en',
    ]);

Than call an url for what is only accessible after login. You will be redirected to login. On login you will be redirected to the url what you called originally.

There you can access the session variables.

`debug($this->request->session()->read('Test'));`

So I confirm, that variables saved to session prior to login are still available after login.

So this really becomes black magic to me :astonished:

Now I save my request data in the beforeFilter() function:

   public function beforeFilter(Event $event)
    {
        if ($this->request->params['action'] == 'add') {
    	    $this->request->session()->write('Test1', $this->request->data);
    	    $this->request->session()->write('Test2', ['a' => 'b']);
    	    debug($this->request->session()->read());
        }

    parent::beforeFilter($event);
    $this->Auth->allow(['index']);
    }

and the debug at the end clearly shows it worked:

   [
    	'Config' => [
    		'time' => (int) 1492465181
    	],
    	'Test1' => [
    		'id' => '6',
    		'fee_id' => '18',
    		'paymentoption_id' => '1',
    		'messages' => [
    			'message' => 'test message'
    		]
    	],
    	'Test2' => [
    		'a' => 'b'
    	]
    ]

However, when I read the same session just after the authentication happened in the “add” action, the ‘Test’ key is there but empty.

public function add()
{
	debug($this->request->session()->read());
}

While the ‘Test2’ key is there!

[
        //....
	'Flash' => [],
	'Test1' => [],
	'Test2' => [
		'a' => 'b'
	]
]

The cakephp version is 3.3.10 btw. not 3.4 as I thought, post above is edited.

Test1 will be empty as it is overwritten on every add call with the request data. So when you call add it empties Test1 variable.

Hi there, thought yesterday already that I have an issue with the variables passed as reference. However, do have any idea how to solve this? I am a bit lost and missing some PHP experience.

Thanks

You would need to change this

to something lke this

if ($this->request->params['action'] == 'add' && isset($this->request->data['id'])) {

So you will save data to the session when the id is present it the request data.

1 Like

So this worked! Heaps of thanks for your help!!!

1 Like