laravel-from-zero-to-production

Wizard Form - Laravel

A dynamic multi-step form builder built with Laravel, featuring conditional logic, custom validation, and comprehensive form management.

๐Ÿš€ Features

โœ… Form Builder

โœ… Form Management

โœ… Submission Handling

โœ… Advanced Features

โœ… Admin Features

๐Ÿ“ Project Structure

wizard-form/
โ”œโ”€โ”€ app/
โ”‚   โ”œโ”€โ”€ Http/Controllers/
โ”‚   โ”‚   โ”œโ”€โ”€ FormController.php       # Form management
โ”‚   โ”‚   โ”œโ”€โ”€ FormStepController.php   # Step management
โ”‚   โ”‚   โ”œโ”€โ”€ FormFieldController.php  # Field management
โ”‚   โ”‚   โ””โ”€โ”€ SubmissionController.php # Submission handling
โ”‚   โ”œโ”€โ”€ Models/
โ”‚   โ”‚   โ”œโ”€โ”€ Form.php                # Form model
โ”‚   โ”‚   โ”œโ”€โ”€ FormStep.php            # Step model
โ”‚   โ”‚   โ”œโ”€โ”€ FormField.php           # Field model
โ”‚   โ”‚   โ””โ”€โ”€ FormSubmission.php      # Submission model
โ”‚   โ”œโ”€โ”€ Services/
โ”‚   โ”‚   โ”œโ”€โ”€ FormService.php         # Form business logic
โ”‚   โ”‚   โ”œโ”€โ”€ ValidationService.php   # Custom validation
โ”‚   โ”‚   โ””โ”€โ”€ ExportService.php       # Data export
โ”‚   โ””โ”€โ”€ Policies/
โ”‚       โ””โ”€โ”€ FormPolicy.php          # Authorization policies
โ”œโ”€โ”€ database/
โ”‚   โ””โ”€โ”€ migrations/
โ”‚       โ”œโ”€โ”€ create_forms_table.php
โ”‚       โ”œโ”€โ”€ create_form_steps_table.php
โ”‚       โ”œโ”€โ”€ create_form_fields_table.php
โ”‚       โ””โ”€โ”€ create_form_submissions_table.php
โ”œโ”€โ”€ resources/
โ”‚   โ””โ”€โ”€ views/
โ”‚       โ”œโ”€โ”€ forms/
โ”‚       โ”‚   โ”œโ”€โ”€ index.blade.php     # Form listing
โ”‚       โ”‚   โ”œโ”€โ”€ create.blade.php    # Form builder
โ”‚       โ”‚   โ”œโ”€โ”€ show.blade.php      # Form display
โ”‚       โ”‚   โ””โ”€โ”€ edit.blade.php      # Form editor
โ”‚       โ”œโ”€โ”€ submissions/
โ”‚       โ”‚   โ”œโ”€โ”€ index.blade.php     # Submission listing
โ”‚       โ”‚   โ””โ”€โ”€ show.blade.php      # Submission details
โ”‚       โ””โ”€โ”€ admin/
โ”‚           โ””โ”€โ”€ dashboard.blade.php # Admin panel
โ”œโ”€โ”€ routes/
โ”‚   โ””โ”€โ”€ web.php                    # Application routes
โ””โ”€โ”€ README.md                      # This file

๐Ÿ› ๏ธ Installation

1. Prerequisites

2. Installation

# Clone the project
git clone <repository-url>
cd wizard-form

# Install dependencies
composer install

# Copy environment file
cp .env.example .env

# Generate application key
php artisan key:generate

# Configure database in .env
DB_CONNECTION=mysql
DB_HOST=127.0.0.1
DB_PORT=3306
DB_DATABASE=wizard_form
DB_USERNAME=root
DB_PASSWORD=

# Run migrations
php artisan migrate

# Install Laravel Breeze
composer require laravel/breeze --dev
php artisan breeze:install blade

# Install frontend assets
npm install
npm run build

# Create storage link
php artisan storage:link

# Start server
php artisan serve

3. Access the application

๐Ÿ“š Laravel Concepts Used

Eloquent Models with Relationships

class Form extends Model
{
    protected $fillable = [
        'title', 'description', 'slug', 'status', 'public',
        'multiple_submissions', 'max_submissions', 'expires_at'
    ];

    // Relationships
    public function steps()
    {
        return $this->hasMany(FormStep::class)->orderBy('order');
    }

    public function submissions()
    {
        return $this->hasMany(FormSubmission::class);
    }

    public function user()
    {
        return $this->belongsTo(User::class);
    }

    // Scopes
    public function scopeActive($query)
    {
        return $query->where('status', 'active');
    }

    public function scopePublic($query)
    {
        return $query->where('public', true);
    }
}

Service Classes

class FormService
{
    public function createForm($data)
    {
        $form = Form::create($data);
        
        // Create default step
        $form->steps()->create([
            'title' => 'Step 1',
            'order' => 1,
            'required' => true
        ]);
        
        return $form;
    }

    public function addFieldToStep($stepId, $fieldData)
    {
        $step = FormStep::findOrFail($stepId);
        
        $field = $step->fields()->create([
            'label' => $fieldData['label'],
            'type' => $fieldData['type'],
            'required' => $fieldData['required'] ?? false,
            'options' => $fieldData['options'] ?? null,
            'validation_rules' => $fieldData['validation_rules'] ?? null,
            'order' => $step->fields()->count() + 1
        ]);
        
        return $field;
    }

