# 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: