Laravel 11 - How to Integrate Signature Pad

Touseef Afridi
30 Oct 24

Laravel 11 - How to Integrate Signature Pad

This tutorial covers integrating a signature pad in Laravel 11, enabling electronic signatures for faster workflows, reduced paperwork, and streamlined approvals.


If you're a video person, feel free to skip the post and check out the video instead!


Quick Overview

This guide walks you through integrating a digital signature feature into your Laravel application. It begins with creating a fresh Laravel project or using an existing one. Then, you'll install the laravel-sign-pad package and publish necessary configuration and migration files. The User model is updated to handle signatures, and routes for user creation, signature storage, and agreement viewing are set up. A UserController is created to manage user data and signatures. Views are built for collecting user details and signature, along with a display page for showing the user's agreement details. Finally, the application is tested by submitting the form and viewing the agreement using the user's ID.

Step # 1 : Create fresh Laravel project or use existing project.

If Laravel is installed globally, use the following command to create a new project.
laravel new signature
Or
if Laravel is not installed globally, you can create a new project using Composer.
composer create-project laravel/laravel --prefer-dist signature
After executing one of the above commands, you will be prompted.
  1. Would you like to install the starter kit? — Choose none
  2. After selecting None, you'll be asked about testing framework. — Choose Pest
  3. After selecting Pest, you'll be asked to select the database for your application. — Choose mysql
  4. After selecting MySql, you'll be asked if you want to run the default database migration. — Choose yes

Step # 2 : Access the project.

Open a terminal (e.g., Git Bash) and navigate to your Laravel project's root folder.
cd c:xampp/htdocs/signature

Step # 3 : Install Signpad package.

Run the following command to install the package.
composer require creagia/laravel-sign-pad
This command will download and install the Laravel SignPad package, which allows you to capture and store digital signatures in your Laravel application.

Step # 4 : Publish the Config, Migration & Assets.

Run the following command to publish the package configuration and migration.
php artisan sign-pad:install
During the installation, you'll be prompted to run the migrations—type yes to proceed. After the migration details, you'll be asked to star the repository on GitHub—type yes to star the repository or no to skip.. Then, publish the JavaScript assets by running
php artisan vendor:publish --tag=sign-pad-assets

Step # 5 : Update the User Model.

Modify the User model to include signature handling by adding the necessary traits and contracts.
<?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;
// Include signature handling traits and contracts
use Creagia\LaravelSignPad\Concerns\RequiresSignature;
use Creagia\LaravelSignPad\Contracts\CanBeSigned;
// User model implements CanBeSigned for signature capabilities.
class User extends Authenticatable implements CanBeSigned
{
    /** @use HasFactory<\Database\Factories\UserFactory> */
    // Uses RequiresSignature for signature handling.
    use HasFactory, Notifiable, RequiresSignature;
    /**
     * The attributes that are mass assignable.
     *
     * @var array<int, string>
     */
    protected $fillable = [
        'name',
        'email',
        'password',
    ];
    /**
     * The attributes that should be hidden for serialization.
     *
     * @var array<int, string>
     */
    protected $hidden = [
        'password',
        'remember_token',
    ];
    /**
     * Get the attributes that should be cast.
     *
     * @return array<string, string>
     */
    protected function casts(): array
    {
        return [
            'email_verified_at' => 'datetime',
            'password' => 'hashed',
        ];
    }
}
This update enables digital signature functionality in the User model by implementing CanBeSigned and using RequiresSignature, allowing users to sign documents within your Laravel application.

Step # 6 : Create and Update Routes.

Import the UserController class, which will be created in the next step.
use App\Http\Controllers\UserController;
// Route to display the user creation form.
Route::get('/', [UserController::class, 'create']);
// Route to handle the form submission for creating a user and storing the signature.
Route::post('/confirm', [UserController::class, 'store']);
// Route to display the user's agreement details.
Route::get('/show/{user}', [UserController::class, 'show']);
These routes handle user creation, signature storage, and displaying agreement details in your Laravel application.

Step # 7 : Create a UserController.

Generate the UserController using the following command.
php artisan make:controller UserController
Replace the content of UserController.php with the following code to handle user creation and signature storage.
<?php
namespace App\Http\Controllers;
use App\Models\User;
use Creagia\LaravelSignPad\Signature;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
class UserController extends Controller
{
    public function create()
    {
        return view('sign');
    }
    public function store(Request $request)
    {
        $validatedData = $request->validate([
            'name' => 'required|string|max:255',
            'email' => 'required|string|email|max:255|unique:users',
            'password' => 'required|string|min:8',
            'sign' => 'required',
        ]);
        $user = User::create($validatedData);
        $signatureData = str_replace('data:image/png;base64,', '', $validatedData['sign']);
        $signatureData = base64_decode($signatureData);
        $imageName = 'signatures/' . Str::uuid() . '.png';
        Storage::disk('public')->put($imageName, $signatureData);
        $signature = new Signature();
        $signature->model_type = User::class;
        $signature->model_id = $user->id;
        $signature->uuid = Str::uuid();
        $signature->filename = $imageName;
        $signature->document_filename = null;
        $signature->certified = false;
        $signature->from_ips = json_encode([request()->ip()]);
        $signature->save();
        // Redirect back with success message.
        return redirect()->back()->with('success', 'Employment Agreement submited successfully!');
    }
    public function show(User $user)
    {
        $user->load('signature');
        return view('show', compact('user'));
    }
}
This controller handles displaying the signature form (create method), validating and storing user details along with the signature (store method), and showing the user's agreement details (show method).

