Reload/Update kirby user object

My Kirby installation is fetching users form a sqlite database and i create a custom users object for those users and override the native account users.

If i do some updates to the database e.g. updating the users email or name, the kirby users object is not updated, because it is initiated via index.php and at this point the object has still the old state.

I do have to refresh the page once, so kirby is re-init the users object, and fetches the new values from the database.

Because i do a lot of stuff in the frontend with user updates, i need a way to re-init the kirby user object so i get the new values after doing some updates via e.g. forms. Right now i just do a simple header(“Refresh:1”); to geht the new values.

Is there a way to reload the kirby users object like $users->reload?

Are we talking frontend only in this case? I.e. you do a frontend form update and on the same page you want these updates to be reflected immediately?

Exactly. Not sure this is an issue with my setup or a general one.

I have a frontend user, and this user is updating some entries with a form post. if i log the user object after the post, there is still the old value in it. if i refresh again, the new value appears.

Could you post the code your are using to update the user information?

// change email 
    if (($user = $kirby->user()) && ($user->role()->id() === 'editor' || $user->role()->id() === 'admin')) {
        // current user id
        $useruuid = $kirby->user()->id();
        if ($kirby->request()->is('POST') and ($useruuid === get('sender') and get('yooh-settings-change-email'))) {
            // test form pot
            if (empty(get('websitePot-change-email')) === false) {
                go($page->url());
                exit;
            }
            try {
                //get form mail
                $email = get('email');
                if (V::email(esc($email))) {
                    $testEmail = $kirby->users()->findBy('email', esc($email));
                    if ($testEmail) {
                        $messageUserChangedEmailAddressError = "This E-Mail Address is taken by another user. Please use another E-Mail.";
                    } else {
                        Db::update(
                            'yooh_user',
                            [
                                'email' => $email,
                                'verified' => '0',
                            ],
                            'id == "' . esc($useruuid) . '" '
                        );
                        $messageUserChangedEmailAddress = "The E-Mail address has changed.";
                        header("Refresh:1");
                    }
                } else {
                    $messageUserChangedEmailAddressError = "Please use a valid E-Mail address.";
                }
            } catch (Exception $e) {
                $messageUserChangedEmailAddressError = "There was a problem. Please try again later.";
            }
        }
    }

return compact('messageUserChangedEmailAddress', 'messageUserChangedEmailAddressError');

It is a simple form, nothing special. this code is in the template controller and works as expected, beside the not updated user object.

what im not understand, the form post does refresh the page but not the user object. i have to reload manual or via the header hack.

The thing is that your are not returning the updated user but only update the database.

If you were updating a normal user, you would store the new user in a variable:

$user = $user->update();

You would have to do the same thing here, also I don’t see where you are returning the user to the template.

Maybe it’s because of the DB setup, but i can’t update the user object with,

$user = $user->update();

or

$user->changeEmail();

It looks like the user is imutable or the functions are not bindet to the DB user setup, but just to the default user object?

But you right, there is no return at all in my code :partying_face:. Because this is the only situation i need the updated state, i just return the new email to the frontend. The DB is up to date and if the user reloads or navigates the new user data is loaded anyway.

But how do you display the user then in your frontend?

$user = $kirby->user();
$currentEmail = $user->email();

in the frontend i display users data from the user object. as usual, if no update is going on.

if the controller return any changes after the form post, i replace $currentEmail with the value from the controller which is then just a string with the new email, but not the object state.

Hm, you don’t have a user class, do you, where you could redefine the way the user is stored, so that you could use $user->update()? I’m not really sure how it would work here, because your database update only return true or false and not a user object.

I did a second test environment with the same code but with native users inside the starterkit.

$user = $kirby->user();
$user->changeEmail($email);
$user = $user->update();

After form post, the user object is up to date and i can return the new user in the template, or just grab the new user object without returning it in the template, because $user is anyway updated because of the post page refresh. All fine.

The issue is the DB users setup. Because of overriding the original users, i guess i have no access to the kirby build in functions regarding user modification.

After all, when i think about this i guess it makes sense that the DB user object is not mutable via kirby build in functions, because of redundancy of two states.

We do have user models though: https://getkirby.com/docs/reference/plugins/extensions/user-models

So in theory should should be able to override the default user methods here and replace $user->update() etc. with the database operations.