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:
Profiles
section to the CMS for site administratorsProfile
records to users upon
registrationRequirements:
This module will be used to attach extra information to User
records:
1php artisan twill:make:module Profiles
Update the generated migration to add the required fields:
File:
database/migrations/2021_08_01_204153_create_profiles_tables.php
1<?php 2 3use Illuminate\Database\Migrations\Migration; 4use Illuminate\Database\Schema\Blueprint; 5 6return new class extends Migration 7{ 8 public function up() 9 {10 Schema::create('profiles', function (Blueprint $table) {11 createDefaultTableFields($table);12 13 $table->string('name', 200)->nullable();14 15 $table->text('description')->nullable();16 17 $table->boolean('is_vip')->default(false);18 19 $table->foreignId('user_id')20 ->constrained()21 ->onUpdate('cascade')22 ->onDelete('cascade');23 });24 }25 26 public function down()27 {28 Schema::dropIfExists('profiles');29 }30};
Then, run the migration:
1php artisan migrate
Edit the fillable fields to match the new schema and add the Profile > User
relationship:
File:
resources/views/admin/repeaters/tasks.blade.php
1<?php 2 3namespace App\Models; 4 5use A17\Twill\Models\Model; 6 7class Profile extends Model 8{ 9 protected $fillable = [10 'published',11 'name',12 'description',13 'is_vip',14 ];15 16 public function user()17 {18 return $this->belongsTo(User::class);19 }20}
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:
File:
app/Models/User.php
1<?php 2 3namespace App\Models; 4 5use Illuminate\Contracts\Auth\MustVerifyEmail;
6use Illuminate\Database\Eloquent\Factories\HasFactory; 7use Illuminate\Foundation\Auth\User as Authenticatable; 8use Illuminate\Notifications\Notifiable; 9 10class User extends Authenticatable11{12 use HasFactory, Notifiable;13 14 protected $fillable = [
15 'name',16 'email',17 'password',18 ];19 20 protected $hidden = [
21 'password',22 'remember_token',23 ];24 25 protected $casts = [
26 'email_verified_at' => 'datetime',27 ];28 29 public function profile()30 {31 return $this->hasOne(Profile::class);32 }33 34 protected static function booted()35 {36 static::created(function ($user) {37 $profile = Profile::make();38 $profile->name = $user->name;39 $profile->user_id = $user->id;40 $profile->save();41 42 $user->name = '';43 $user->save();44 });45 }46 47 public function getNameAttribute()48 {49 return $this->profile->name;50 }51}
Define our custom name
column to be used instead of the default title
and
prevent administrators from creating and deleting profiles in the CMS
File:
app/Http/Controllers/Twill/ProfileController.php
1<?php 2 3namespace App\Http\Controllers\Admin; 4 5use A17\Twill\Http\Controllers\Admin\ModuleController; 6 7class ProfileController extends ModuleController 8{ 9 protected $moduleName = 'profiles';10 11 protected $titleColumnKey = 'name';12 13 protected $indexOptions = [14 'create' => false,15 'delete' => false,16 ];17}
File:
resources/views/twill/profiles/form.blade.php
1@extends('twill::layouts.form') 2 3@section('contentFields') 4 <x-twill::input 5 type="textarea" 6 name="description" 7 label="Description" 8 :maxlength="1000" 9 />10 11 <x-twill::checkbox 12 name="is_vip"13 label="Can access all VIP content"14 />15@stop
File:
app/Http/Requests/Twill/ProfileRequest.php
1<?php 2 3namespace App\Http\Requests\Admin; 4 5use A17\Twill\Http\Requests\Admin\Request; 6 7class ProfileRequest extends Request 8{ 9 public function rulesForCreate()
10 {11 return [];12 }13 14 public function rulesForUpdate()15 {16 return [17 'name' => 'required'18 ];19 }20}
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:
1@if (Auth::user()->profile->published)2{{-- Account has been approved, show the dashboard --}}3@else4{{-- Account has not yet been approved, show "pending approval" message --}}5@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