# Manage frontend user profiles from Twill
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:
# Create the profiles module
This module will be used to attach extra information to User
records:
php artisan twill:make:module Profiles
# Edit the migration
Update the generated migration to add the required fields:
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
class CreateProfilesTables extends Migration
{
public function up()
{
Schema::create('profiles', function (Blueprint $table) {
createDefaultTableFields($table);
$table->string('name', 200)->nullable();
$table->text('description')->nullable();
$table->boolean('is_vip')->default(false);
$table->foreignId('user_id')
->constrained()
->onUpdate('cascade')
->onDelete('cascade');
});
}
public function down()
{
Schema::dropIfExists('profiles');
}
}
Then, run the migration:
php artisan migrate
# Edit the Profile model
Edit the fillable fields to match the new schema and add the Profile > User
relationship:
<?php
namespace App\Models;
use A17\Twill\Models\Model;
class Profile extends Model
{
protected $fillable = [
'published',
'name',
'description',
'is_vip',
];
public function user()
{
return $this->belongsTo(User::class);
}
}
# Edit the User model
Define the User > Profile
relationship and 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.
Finally, define the name
attribute accessor. This will allow existing
Laravel Breeze code to access the user name from the attached profile:
<?php
namespace App\Models;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
class User extends Authenticatable
{
use HasFactory, Notifiable;
protected $fillable = [
'name',
'email',
'password',
];
protected $hidden = [
'password',
'remember_token',
];
protected $casts = [
'email_verified_at' => 'datetime',
];
public function profile()
{
return $this->hasOne(Profile::class);
}
protected static function booted()
{
static::created(function ($user) {
$profile = Profile::make();
$profile->name = $user->name;
$profile->user_id = $user->id;
$profile->save();
$user->name = '';
$user->save();
});
}
public function getNameAttribute()
{
return $this->profile->name;
}
}
# Edit ProfileController
Define our custom name
column to be used instead of the default title
and
prevent administrators from creating and deleting profiles in the CMS
<?php
namespace App\Http\Controllers\Admin;
use A17\Twill\Http\Controllers\Admin\ModuleController;
class ProfileController extends ModuleController
{
protected $moduleName = 'profiles';
protected $titleColumnKey = 'name';
protected $indexOptions = [
'create' => false,
'delete' => false,
];
}
# Edit the profile form
@extends('twill::layouts.form')
@section('contentFields')
@formField('input', [
'type' => 'textarea',
'name' => 'description',
'label' => 'Description',
'maxlength' => 1000,
])
@formField('checkbox', [
'name' => 'is_vip',
'label' => 'Can access all VIP content',
])
@stop
# Edit ProfileRequest
<?php
namespace App\Http\Requests\Admin;
use A17\Twill\Http\Requests\Admin\Request;
class ProfileRequest extends Request
{
public function rulesForCreate()
{
return [];
}
public function rulesForUpdate()
{
return [
'name' => 'required'
];
}
}
# Finishing touches
Add the module to your twill-navigation.php
and to your admin.php
routes and you are done!
# Where to go from here?
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
.
# User approval & restricted content
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).
# Frontend profile editing
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.
# Complete user management from the CMS
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()
(opens new window), for user creationafterDelete()
(opens new window), for user deletion