Having issues with user:create:after hook and actual class of user

hello everyone,

i am having some issues with this hook. what i am trying to do:

  • i create a user programatically
  • after the creation i want to call the update function so even empty fields are created in the content file, for instance for when the user gets exported in a CSV file these empty fields are also available
  • in the update function i also manipulate the data a bit, so i created an extra class/model for my user

this is my code

class MemberUser extends User
{
    public function update(array $input = null, string $languageCode = null, bool $validate = false): static
    {
        kirbylog(get_class($this)); // this gives me MemberUser

       // ... here i manipulate a bit the $input array

        return parent::update($input);
    }
}

in my plugin i add this model of course

'userModels' => [
        'member' => MemberUser::class
],

My hook looks like this

'user.create:after' => function ($user) {
           
            if ($user->role() == 'member') { // this if is irrelevant, just to filter all other user roles out so they skip this whole thing
                kirbylog(get_class($user)); // this gives me only Kirby\Cms\User
                // to create all fields, also empty ones, and do the input manipulations
                $saveduser = $user->update();
            }
}

as you can see i am logging the class of my user using kirbylog(). in the model the class output is MemberUser. in the create:after hook its only User though, which means my overwritten update() is not getting called.

by the way, if i kirbylog() the class in a user:update:after hook, it also gives me MemberUser.

'user.update:after' => function (Kirby\Cms\User $newUser, Kirby\Cms\User $oldUser) {
      kirbylog(get_class($newUser)); // this also gives me MemberUser
 },

someone any ideas? :-/

Hm, what if you add a create method inside your model, does that return a member user then?

But: why don’t you do this manipulation and field generation stuff right when creating the user? IMO, it doesn’t make sense to create the user and then do an update in a hook.

hello sonja,

well yes, that is what i am doing now. but then if i need an extra manipulation i need 2 parts of code that i have to change, one before the user gets created, and one inside the update() function of the model (i have some hidden fields that i have to keep updating every time the user is saved, for instance). so technically i have it working as i need it, but again, i have redundancy and i wanted to solve it in the update() together.

Hm, what if you add a create method inside your model, does that return a member user then?

of course! i didnt think of that, that might do the trick. will give it a try now.

EDIT: hmm i just realised… the method create() does not exist in the user model itself, it comes from $users (collection). so i am a bit confused on how to do it.

EDIT 2:

btw i am creating the user like this

$user = $kirby->users()->create([
            'email' => $data['email'],
            'role' => 'member',
            'language' => 'en',
            'name' => $data['first-name'] . ' ' . $data['last-name'],
            'content' => $createdContent // this is just a bunch of fields from the frontend form
]);

so somehow, if i understand the problem correctly, 'role' => 'member' is not making my user instantly have the class MemberUser. can i use something like this maybe? just because pages have the model attribute…

$user = $kirby->users()->create([
            'email' => $data['email'],
            'role' => 'member',
            'model' => 'MemberUser', // <-- like this?
            'language' => 'en',
            'name' => $data['first-name'] . ' ' . $data['last-name'],
            'content' => $createdContent // this is just a bunch of fields from the frontend form
]);

@texnixe dear sonja, i got it working, this did the trick

$user = $kirby->users()->create([
            'email' => $data['email'],
            'role' => 'member',
            'model' => 'member', // <--
            'language' => 'en',
            'name' => $data['first-name'] . ' ' . $data['last-name'],
            'content' => $createdContent // this is just a bunch of fields from the frontend form
]);

now i am inside the actual update function of the model :slight_smile: