Laravel 11 Workgroup: Creating Collaborative Environments (Linked By Email)
that caters for different project requirements, communication styles, and workflow preferences.
[0] Create Laravel project with Auth API
Follow the previous article, or download a quick start project.
[1] Create migration
Run Artisan command:
php artisan make:migration create_workgroups_table
Edit the migration file.
(file → database\migrations\yyyy_mm_dd_hhmmss_create_workgroups_table.php)
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateWorkgroupsTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('workgroups', function (Blueprint $table) {
$table->id();
$table->string('name');
$table->string('refr');
$table->text('desc');
$table->string('locn');
$table->integer('estartdate');
$table->string('key1');
$table->string('key2');
$table->string('key3');
$table->string('key4');
$table->string('key5');
$table->integer('n');
$table->integer('admn');
$table->integer('cord');
$table->integer('oper');
$table->integer('mngr');
$table->string('mngr_email');
$table->timestamps();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('workgroups');
}
}
Create Workgroup model.
php artisan make:model Workgroup
Edit Workgroup model.
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
class Workgroup extends Model
{
use HasFactory;
protected $fillable = [
'name',
'refr',
'desc',
'locn',
'estartdate',
'key1',
'key2',
'key3',
'key4',
'key5',
'n',
'admn',
'cord',
'oper',
'mngr',
'mngr_email',
];
}
Run Artisan command to perform migration.
php artisan migrate
[2] Create Web Controller
Create controller script file
php artisan make:controller WorkgroupsController
Edit controller script file.
(file → app\Http\Controllers\WorkgroupsController.php)
<?php
namespace App\Http\Controllers;
use App\Models\Workgroup;
use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
class WorkgroupsController extends Controller
{
public function index()
{
$user = Auth::user();
$workgroups = Workgroup::where('mngr_email', $user->email)
->get();
return view('workgroups.index', [
'workgroups' => $workgroups,
]);
}
public function store(Request $request)
{
$validatedData = $request->validate([
'name' => 'required|string|max:255',
'refr' => 'required|string',
'desc' => 'required|string',
'locn' => 'required|string',
'estartdate' => 'required|integer',
'key1' => 'required|string',
'key2' => 'required|string',
'key3' => 'required|string',
'key4' => 'required|string',
'key5' => 'required|string',
'n' => 'required|integer',
]);
$user = Auth::user();
$workgroup = Workgroup::create([
'mngr_email' => $user->email,
'name' => $validatedData['name'],
'refr' => $validatedData['refr'],
'desc' => $validatedData['desc'],
'locn' => $validatedData['locn'],
'estartdate' => $validatedData['estartdate'],
'key1' => $validatedData['key1'],
'key2' => $validatedData['key2'],
'key3' => $validatedData['key3'],
'key4' => $validatedData['key4'],
'key5' => $validatedData['key5'],
'admn' => 0,
'cord' => 0,
'oper' => 0,
'mngr' => $user->id,
'n' => $validatedData['n'],
]);
return redirect()->route('workgroups.index')
->with('success', 'Workgroup created successfully.');
}
}
[3] Create Web View
This step assumes that you have integrated Breeze into your system. Refer to Blade Templates guide for more information about the package.
Edit workgroups.index:
(file → resources\views\workgroups\index.blade.php)
<x-app-layout>
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Your Workgroups') }}
</h2>
</x-slot>
<div class="py-12">
<div class="max-w-7xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 text-gray-900">
<script>
document.addEventListener('DOMContentLoaded', function() {
const buttonShowFormNewWorkgroup = document.getElementById('buttonShowFormNewWorkgroup');
const formNewWorkgroup = document.getElementById('newWorkgroupForm1');
const buttonCancelFormNewWorkgroup = document.getElementById('buttonCancelFormNewWorkgroup');
buttonShowFormNewWorkgroup.addEventListener('click', function() {
formNewWorkgroup.classList.toggle('hidden');
buttonShowFormNewWorkgroup.classList.add('hidden');
});
buttonCancelFormNewWorkgroup.addEventListener('click', function() {
formNewWorkgroup.classList.toggle('hidden');
buttonShowFormNewWorkgroup.classList.remove('hidden');
});
});
</script>
@if (session('success'))
<div class="bg-green-100 border border-green-400 text-green-700 px-4 py-3 rounded relative" role="alert">
<strong class="font-bold">Success!</strong>
<span class="block sm:inline">{{ session('success') }}</span>
</div>
@endif
<br/>
<x-primary-button id="buttonShowFormNewWorkgroup">
New Workgroup
</x-primary-button>
<div id="newWorkgroupForm1" class="w-full sm:max-w-md mt-6 px-6 py-4 bg-white shadow-md overflow-hidden sm:rounded-lg hidden">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('New Workgroup') }}
</h2>
<form action="{{ route('workgroups.store') }}" method="POST">
@csrf
<div class="mb-4">
<label for="name" class="block text-gray-700 font-semibold mb-2">Name</label>
<input type="text" id="name" name="name" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="refr" class="block text-gray-700 font-semibold mb-2">Reference</label>
<input type="text" id="refr" name="refr" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="desc" class="block text-gray-700 font-semibold mb-2">Description</label>
<textarea id="desc" name="desc" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">-</textarea>
</div>
<div class="mb-4">
<label for="locn" class="block text-gray-700 font-semibold mb-2">Location</label>
<input type="text" id="locn" name="locn" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="estartdate" class="block text-gray-700 font-semibold mb-2">Start Date</label>
<input type="number" id="estartdate" value="0" name="estartdate" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="key1" class="block text-gray-700 font-semibold mb-2">Key 1</label>
<input type="text" id="key1" name="key1" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="key2" class="block text-gray-700 font-semibold mb-2">Key 2</label>
<input type="text" id="key2" name="key2" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="key3" class="block text-gray-700 font-semibold mb-2">Key 3</label>
<input type="text" id="key3" name="key3" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="key4" class="block text-gray-700 font-semibold mb-2">Key 4</label>
<input type="text" id="key4" name="key4" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="key5" class="block text-gray-700 font-semibold mb-2">Key 5</label>
<input type="text" id="key5" name="key5" value="-" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<div class="mb-4">
<label for="n" class="block text-gray-700 font-semibold mb-2">N</label>
<input type="number" id="n" name="n" value="0" class="w-full px-4 py-2 border rounded-md focus:outline-none focus:ring focus:border-blue-300">
</div>
<x-secondary-button id="buttonCancelFormNewWorkgroup">
Cancel
</x-secondary-button>
<x-primary-button id="buttonSaveFormNewWorkgroup" type="submit">
Save Workgroup
</x-primary-button>
</form>
</div>
@if ($workgroups->count() > 0)
<div class="mt-4 space-y-4">
@foreach ($workgroups as $workgroup)
<div class="bg-white shadow-md rounded-lg p-4 border border-gray-300 border-solid border-1">
<div class="flex items-center justify-between">
<div>
<h5 class="font-semibold">{{ $workgroup->name }}</h5>
<p class="text-gray-600">{{ $workgroup->desc }}</p>
<p class="text-gray-600">Reference: {{ $workgroup->refr }}</p>
<p class="text-gray-600">Location: {{ $workgroup->locn }}</p>
<p class="text-gray-600">Start Date: {{ $workgroup->estartdate }}</p>
<p class="text-gray-600">Key 1: {{ $workgroup->key1 }}</p>
<p class="text-gray-600">Key 2: {{ $workgroup->key2 }}</p>
<p class="text-gray-600">Key 3: {{ $workgroup->key3 }}</p>
<p class="text-gray-600">Key 4: {{ $workgroup->key4 }}</p>
<p class="text-gray-600">Key 5: {{ $workgroup->key5 }}</p>
<p class="text-gray-600">N: {{ $workgroup->n }}</p>
</div>
<div class="space-x-2">
<a href="#" class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded">
Edit
</a>
<a href="#" class="bg-red-500 hover:bg-red-700 text-white font-bold py-2 px-4 rounded">
Delete
</a>
</div>
</div>
</div>
@endforeach
</div>
@else
<p class="mt-4 text-gray-600">You haven't created any workgroups yet.</p>
@endif
</div>
</div>
</div>
</div>
</x-app-layout>
Add the navigation link for the workgroups page in the navigation layout file:
(file →resources\views\layouts\navigation.blade.php)
<!-- Navigation Links -->
<div class="hidden space-x-8 sm:-my-px sm:ms-10 sm:flex">
<x-nav-link :href="route('dashboard')" :active="request()->routeIs('dashboard')">
{{ __('Dashboard') }}
</x-nav-link>
<x-nav-link :href="route('workgroups.index')" :active="request()->routeIs('workgroups.*')">
{{ __('Workgroups') }}
</x-nav-link>
</div>
[4] Update Web Route
...
use App\Http\Controllers\WorkgroupsController;
Route::get('/workgroups', [WorkgroupsController::class, 'index'])->name('workgroups.index');
Route::get('/workgroups/create', [WorkgroupsController::class, 'create'])->name('workgroups.create');
Route::post('/workgroups', [WorkgroupsController::class, 'store'])->name('workgroups.store');
...
[5] Test
Click New Workgroup button.
Enter details of the Workgroup e.g.:
Name = Group1
Description=This is Group1
Click Save Workgroup button.
Outcome:
Download:
https://archive.org/download/laravelprojects/lara11breeze_userapi_workgroups_20240409.zip
Further reading:
If you want to implement belongs_to
and has_many
relationship, refer https://hashnotes.hashnode.dev/laravel-11-workgroup-creating-collaborative-environments