Skip to content

Repository files navigation

PHP Any Form Handler

A self-hosted, open-source form submission handler that works with any website. Accept form submissions from anywhere, store them in your own database, and get email notifications - all without limits.

The perfect alternative to Netlify Forms, Formspree, or other hosted form services.

Buy Me A CoffeePHP 8.1+License: MIT


Why Use This?

FeatureNetlify FormsFormspreePHP Any Form Handler
Monthly submissions100 (free)50 (free)Unlimited
Self-hostedNoNoYes
Data ownershipNoNo100% yours
Multi-tenantNoNoYes
Custom databaseNoNoYes
No vendor lock-inNoNoYes
Cost$19+/mo$10+/moFree

Features

  • Universal Form Handler - Works with any HTML form from any website
  • Multi-Tenant Support - Host multiple clients/projects with separate databases
  • Email Notifications - Get notified via SMTP when forms are submitted
  • JSON Storage - Flexible schema-less storage using MySQL JSON columns
  • Simple Dashboard - View submissions with just a Tenant ID (no password needed)
  • CORS Support - Accept submissions from any domain
  • Bot Protection - Built-in honeypot field to catch spam bots
  • Hidden Field Overrides - Override recipients dynamically per form
  • Secure by Design - SQL injection protection, XSS prevention, input sanitization

Quick Start

1. Clone & Install

git clone https://github.com/yourusername/php-any-form-handler.git
cd php-any-form-handler
composer install

2. Create Your Tenant Config

Copy the example config and customize it:

cp configs/example.json configs/mysite.json

Edit configs/mysite.json:

{
"tenant_id": "my-company",
"database": {
"host": "localhost",
"port": 3306,
"name": "forms_mycompany",
"username": "db_user",
"password": "db_password"
},
"email": {
"enabled": true,
"to": ["admin@mycompany.com"],
"cc": [],
"bcc": ["archive@mycompany.com"],
"from_email": "forms@myserver.com",
"from_name": "Contact Form",
"subject_prefix": "[Website Contact]"
},
"smtp": {
"host": "smtp.gmail.com",
"port": 587,
"encryption": "tls",
"username": "your-email@gmail.com",
"password": "your-app-password"
},
"allowed_origins": ["https://mycompany.com", "https://www.mycompany.com"]
}

3. Create Database

Create a MySQL database and run the schema:

mysql -u root -p -e "CREATE DATABASE forms_mycompany"
mysql -u root -p forms_mycompany < schema.sql

4. Configure Web Server

Point your web server's document root to the public/ folder.

Apache (.htaccess already included):

DocumentRoot /var/www/php-any-form-handler/public

Nginx:

server{listen80;server_name forms.myserver.com;root /var/www/php-any-form-handler/public;indexindex.php;location / {try_files$uri$uri/ /index.php?$query_string;}location~\.php$ {fastcgi_pass unix:/var/run/php/php8.1-fpm.sock;fastcgi_param SCRIPT_FILENAME $realpath_root$fastcgi_script_name;include fastcgi_params;}}

5. Add Form to Your Website

<formaction="https://forms.myserver.com/index.php" method="POST"><!-- Required: Your config ID --><inputtype="hidden" name="configId" value="mysite"><!-- Optional: Form identifier --><inputtype="hidden" name="_formname" value="contact"><!-- Optional: Redirect after submission --><inputtype="hidden" name="_redirect" value="https://mycompany.com/thank-you"><!-- Honeypot: Hide this with CSS --><inputtype="text" name="_honeypot" style="display:none" tabindex="-1" autocomplete="off"><!-- Your form fields --><inputtype="text" name="name" placeholder="Your Name" required><inputtype="email" name="email" placeholder="Your Email" required><inputtype="tel" name="phone" placeholder="Phone Number"><textareaname="message" placeholder="Your Message" required></textarea><buttontype="submit">Send Message</button></form>

Hidden Field Reference

Control form behavior with these hidden fields:

FieldRequiredDescription
configIdYesWhich tenant config to load
_formnameNoIdentifier for this form (shown in dashboard)
_redirectNoURL to redirect after successful submission
_honeypotNoBot trap - must be empty (hide with CSS)
_subjectNoOverride email subject line
tomailNoOverride recipient email(s)
ccNoOverride CC recipients
bccNoOverride BCC recipients

Dashboard

View your submissions at /dashboard.php. Just enter your Tenant ID - no password required.

Dashboard URL:https://forms.myserver.com/dashboard.php

The dashboard provides:

  • List of all form submissions
  • Filter by form name
  • Pagination for large datasets
  • View full submission details including IP and referrer

Multi-Tenant Setup

Host multiple clients by creating separate config files:

configs/
├── client-a.json → Tenant ID: "client-a-company"
├── client-b.json → Tenant ID: "client-b-corp"
├── my-personal.json → Tenant ID: "personal-site"
└── example.json → Template (ignored by git)

Each tenant gets:

  • Their own database (complete data isolation) or use a shared database
  • Custom email settings
  • Separate dashboard access
  • Independent allowed origins

API Response

Success (JSON)

{
"success": true,
"message": "Form submitted successfully"
}

Error (JSON)

{
"success": false,
"error": "Missing configId parameter"
}

With Redirect

If _redirect is set, users are redirected instead of receiving JSON.


Security

  • SQL Injection: All queries use PDO prepared statements
  • XSS Prevention: All output is escaped with htmlspecialchars()
  • Bot Protection: Honeypot field catches automated submissions
  • CORS Control: Per-tenant allowed origins configuration
  • Directory Traversal: Config IDs are sanitized
  • Config Protection: .htaccess blocks direct access to config files

Requirements

  • PHP 8.1 or higher
  • MySQL 5.7+ or MariaDB 10.2+ (with JSON support)
  • Composer
  • Web server (Apache/Nginx)

Project Structure

php-any-form-handler/
├── public/ # Web root
│ ├── index.php # Form submission endpoint
│ ├── dashboard.php # Tenant dashboard
│ └── assets/css/style.css # Dashboard styles
├── src/
│ ├── ConfigLoader.php # Loads tenant configurations
│ ├── Database.php # MySQL/JSON storage
│ ├── FormHandler.php # Core processing logic
│ ├── Mailer.php # Email notifications
│ └── Response.php # CORS & JSON responses
├── configs/
│ └── example.json # Config template
├── templates/
│ ├── dashboard-login.php # Login page
│ └── dashboard-list.php # Submissions list
├── composer.json
├── schema.sql
└── README.md

Contributing

Contributions are welcome! Here's how you can help:

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

Ideas for Contribution

  • File upload support
  • Webhook notifications (Slack, Discord)
  • Rate limiting
  • reCAPTCHA integration
  • Export submissions to CSV
  • Email templates customization
  • PostgreSQL support
  • REST API for submissions
  • Admin dashboard for managing tenants

Support the Project

If this project saves you money or time, consider buying me a coffee!

Buy Me A Coffee

Your support helps keep this project maintained and free for everyone.


License

This project is open source and available under the MIT License.


Acknowledgments

  • PHPMailer - Email sending library
  • Built as a free alternative to paid form handling services

Made with determination to keep the web open and self-hosted.

Ping me on https://softlancersolutions.com in case you need installation help and support for your system.

About

No description, website, or topics provided.

Resources

Stars

0 stars

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages