This is a simple solution to allow site administrators to manage frontend user profiles from the CMS. It can be used as a starting point to implement a user approval workflow and content access restrictions.
Objectives:
- Add a
Profiles
section to the CMS for site administrators - Automatically create and assign
Profile
records to users upon registration
Requirements:
Versions used at the time of writing:
Version | |
---|---|
PHP | 7.4 |
Laravel | 8 |
Laravel Breeze | 1.3 |
Twill | 2.4 |
This module will be used to attach extra information to User
records:
php artisan twill:make:module profiles
Update the generated migration to add the required fields:
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
createDefaultTableFields($table);
// Rename the 'title' field to 'name'
$table->string('name', 200)->nullable();
// Keep the description
$table->text('description')->nullable();
// Example boolean field to allow access to special content
$table->boolean('is_vip')->default(false);
// Add a foreign key to the `users` table from Laravel Breeze
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
});
}
Then, run the migration:
php artisan migrate
Edit the fillable fields to match the new schema:
protected $fillable = [
'published',
'name',
'description',
'is_vip',
];
Then, define the Profile—User
relationship:
public function user()
{
return $this->belongsTo(User::class);
}
Define the User—Profile
relationship:
public function profile()
{
return $this->hasOne(Profile::class);
}
Use the model's booted()
method to hook into the created
event. When a user is created through the Laravel Breeze user registration form, automatically create and assign a Profile
record:
protected static function booted()
{
static::created(function ($user) {
// Create the user profile
$profile = Profile::make();
$profile->name = $user->name;
$profile->user_id = $user->id;
$profile->save();
// The `name` value is transferred to the `profile` record
$user->name = '';
$user->save();
});
}
Then, define the name
attribute accessor. This will allow existing Laravel Breeze code to access the user name from the attached profile:
public function getNameAttribute()
{
return $this->profile->name;
}
// Define our custom `name` column to be used instead of the default `title`
protected $titleColumnKey = 'name';
// Prevent administrators from creating and deleting profiles in the CMS
protected $indexOptions = [
'create' => false,
'delete' => false,
];
@section('contentFields')
@formField('input', [
'type' => 'textarea',
'name' => 'description',
'label' => 'Description',
'maxlength' => 1000,
])
@formField('checkbox', [
'name' => 'is_vip',
'label' => 'Can access all VIP content',
])
@stop
public function rulesForUpdate()
{
return ['name' => 'required'];
}
Add the module to your twill-navigation.php
and to your admin.php
routes — and you are done!
Site administrators now have access to a Profiles
section in the CMS, to edit basic user information.
Within your site's views and controllers, you can access the profile information for the current user via Auth::user()->profile
.
Upon registration, a user profile is created with a draft
status (ie. not published). This can be used to implement a user approval workflow:
@if (Auth::user()->profile->published)
{{-- Account has been approved, show the dashboard --}}
@else
{{-- Account has not yet been approved, show "pending approval" message --}}
@endif
The same technique also applies for granular access control (e.g. a VIP section with additional content).
A frontend form can be added to allow users to edit their descriptions. As always, make sure to sanitize user input before storing it in the database.
For simplicity, this implementation prevents site administrators from creating and deleting users from the CMS.
A few methods from ModuleRepository
can be extended in ProfileRepository
to implement the feature:
afterSave()
, for user creationafterDelete()
, for user deletion
Thanks for reading and have fun :)