Step # 8 : Create a storage link.

Run the following command to create a symbolic link from the public directory to the storage directory.
php artisan storage:link
This ensures that files stored in the storage folder are publicly accessible via the public directory.

Step # 9 : Create Views.

Create the sign.blade.php view. This view includes a form where the user can input their details (such as name, email, and password) and sign the employment agreement.
<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Code Shotcut - Employment Agreement</title>
  <script src="https://cdn.tailwindcss.com"></script>
  <style>
    .sign-pad-button-submit {
      margin-top: 5px;
      background-color: #3b82f6;
      color: white;
      font-weight: bold;
      padding: 0.5rem 1rem;
      border-radius: 0.5rem;
      transition: background-color 0.3s ease;
    }
    .sign-pad-button-submit:hover {
      background-color: #2563eb;
    }
    .sign-pad-button-clear {
      margin-top: 5px;
      background-color: #ef4444;
      color: white;
      font-weight: bold;
      padding: 0.5rem 1rem;
      border-radius: 0.5rem;
      transition: background-color 0.3s ease;
    }
    .sign-pad-button-clear:hover {
      background-color: #dc2626;
    }
  </style>
</head>
<body class="bg-gray-50 min-h-screen flex items-center justify-center">
  <form action="/confirm" method="POST" class="bg-white p-10 rounded-lg shadow-lg max-w-xl w-full">
    @csrf
    <h1 class="text-2xl font-bold text-center mb-4">Code Shotcut - Employment Agreement</h1>
    <p class="mb-4 text-justify text-gray-600">
      Please fill in your details and sign below to confirm your acceptance of the employment terms.
    </p>
    <!-- Display Success Message -->
    @if (session('success'))
    <div class="bg-green-100 text-green-700 p-4 rounded mb-4">
      {{ session('success') }}
    </div>
    @endif
    <!-- Display Error Messages -->
    @if ($errors->any())
    <div class="bg-red-100 text-red-700 p-4 rounded mb-4">
      <ul>
        @foreach ($errors->all() as $error)
        <li>{{ $error }}</li>
        @endforeach
      </ul>
    </div>
    @endif
    <div class="mb-4">
      <label for="name" class="block text-lg text-gray-700 font-medium mb-1">Full Name</label>
      <input type="text" id="name" name="name"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
      placeholder="Enter your full name" required />
    </div>
    <div class="mb-4">
      <label for="email" class="block text-lg text-gray-700 font-medium mb-1">Email Address</label>
      <input type="email" id="email" name="email"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
      placeholder="Enter your email" required />
    </div>
    <div class="mb-4">
      <label for="password" class="block text-lg text-gray-700 font-medium mb-1">Password</label>
      <input type="password" id="password" name="password"
      class="w-full px-4 py-2 border border-gray-300 rounded-lg focus:outline-none focus:ring-2 focus:ring-blue-500"
      placeholder="Create a password" required />
    </div>
    <!-- Signature Pad -->
    <div class="mb-4">
      <label class="block text-lg text-gray-700 font-medium mb-2">Signature</label>
      <x-creagia-signature-pad name='sign' />
    </div>
  </form>
  <!-- Sign-pad js -->
  <script src="{{ asset('vendor/sign-pad/sign-pad.min.js') }}"></script>
</body>
</html>
Create the show.blade.php view. This view displays the user's agreement details, including their name, email, and signature image if available.
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Code Shotcut - User Agreement</title>
    <link href="https://cdn.jsdelivr.net/npm/tailwindcss@2.2.19/dist/tailwind.min.css" rel="stylesheet">
</head>
<body class="bg-gray-50 min-h-screen flex items-center justify-center">
    <div class="bg-white p-10 rounded-lg shadow-lg max-w-md w-full">
        <h1 class="text-2xl font-bold text-center mb-4">User Details</h1>
        <p><strong>Name:</strong> {{ $user->name }}</p>
        <p><strong>Email:</strong> {{ $user->email }}</p>
        <h2 class="mt-4 mb-2 text-lg font-medium">Signature</h2>
        @if ($user->signature)
            <img src="{{ asset('storage/' . $user->signature->filename) }}" alt="User Signature" class="w-full h-auto">
        @else
            <p>No signature available.</p>
        @endif
    </div>
</body>
</html>

Step # 10 : It's time to test.

Start the Laravel development server with the command.
php artisan serve
Open your web browser and navigate to the following URL to access the form.
127.0.0.1:8000

Complete the form with the required information and submit it to store the user and their signature.

To view the submitted agreement, visit the following URL and replace $id with the actual user ID.
127/0.0.1/show/$id

Conclusion

By following this guide, you've successfully integrated a digital signature feature into your Laravel application. Users can now submit their details along with a digital signature, which is securely stored in the application. With the laravel-sign-pad package managing the signature functionality, your application offers an efficient and reliable way to collect and display user agreements. You can further customize the implementation to suit your specific needs.
For more details, check the laravel-sign-pad package documentation.
Share this with friends!


"Give this post some love and slap that 💖 button as if it owes you money! 💸😄"
0

0 Comments

To engage in commentary, kindly proceed by logging in or registering