    public function processSubmission($formId, $data)
    {
        $form = Form::findOrFail($formId);
        
        // Validate submission
        $this->validateSubmission($form, $data);
        
        // Create submission
        $submission = $form->submissions()->create([
            'data' => $data,
            'ip_address' => request()->ip(),
            'user_agent' => request()->userAgent()
        ]);
        
        // Send notifications
        $this->sendNotifications($form, $submission);
        
        return $submission;
    }
}

Resource Controllers

class FormController extends Controller
{
    protected $formService;

    public function __construct(FormService $formService)
    {
        $this->middleware('auth');
        $this->formService = $formService;
    }

    public function index(): View
    {
        $forms = auth()->user()->forms()
                    ->withCount('submissions')
                    ->latest()
                    ->paginate(10);

        return view('forms.index', compact('forms'));
    }

    public function store(StoreFormRequest $request): RedirectResponse
    {
        $form = $this->formService->createForm($request->validated());

        return redirect()->route('forms.edit', $form)
                        ->with('success', 'Form created successfully!');
    }

    public function show(Form $form): View
    {
        $form->load(['steps.fields', 'submissions']);
        
        return view('forms.show', compact('form'));
    }
}

Form Requests for Validation

class StoreFormRequest extends FormRequest
{
    public function rules(): array
    {
        return [
            'title' => 'required|string|max:255',
            'description' => 'nullable|string|max:1000',
            'status' => 'required|in:draft,active,inactive',
            'public' => 'boolean',
            'multiple_submissions' => 'boolean',
            'max_submissions' => 'nullable|integer|min:1',
            'expires_at' => 'nullable|date|after:now',
        ];
    }
}

๐ŸŽฏ Detailed Features

Form Builder

Multi-step Forms

Conditional Logic

Submission Management

Analytics and Reporting

๐Ÿ”ง Customization

Add new field types

  1. Create new field type classes
  2. Add field type to the form builder
  3. Create validation rules
  4. Update the form processor

Custom themes

  1. Create new Blade layouts
  2. Customize CSS and JavaScript
  3. Add theme configuration options
  4. Implement theme switching

Extend functionality

๐Ÿงช Testing

Unit Tests

# Run tests
php artisan test

# Specific tests
php artisan test --filter=FormTest

Feature Tests

class FormTest extends TestCase
{
    use RefreshDatabase;

    public function test_can_create_form()
    {
        $user = User::factory()->create();
        $this->actingAs($user);

        $response = $this->post('/forms', [
            'title' => 'Test Form',
            'description' => 'Test form description',
            'status' => 'active',
            'public' => true
        ]);

        $response->assertRedirect();
        $this->assertDatabaseHas('forms', ['title' => 'Test Form']);
    }

    public function test_can_submit_form()
    {
        $form = Form::factory()->create(['status' => 'active']);
        $step = $form->steps()->create(['title' => 'Step 1', 'order' => 1]);
        $field = $step->fields()->create([
            'label' => 'Name',
            'type' => 'text',
            'required' => true
        ]);

        $response = $this->post("/forms/{$form->id}/submit", [
            'step_1' => [
                'field_' . $field->id => 'John Doe'
            ]
        ]);

        $response->assertRedirect();
        $this->assertDatabaseHas('form_submissions', ['form_id' => $form->id]);
    }
}

๐Ÿš€ Deployment

Heroku

# Create Heroku app
heroku create wizard-form-laravel

# Configure environment variables
heroku config:set APP_KEY=base64:your-key
heroku config:set DB_CONNECTION=postgresql
heroku config:set FILESYSTEM_DISK=s3

# Deploy
git push heroku main

# Run migrations
heroku run php artisan migrate

VPS/Dedicated Server

# Clone on server
git clone <repository-url>
cd wizard-form

# Install dependencies
composer install --optimize-autoloader --no-dev
npm install && npm run build

# Configure environment
cp .env.example .env
php artisan key:generate

# Run migrations
php artisan migrate

# Optimize for production
php artisan config:cache
php artisan route:cache
php artisan view:cache

๐Ÿ“ API Endpoints

The wizard form can be extended with a REST API:

// routes/api.php
Route::apiResource('forms', FormApiController::class);
Route::post('forms/{form}/submit', [FormApiController::class, 'submit']);
Route::get('forms/{form}/submissions', [FormApiController::class, 'submissions']);

Available endpoints

๐Ÿค Contributing

  1. Fork the project
  2. Create a feature branch (git checkout -b feature/AmazingFeature)
  3. Commit your changes (git commit -m 'Add some AmazingFeature')
  4. Push to the branch (git push origin feature/AmazingFeature)
  5. Open a Pull Request

๐Ÿ“„ License

This project is licensed under the MIT License. See the LICENSE file for details.

๐Ÿ†˜ Support

For any questions or issues:

  1. Check this README
  2. Consult Laravel documentation
  3. Open an issue on GitHub

Wizard Form - Dynamic multi-step form builder with conditional logic ๐Ÿง™โ€โ™‚๏ธ