Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Bug: Flashdata does not work properly #9505

Closed
neznaika0 opened this issue Apr 4, 2025 · 10 comments
Closed

Bug: Flashdata does not work properly #9505

neznaika0 opened this issue Apr 4, 2025 · 10 comments

Comments

@neznaika0
Copy link
Contributor

neznaika0 commented Apr 4, 2025

PHP Version

8.4

CodeIgniter4 Version

4.6

CodeIgniter4 Installation Method

Git

Which operating systems have you tested for this bug?

Linux

Which server did you use?

cli-server (PHP built-in webserver)

Database

No response

What happened?

I use HTMX. Let's say there is a navigation bar with XHR loading.

Home | Main | Acme

The pages inside have forms that show flashdata+form as a result:

if ($this->request->isHtmx()) {
  service('session')->setFlashdata('success', 'Updated!');
  return view_fragment(...); // michalsn htmx package
}

After the first sending, the session value is:

array (size=4)
  '__ci_last_regenerate' => int 1743794589
  '_ci_previous_url' => string 'http://localhost:8080/' (length=22)
  'success' => string 'Updated!' (length=8)
  '__ci_vars' => 
    array (size=1)
      'success' => string 'new' (length=3)

and I'm showing toasts:

<?php foreach ($flashes as $flashKey => $flashMessage): ?>
  <?= session()->getFlashdata($flashKey) ?>
<?php endforeach; ?>

After the second sending, the session value is:

array (size=4)
  '__ci_last_regenerate' => int 1743794590
  '_ci_previous_url' => string 'http://localhost:8080/' (length=22)
  'success' => string 'Updated!' (length=8)
  '__ci_vars' => 
    array (size=1)
      'success' => string 'old' (length=3)

and I'm showing toasts again. But this is incorrect, it should be a one-time use.

Steps to Reproduce

It is difficult to reproduce outside the project. Better ask clarifying questions.
In short, between two requests, flashdata is not cleaned after the first one.

Expected Output

Flashdata should be a one-time use.

Image

Anything else?

I looked at the code, I think there's a mistake. Flash data never has a timestamp (integer), only new or old. It seems that the code was originally copied from tempdata.

@neznaika0 neznaika0 added the bug Verified issues on the current code behavior or pull requests that will fix them label Apr 4, 2025
@michalsn
Copy link
Member

michalsn commented Apr 5, 2025

There is no issue - the flashdata code works as intended. Flashdata is designed for traditional request-response cycles and should be set before performing a redirect.

If you need something that will work better with htmx, you can check https://github.com/michalsn/codeigniter-htmx-alerts

@michalsn michalsn closed this as completed Apr 5, 2025
@michalsn michalsn removed the bug Verified issues on the current code behavior or pull requests that will fix them label Apr 5, 2025
@neznaika0
Copy link
Contributor Author

The issue with the flashdata type is open: string or int|string?

@neznaika0
Copy link
Contributor Author

Yes, I think I realized the mistake. Flashdata needs to be used for redirect, if toasts are shown immediately, then you need to add a template to the Response.

@michalsn
Copy link
Member

michalsn commented Apr 5, 2025

The issue with the flashdata type is open: string or int|string?

What exactly do you have in mind? Can you be more precise?

@neznaika0
Copy link
Contributor Author

&& ! is_int($_SESSION['__ci_vars'][$key])) ? $_SESSION[$key] : null;

Why is_int()?

@michalsn
Copy link
Member

michalsn commented Apr 5, 2025

Why is_int()?

This is how we determine the tempdata: https://codeigniter.com/user_guide/libraries/sessions.html#tempdata

@neznaika0
Copy link
Contributor Author

Hmm, flashdata = tempdata? Not obvious and not documented

@michalsn
Copy link
Member

michalsn commented Apr 6, 2025

No, flashdata and tempdata are different. The user guide clearly explains the distinction between them.
The only thing not documented is the technical implementation behind how they're handled, but we typically don't go into that level of detail anyway. Developers don’t need to know those internals to use either one correctly.

Feel free to send a PR if you think something is missing in the docs.

@neznaika0
Copy link
Contributor Author

I can't describe it correctly in English. My sentences in my native language sound different.

But example in controller:

  1. Go to http://localhost:8080/?mixed
  2. See result http://localhost:8080/?see

Flashdata is overwritten with tempdata. Therefore, the is_int() check is incorrect. And overwriting flashdata is not described in the documentation.

class Home extends Controller
{
    public function index(): string
    {
        // if (isset($_GET['flash'])) {
        //     session()->setFlashdata('_flash', 'It flash data.');
        // }

        // if (isset($_GET['temp'])) {
        //     session()->setTempdata('_temp', 'It temp data.', 60);
        // }

        if (isset($_GET['mixed'])) {
            session()->setFlashdata('_mixed', 'It flash data >> temp data.');
            session()->markAsTempdata('_mixed', 60);
        }

        if (isset($_GET['see'])) {
            // var_dump(session()->getFlashdata('_flash'));  // It flash data. Once
            // var_dump(session()->getTempdata('_temp')); // It temp data. 60 sec

            var_dump(session()->getFlashdata('_mixed')); // null
            var_dump(session()->getTempdata('_mixed'));  // It flash data >> temp data.
        }

        return view('welcome_message');
    }
}

@michalsn
Copy link
Member

michalsn commented Apr 6, 2025

Please read the user guide carefully: https://codeigniter.com/user_guide/libraries/sessions.html

Every aspect is documented - some highlights:

The get() method WILL return flashdata or tempdata items when retrieving a single item by key. It will not return flashdata or tempdata when grabbing all data from the session, however.

It should be noted that flashdata variables are regular session variables, managed inside the CodeIgniter session handler.

Similarly to flashdata, tempdata variables are managed internally by the CodeIgniter session handler.

All these have code examples that demonstrate the concept used. Flashdata is ordinary session data, but treated in a special way, just like tempdata. We can't provide an example for every scenario - especially the less likely ones.

Everything is working as expected.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants