Assign role after registration

hi all, It's possibile to assign role after the registration? i've a custom register:
class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

}
class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

}
i would perform a $user->assignRole('agency'); how can i do that? thanks
Solution:
@ocram82 I just tried it myself, this worked for me ```php class CustomRegister extends Register {...
Jump to solution
67 Replies
Povilas K
Povilas K3mo ago
I would do it on the Eloquent level in the Model/Observer when creating a user, if that's a default role
Povilas K
Povilas K3mo ago
Just in your case, I guess, it should be a created() model in the booted() method, not creating()
toeknee
toeknee3mo ago
Povilas is right if you are also creating users programatically aswell. Else you can use afterCreate I beleive https://filamentphp.com/docs/2.x/admin/resources/creating-records#lifecycle-hooks
Povilas K
Povilas K3mo ago
@toeknee your link is to the 2.x version of the docs, just in case - the docs for v3: https://filamentphp.com/docs/3.x/panels/resources/creating-records#lifecycle-hooks
Povilas K
Povilas K3mo ago
not sure if there's a difference, though 🙂
toeknee
toeknee3mo ago
Thanks bud! I just quickly googled, should have checked
Povilas K
Povilas K3mo ago
yeah, I'm surprised how many times I google and end up on the page of the docs or plugin for v2, it's very easy to miss in a hurry
ocram82
ocram823mo ago
hi @PovilasKorop and thanks for solution. But in my case i have 2 kind of registration: one through api and one through Filament registration form. Based on which form the user use, i have to assign role. And that's make me stucked
Povilas K
Povilas K3mo ago
then probably afterCreate() is better for Filament suggested by @toeknee and for API you save the role in the API Controller or similar
ocram82
ocram823mo ago
yes in the API i don't have this problem because i've a controller and a action dedicated to. afterCreate() is very interesting....but where i have to put that method?
toeknee
toeknee3mo ago
I wonder if we should check if referrer is google redirect to v3 hehe The docs state for create resource, but I am assuming it should work with the register method. I'd need to code dive, but it would be the page where the creation happens as a function
toeknee
toeknee3mo ago
You are assigning a role, so you can't do it before create / mutating really. as you need to save to releationships. as I assume you are using a permisisons package. Or are you assigning a role to the user object? i.e. a column on the user table
Povilas K
Povilas K3mo ago
this is for general forms. For registration form actually it's better to look inside the source and choose which part to hook in, here: https://github.com/filamentphp/filament/blob/c7e3e1aacd640c1214b1c5798a91af29d7e938f5/packages/panels/src/Pages/Auth/Register.php#L83
GitHub
filament/packages/panels/src/Pages/Auth/Register.php at c7e3e1aacd6...
A collection of beautiful full-stack components for Laravel. The perfect starting point for your next app. Using Livewire, Alpine.js and Tailwind CSS. - filamentphp/filament
ocram82
ocram823mo ago
i'm using Spatie/Permission package
Povilas K
Povilas K3mo ago
1. Hook afterRegister? 2. Event (Registered) with Listener? 3. override handleRegistration method? I would probably go for no.3, personally (I feel I need to write a proper tutorial about it, adding to my to-do list)
ocram82
ocram823mo ago
Number 3 is the best in my case think
Povilas K
Povilas K3mo ago
though not 100% sure it would work, cause that method is a part of a transaction
toeknee
toeknee3mo ago
I was just going to say afterRegister
Povilas K
Povilas K3mo ago
but try it out
ocram82
ocram823mo ago
But for do that...should i create a method handleRegistration inside the class i posted above? where i have to put afterRegister ?
Povilas K
Povilas K3mo ago
Yes, exactly, copy the code from that method and then make changes
ocram82
ocram823mo ago
thanks very much igo to try now now my class looks like this:
<?php

namespace App\Filament\Agency\Pages\Auth;

use Filament\Forms\Form;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Auth\Register as BaseRegister;

class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('rag_sociale')
->label('Ragione sociale')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->asignRole('agency');
return $user;

}

}
<?php

namespace App\Filament\Agency\Pages\Auth;

use Filament\Forms\Form;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Auth\Register as BaseRegister;

class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('rag_sociale')
->label('Ragione sociale')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->asignRole('agency');
return $user;

}

}
but it don't work
toeknee
toeknee3mo ago
on the same page. So in the register class just add
protected function afterRegister(): void
{
dd('hit');
// Runs after the form fields are saved to the database.
}
protected function afterRegister(): void
{
dd('hit');
// Runs after the form fields are saved to the database.
}
ocram82
ocram823mo ago
ok going to try this here i need an istance of just created user
toeknee
toeknee3mo ago
dd($this->userModel);
dd($this->userModel);
Try the above or
dd($this->form->model);
dd($this->form->model);
ocram82
ocram823mo ago
go to try
toeknee
toeknee3mo ago
You can see the register method and the actions / hooks it calls and what it sets. You should be able to piece it together. vendor/filament/filament/src/Pages/Auth/Register.php
ocram82
ocram823mo ago
thanks you, later i try
Solution
Povilas K
Povilas K3mo ago
@ocram82 I just tried it myself, this worked for me
class CustomRegister extends Register
{
protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->assignRole('User');

return $user;
}
class CustomRegister extends Register
{
protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->assignRole('User');

return $user;
}
ocram82
ocram823mo ago
oh wow! thanks
Povilas K
Povilas K3mo ago
I see in your code you misspelled the method name $user->asignRole('agency'); Maybe asignRole is the reason?
ocram82
ocram823mo ago
now i'm going to try i'll try now. i'll give you a feedback soon It doesn't works...this is my class:
<?php

namespace App\Filament\Agency\Pages\Auth;

use Filament\Forms\Form;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Auth\Register as BaseRegister;

class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->assignRole('agency');

return $user;
}
}
<?php

namespace App\Filament\Agency\Pages\Auth;

use Filament\Forms\Form;
use Illuminate\Database\Eloquent\Model;
use Filament\Forms\Components\TextInput;
use Filament\Pages\Auth\Register as BaseRegister;

class Register extends BaseRegister
{
public function form(Form $form): Form
{
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
}

protected function handleRegistration(array $data): Model
{
$user = $this->getUserModel()::create($data);
$user->assignRole('agency');

return $user;
}
}
toeknee
toeknee3mo ago
What doesn't work?
ocram82
ocram823mo ago
maybe because @PovilasKorop posted a class
class CustomRegister extends Register
class CustomRegister extends Register
my class is:
class Register extends BaseRegister
class Register extends BaseRegister
?
toeknee
toeknee3mo ago
Possibly, why are you extending base over register?
ocram82
ocram823mo ago
i've made some modification to register form, i added company name where you put this code?
toeknee
toeknee3mo ago
You are using Register just aliased with: use Filament\Pages\Auth\Register as BaseRegister; What happens when you submit? do you hit the function.
Povilas K
Povilas K3mo ago
@ocram82 have you registered that class in the AdminPanelProvider?
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('admin')
->path('admin')
->login()
->registration(CustomRegister::class)
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('admin')
->path('admin')
->login()
->registration(CustomRegister::class)
ocram82
ocram823mo ago
yes. is called AgencyPanelProvider
...
use App\Filament\Agency\Pages\Auth\Register;
...


class AgencyPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('agency')
->path('agency')
->darkMode(false)
->login()
->registration(Register::class)
->emailVerification()
->passwordReset()
->profile()
...
...
use App\Filament\Agency\Pages\Auth\Register;
...


class AgencyPanelProvider extends PanelProvider
{
public function panel(Panel $panel): Panel
{
return $panel
->default()
->id('agency')
->path('agency')
->darkMode(false)
->login()
->registration(Register::class)
->emailVerification()
->passwordReset()
->profile()
...
if i put dd() inside
protected function handleRegistration(array $data): Model
{
dd('here!!!');
$user = $this->getUserModel()::create($data);
$user->assignRole('agency');

return $user;
}
protected function handleRegistration(array $data): Model
{
dd('here!!!');
$user = $this->getUserModel()::create($data);
$user->assignRole('agency');

return $user;
}
nothing happens
Povilas K
Povilas K3mo ago
ok weird, let's debug further... So by "doesn't work" you're saying it doesn't assign the role, so no new record in the "model_has_roles" DB table? Or it throws some kind of error? can you try to dd($this->getUserModel()) in that method? Hmmm... filament version?
ocram82
ocram823mo ago
no errors and no new record inside model_has_roles v3 i try now after the registration i obtain 403 Forbidden
toeknee
toeknee3mo ago
I would also test its being hit so
dd('hit');
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
dd('hit');
return $form
->schema([
TextInput::make('company_name')
->label('Company Name')
->required()
->maxLength(255),
$this->getEmailFormComponent(),
$this->getPasswordFormComponent(),
$this->getPasswordConfirmationFormComponent(),
]);
Which ensures the page is indeed hit prior to submission
ocram82
ocram823mo ago
yes this is hit
Povilas K
Povilas K3mo ago
version 3.what? apparently this was pushed only a few weeks ago
Povilas K
Povilas K3mo ago
GitHub
Update Register.php · filamentphp/filament@35edbd2
Updated the registration to handle relation data if user customize the form, also added the default hooks for is a user wants to manipulate the data it is possible to do so.
ocram82
ocram823mo ago
from my component.json => "filament/filament": "^3.2",
toeknee
toeknee3mo ago
Great spot Polvilas @ocram82 update filament to the latest with composer update/upgrade
Povilas K
Povilas K3mo ago
php artisan about ? mine says v3.2.63
ocram82
ocram823mo ago
No description
ocram82
ocram823mo ago
oh my god....upgrading give the solution?
Povilas K
Povilas K3mo ago
yup, upgrade
No description
ocram82
ocram823mo ago
oh my god. try now php artisan composer upgrade is correct?
Povilas K
Povilas K3mo ago
no no
ocram82
ocram823mo ago
composer update ? sorry ignore the previous message
Povilas K
Povilas K3mo ago
I would limit to "composer update filamentphp/filament" thinking about it... that handleRegistration() method existed even before this change, it just wasn't called in the same way, so... fingers crossed but not 100% guarantee
ocram82
ocram823mo ago
oh my god! @PovilasKorop you save my day. thank you very much! Apart from the fact that I follow you on your YouTube channel, you just was a kind of hero for me...now much more! 😁 @toeknee thanks a lot you too!! you're very very helpful
Povilas K
Povilas K3mo ago
awwww 🙂 teamwork @toeknee !
toeknee
toeknee3mo ago
making the dream work
ocram82
ocram823mo ago
great both
Garadit
Garadit3mo ago
Sorry in advance, is this method possible for hasOne relationships? I used fieldset, but after trying it, the relationship data is not saved. Can we save the main data with handleRegistration and then the relationship data afterwards?
Garadit
Garadit3mo ago
I'm using this code to create a fieldset
No description
Povilas K
Povilas K3mo ago
Not sure about "afterwards", where exactly? Why not handleRegistration?
Garadit
Garadit3mo ago
I want to use a fieldset to handle the hasOne relation 'userDetail'. Referring to the latest release, I thought this would be supported by default since $this->form->model($user)->saveRelationships(); is there by default now. But it doesn't work in my case. I don't know if I did it right or not. Someone has asked this kind of question before, but with another version and it is not compatible with the latest version. https://discord.com/channels/883083792112300104/1222497096817447022 Here's the full code I wrote for the custom Regiter.php, wondering what went wrong: https://gist.github.com/TegarAditya/d236edbbf94fd3a8b7fffb5aeedff43d So I will probably use handleRegistration for this. But is that a good idea or a bad practice?
Gist
Custom Register with HasOne relationship
Custom Register with HasOne relationship. GitHub Gist: instantly share code, notes, and snippets.
Garadit
Garadit3mo ago
My bad, I forgot to add a model. I'll probably open a new thread related to this.