QR Code Generator using PHP (Library + API)

QR codes have become an essential part of modern web applications. From sharing URLs and contact details to enabling quick payments and app downloads, QR codes provide a fast and user-friendly way to exchange information.

In this tutorial, we will explore how to generate QR codes using PHP, a popular server-side scripting language. We will use the custom PHP library that makes it easy to create QR codes in various formats. With this step-by-step guide, you’ll learn how to build a professional QR Code Generator using PHP with a clean architecture and reusable components. This guide is based on a real-world PHP project structure and uses the powerful Endroid QR Code library.

By the end of this tutorial, you will understand:

  • How QR code generation works in PHP
  • How to structure a scalable QR code generator
  • How to generate QR codes dynamically via UI and REST API
  • How to customize QR size, format, and content

🎯 Use Cases

This PHP QR Code Generator can be used for:

  • Generating QR codes for URLs
  • Creating QR codes for text or custom data
  • Integrating QR generation into APIs
  • Embedding QR codes in invoices, posters, or PDFs
  • SaaS tools and admin dashboards

πŸ“‹ Prerequisites

We will use custom PHP library to generate QR codes. This library has a dependency on GD extension for image processing. Make sure you have the GD extension enabled in your PHP installation.

πŸ“ Project Structure Overview

Here is the directory structure used in this QR Code Generator project:

qr_code_generator/
β”œβ”€β”€ config.php
β”œβ”€β”€ index.php
β”œβ”€β”€ api.php
β”œβ”€β”€ includes/
|   β”œβ”€β”€ QRCodeGenerator.php
β”‚   └── QRCodeRenderer.php
β”œβ”€β”€ vendor/
└── assets/
    └── style.css

Each file has a specific responsibility, making the project easy to maintain and extend:

  • config.php: Configuration settings for the QR code generator.
  • index.php: The main entry point for the web interface.
  • api.php: REST API endpoint for generating QR codes programmatically.
  • includes/QRCodeGenerator.php: Contains the logic for generating QR codes.
  • includes/QRCodeRenderer.php: Handles rendering QR codes in different formats.
  • vendor/: Contains third-party libraries installed via Composer.
  • assets/style.css: CSS styles for the web interface.

Step 1: Install Dependencies using Composer

This project uses the Endroid QR Code library, one of the most reliable PHP QR code libraries. To install it, run the following command in your project root:

composer require endroid/qr-code

Composer will create the vendor/ directory and install all required dependencies.

Note that: You don’t need to download the Endroid QR Code library separately, all the required library files are included in our source code package.

Step 2: Configuration File (config.php)

The config.php file loads Composer’s autoloader for dependencies and contains all the configuration settings for the QR Code Generator. Here, we define constants for QR code sizes, types, and validation rules.

<?php 
// Load Composer autoloader for dependencies
require_once __DIR__ '/vendor/autoload.php';

// QR Code Configuration
define('QR_CODE_SIZE'300);                 // Default QR code size in pixels
define('QR_CODE_SIZE_DOWNLOAD'500);        // Size for downloads in pixels

// QR Code Types
$QR_TYPES = [
    
'url' => ['label' => 'URL/Website''icon' => '🌐'],
    
'email' => ['label' => 'Email''icon' => 'βœ‰οΈ'],
    
'phone' => ['label' => 'Phone Call''icon' => '☎️'],
    
'sms' => ['label' => 'SMS Message''icon' => 'πŸ’¬'],
    
'contact' => ['label' => 'Contact''icon' => 'πŸ‘€'],
    
'vcard' => ['label' => 'vCard (Business Card)''icon' => 'πŸ’Ό'],
    
'wifi' => ['label' => 'WiFi Network''icon' => 'πŸ“‘'],
    
'event' => ['label' => 'Event/Calendar''icon' => 'πŸ“…'],
    
'location' => ['label' => 'GPS Location''icon' => 'πŸ“'],
    
'app' => ['label' => 'App Download Link''icon' => 'πŸ“±']
];

// WiFi Security Types
$WIFI_SECURITY_TYPES = [
    
'WPA' => 'WPA/WPA2 (Recommended)',
    
'WEP' => 'WEP (Legacy)',
    
'nopass' => 'No Password (Open Network)'
];

// Validation Rules
$VALIDATION_RULES = [
    
'url' => [
        
'type' => 'url',
        
'required' => true,
        
'message' => 'Please enter a valid URL starting with http:// or https://'
    
],
    
'email' => [
        
'type' => 'email',
        
'required' => true,
        
'message' => 'Please enter a valid email address'
    
],
    
'phone' => [
        
'type' => 'tel',
        
'required' => true,
        
'pattern' => '/^[0-9+\-\(\) ]+$/',
        
'message' => 'Please enter a valid phone number'
    
],
    
'latitude' => [
        
'type' => 'number',
        
'required' => true,
        
'min' => -90,
        
'max' => 90,
        
'message' => 'Latitude must be between -90 and 90'
    
],
    
'longitude' => [
        
'type' => 'number',
        
'required' => true,
        
'min' => -180,
        
'max' => 180,
        
'message' => 'Longitude must be between -180 and 180'
    
]
];
?>

Step 3: QR Code Data Handler (includes/QRCodeGenerator.php)

The QRCodeGenerator class is used to prepare and validate QR code content before rendering. It includes methods for different QR code types, ensuring the data is formatted correctly.

<?php 
class QRCodeGenerator {
    
    
/**
     * Generate QR code data for a URL
     */
    
public function generateURL($url) {
        if (!
filter_var($urlFILTER_VALIDATE_URL)) {
            throw new 
Exception('Invalid URL format');
        }
        return 
$url;
    }
    
    
/**
     * Generate QR code data for Email
     */
    
public function generateEmail($email$subject ''$body '') {
        if (!
filter_var($emailFILTER_VALIDATE_EMAIL)) {
            throw new 
Exception('Invalid email format');
        }
        
        
$mailto 'mailto:' $email;
        
        if (!empty(
$subject) || !empty($body)) {
            
$params = [];
            if (!empty(
$subject)) {
                
$params[] = 'subject=' urlencode($subject);
            }
            if (!empty(
$body)) {
                
$params[] = 'body=' urlencode($body);
            }
            
$mailto .= '?' implode('&'$params);
        }
        
        return 
$mailto;
    }
    
    
/**
     * Generate QR code data for Phone Call
     */
    
public function generatePhone($phone) {
        
// Remove any non-digit characters except +
        
$phone preg_replace('/[^0-9+]/'''$phone);
        
        if (empty(
$phone)) {
            throw new 
Exception('Invalid phone number');
        }
        
        return 
'tel:' $phone;
    }
    
    
/**
     * Generate QR code data for SMS
     */
    
public function generateSMS($phone$message '') {
        
$phone preg_replace('/[^0-9+]/'''$phone);
        
        if (empty(
$phone)) {
            throw new 
Exception('Invalid phone number');
        }
        
        
$sms 'smsto:' $phone;
        
        if (!empty(
$message)) {
            
$sms .= ':' urlencode($message);
        }
        
        return 
$sms;
    }
    
    
/**
     * Generate QR code data for Contact (vCard format)
     */
    
public function generateContact($name$phone ''$email '') {
        if (empty(
$name)) {
            throw new 
Exception('Contact name is required');
        }
        
        
$vcard "BEGIN:VCARD\r\n";
        
$vcard .= "VERSION:3.0\r\n";
        
$vcard .= "FN:" $this->escapeVCard($name) . "\r\n";
        
        if (!empty(
$phone)) {
            
$phone preg_replace('/[^0-9+]/'''$phone);
            
$vcard .= "TEL:" $phone "\r\n";
        }
        
        if (!empty(
$email)) {
            if (!
filter_var($emailFILTER_VALIDATE_EMAIL)) {
                throw new 
Exception('Invalid email format');
            }
            
$vcard .= "EMAIL:" $email "\r\n";
        }
        
        
$vcard .= "END:VCARD";
        
        return 
$vcard;
    }
    
    
/**
     * Generate QR code data for vCard (Business Card)
     */
    
public function generateVCard($name$phone ''$email ''$org ''$url '') {
        if (empty(
$name)) {
            throw new 
Exception('Name is required');
        }
        
        
$vcard "BEGIN:VCARD\r\n";
        
$vcard .= "VERSION:3.0\r\n";
        
        
// Split name into first and last name
        
$names explode(' '$name2);
        
$vcard .= "N:" . (isset($names[1]) ? $this->escapeVCard($names[1]) : '') . ";" $this->escapeVCard($names[0]) . "\r\n";
        
$vcard .= "FN:" $this->escapeVCard($name) . "\r\n";
        
        if (!empty(
$org)) {
            
$vcard .= "ORG:" $this->escapeVCard($org) . "\r\n";
        }
        
        if (!empty(
$phone)) {
            
$phone preg_replace('/[^0-9+]/'''$phone);
            
$vcard .= "TEL;TYPE=VOICE,WORK:" $phone "\r\n";
        }
        
        if (!empty(
$email)) {
            if (!
filter_var($emailFILTER_VALIDATE_EMAIL)) {
                throw new 
Exception('Invalid email format');
            }
            
$vcard .= "EMAIL;TYPE=INTERNET,WORK:" $email "\r\n";
        }
        
        if (!empty(
$url)) {
            if (!
filter_var($urlFILTER_VALIDATE_URL)) {
                throw new 
Exception('Invalid URL format');
            }
            
$vcard .= "URL:" $url "\r\n";
        }
        
        
$vcard .= "END:VCARD";
        
        return 
$vcard;
    }
    
    
/**
     * Generate QR code data for WiFi Network
     */
    
public function generateWiFi($ssid$password ''$security 'WPA') {
        if (empty(
$ssid)) {
            throw new 
Exception('WiFi SSID is required');
        }
        
        
// WiFi QR code format: WIFI:T:security;S:SSID;P:password;H:hidden;;
        
$wifi 'WIFI:';
        
$wifi .= 'T:' $security ';';
        
$wifi .= 'S:' $this->escapeWiFi($ssid) . ';';
        
        if (!empty(
$password)) {
            
$wifi .= 'P:' $this->escapeWiFi($password) . ';';
        }
        
        
$wifi .= 'H:false;;';
        
        return 
$wifi;
    }
    
    
/**
     * Generate QR code data for Event/Calendar
     */
    
public function generateEvent($title$start ''$end ''$location '') {
        if (empty(
$title)) {
            throw new 
Exception('Event title is required');
        }
        
        
// Using BEGIN:VEVENT format (iCalendar)
        
$ical "BEGIN:VCALENDAR\r\n";
        
$ical .= "VERSION:2.0\r\n";
        
$ical .= "PRODID:-//QR Code Generator//EN\r\n";
        
$ical .= "BEGIN:VEVENT\r\n";
        
        
// Format dates for iCalendar (YYYYMMDDTHHMMSSZ)
        
if (!empty($start)) {
            
$startDate $this->formatICalDate($start);
            
$ical .= "DTSTART:" $startDate "\r\n";
        }
        
        if (!empty(
$end)) {
            
$endDate $this->formatICalDate($end);
            
$ical .= "DTEND:" $endDate "\r\n";
        }
        
        
$ical .= "SUMMARY:" $this->escapeICalText($title) . "\r\n";
        
        if (!empty(
$location)) {
            
$ical .= "LOCATION:" $this->escapeICalText($location) . "\r\n";
        }
        
        
$ical .= "UID:" uniqid() . "@qrcodegenerator\r\n";
        
$ical .= "DTSTAMP:" date('Ymd\THis\Z') . "\r\n";
        
$ical .= "END:VEVENT\r\n";
        
$ical .= "END:VCALENDAR";
        
        return 
$ical;
    }
    
    
/**
     * Generate QR code data for GPS Location
     */
    
public function generateLocation($latitude$longitude) {
        
// Validate coordinates
        
$lat floatval($latitude);
        
$lng floatval($longitude);
        
        if (
$lat < -90 || $lat 90) {
            throw new 
Exception('Latitude must be between -90 and 90');
        }
        
        if (
$lng < -180 || $lng 180) {
            throw new 
Exception('Longitude must be between -180 and 180');
        }
        
        
// Google Maps format: geo:latitude,longitude
        
return 'geo:' $lat ',' $lng;
    }
    
    
/**
     * Generate QR code data for App Download Link
     */
    
public function generateAppDownload($url) {
        if (!
filter_var($urlFILTER_VALIDATE_URL)) {
            throw new 
Exception('Invalid app URL format');
        }
        return 
$url;
    }
    
    
/**
     * Escape special characters for vCard format
     */
    
private function escapeVCard($text) {
        
$text str_replace('\\''\\\\'$text);
        
$text str_replace(',''\\,'$text);
        
$text str_replace(';''\\;'$text);
        
$text str_replace("\r\n"'\\n'$text);
        
$text str_replace("\n"'\\n'$text);
        return 
$text;
    }
    
    
/**
     * Escape special characters for WiFi format
     */
    
private function escapeWiFi($text) {
        
$text str_replace('\\''\\\\'$text);
        
$text str_replace(';''\\;'$text);
        
$text str_replace(':''\\:'$text);
        
$text str_replace(',''\\,'$text);
        
$text str_replace('"''\\"'$text);
        return 
$text;
    }
    
    
/**
     * Escape special characters for iCalendar format
     */
    
private function escapeICalText($text) {
        
$text str_replace('\\''\\\\'$text);
        
$text str_replace(',''\\,'$text);
        
$text str_replace(';''\\;'$text);
        
$text str_replace("\r\n"'\\n'$text);
        
$text str_replace("\n"'\\n'$text);
        return 
$text;
    }
    
    
/**
     * Format datetime string to iCalendar format
     */
    
private function formatICalDate($dateString) {
        try {
            
$date = new DateTime($dateString);
            return 
$date->format('Ymd\THis');
        } catch (
Exception $e) {
            throw new 
Exception('Invalid date format. Please use YYYY-MM-DD or YYYY-MM-DDTHH:MM:SS format');
        }
    }
}
?>

Step 4: QR Code Renderer (includes/QRCodeRenderer.php)

This QRCodeRenderer class is responsible for generating the QR code image using Endroid QR Code (endroid/qr-code) library. This class encapsulates all the logic needed to create and customize QR codes based on the provided data.

  • Initializes the QR Code object
  • Sets size, margin, encoding
  • Defines output format (PNG, SVG, etc.)
  • Renders and outputs the QR image
<?php 
use Endroid\QrCode\QrCode;
use 
Endroid\QrCode\Writer\PngWriter;
use 
Endroid\QrCode\ErrorCorrectionLevel;

class 
QRCodeRenderer {
    
    private 
$errorCorrectionLevel 'M';
    
    public function 
__construct($errorCorrectionLevel 'M') {
        
$this->errorCorrectionLevel $errorCorrectionLevel;
    }
    
    
/**
     * Generate QR code and return as data URL
     */
    
public function generate($text$size 300) {
        try {
            
$imageData $this->createQRImage($text$size);
            return 
'data:image/png;base64,' base64_encode($imageData);
        } catch (
Exception $e) {
            
error_log('QR Generation Error: ' $e->getMessage());
            throw 
$e;
        }
    }
    
    
/**
     * Generate QR code and save to file
     */
    
public function generateToFile($text$filepath$size 300) {
        try {
            
$imageData $this->createQRImage($text$size);
            return 
file_put_contents($filepath$imageData) !== false;
        } catch (
Exception $e) {
            
error_log('QR File Generation Error: ' $e->getMessage());
            throw 
$e;
        }
    }
    
    
/**
     * Get image bytes for download
     */
    
public function getImageBytes($text$size 300) {
        try {
            return 
$this->createQRImage($text$size);
        } catch (
Exception $e) {
            
error_log('QR Bytes Generation Error: ' $e->getMessage());
            throw 
$e;
        }
    }
    
    
/**
     * Create QR image using Endroid library
     */
    
private function createQRImage($text$size) {
        
$text = (string)$text;
        
        
// Map error correction level
        
$ecLevel $this->mapErrorCorrectionLevel($this->errorCorrectionLevel);
        
        
// Create QR code with proper parameters
        
$qrCode = new QrCode(
            
data$text,
            
errorCorrectionLevel$ecLevel,
            
size$size,
            
margin10
        
);
        
        
// Render to PNG
        
$writer = new PngWriter();
        
$result $writer->write($qrCode);
        
        return 
$result->getString();
    }
    
    
/**
     * Map error correction level to Endroid format
     */
    
private function mapErrorCorrectionLevel($level) {
        
$levelMap = array(
            
'L' => ErrorCorrectionLevel::Low,
            
'M' => ErrorCorrectionLevel::Medium,
            
'Q' => ErrorCorrectionLevel::Quartile,
            
'H' => ErrorCorrectionLevel::High
        
);
        
        return 
$levelMap[$level] ?? ErrorCorrectionLevel::Medium;
    }
}
?>

Step 5: User Interface (index.php)

The index.php file serves as the main entry point (frontend interface) for users to interact with the QR code generator. It provides a simple HTML form where users can input the text or URL they want to encode into a QR code. Upon submission, it processes the input, generates the QR code using the QRCodeRenderer class, and displays the resulting QR code image on the same page.

<?php 
// QR Code Generator - Main Page
session_start();

// Include configuration
require_once 'config.php';

// Include the QR Code generator class
require_once 'includes/QRCodeGenerator.php';

// Include the QR Code renderer for internal generation
require_once 'includes/QRCodeRenderer.php';

// Process form submission
$generated_qr null;
$error_message null;
$qr_data null;

if (
$_SERVER['REQUEST_METHOD'] === 'POST') {
    
$type $_POST['qr_type'] ?? '';
    
    try {
        
$qr_generator = new QRCodeGenerator();
        
        switch (
$type) {
            case 
'url':
                
$url $_POST['url'] ?? '';
                if (empty(
$url)) throw new Exception('URL is required');
                
$qr_data $qr_generator->generateURL($url);
                break;
                
            case 
'email':
                
$email $_POST['email'] ?? '';
                
$subject $_POST['email_subject'] ?? '';
                
$body $_POST['email_body'] ?? '';
                if (empty(
$email)) throw new Exception('Email is required');
                
$qr_data $qr_generator->generateEmail($email$subject$body);
                break;
                
            case 
'phone':
                
$phone $_POST['phone'] ?? '';
                if (empty(
$phone)) throw new Exception('Phone number is required');
                
$qr_data $qr_generator->generatePhone($phone);
                break;
                
            case 
'sms':
                
$phone $_POST['sms_phone'] ?? '';
                
$message $_POST['sms_message'] ?? '';
                if (empty(
$phone)) throw new Exception('Phone number is required');
                
$qr_data $qr_generator->generateSMS($phone$message);
                break;
                
            case 
'contact':
                
$name $_POST['contact_name'] ?? '';
                
$phone $_POST['contact_phone'] ?? '';
                
$email $_POST['contact_email'] ?? '';
                if (empty(
$name)) throw new Exception('Contact name is required');
                
$qr_data $qr_generator->generateContact($name$phone$email);
                break;
                
            case 
'vcard':
                
$name $_POST['vcard_name'] ?? '';
                
$phone $_POST['vcard_phone'] ?? '';
                
$email $_POST['vcard_email'] ?? '';
                
$org $_POST['vcard_org'] ?? '';
                
$url $_POST['vcard_url'] ?? '';
                if (empty(
$name)) throw new Exception('Name is required');
                
$qr_data $qr_generator->generateVCard($name$phone$email$org$url);
                break;
                
            case 
'wifi':
                
$ssid $_POST['wifi_ssid'] ?? '';
                
$password $_POST['wifi_password'] ?? '';
                
$security $_POST['wifi_security'] ?? 'WPA';
                if (empty(
$ssid)) throw new Exception('WiFi SSID is required');
                
$qr_data $qr_generator->generateWiFi($ssid$password$security);
                break;
                
            case 
'event':
                
$title $_POST['event_title'] ?? '';
                
$start $_POST['event_start'] ?? '';
                
$end $_POST['event_end'] ?? '';
                
$location $_POST['event_location'] ?? '';
                if (empty(
$title)) throw new Exception('Event title is required');
                
$qr_data $qr_generator->generateEvent($title$start$end$location);
                break;
                
            case 
'location':
                
$lat $_POST['latitude'] ?? '';
                
$lng $_POST['longitude'] ?? '';
                if (empty(
$lat) || empty($lng)) throw new Exception('Latitude and Longitude are required');
                
$qr_data $qr_generator->generateLocation($lat$lng);
                break;
                
            case 
'app':
                
$app_url $_POST['app_url'] ?? '';
                if (empty(
$app_url)) throw new Exception('App URL is required');
                
$qr_data $qr_generator->generateAppDownload($app_url);
                break;
                
            default:
                throw new 
Exception('Invalid QR code type selected');
        }
        
        
// Generate QR code image
        
$generated_qr generateQRCodeImage($qr_data);
        
$_SESSION['last_qr_data'] = $qr_data;
        
$_SESSION['last_qr_type'] = $type;
        
    } catch (
Exception $e) {
        
$error_message $e->getMessage();
    }
}

// Function to generate QR code image using internal library
function generateQRCodeImage($data) {
    
$renderer = new QRCodeRenderer();
    return 
$renderer->generate($dataQR_CODE_SIZE);
}

?> <div class="form-section"> <form method="POST" class="qr-form"> <div class="form-group"> <label for="qr_type">Select QR Code Type:</label> <select id="qr_type" name="qr_type" required onchange="updateFormFields()"> <option value="">-- Choose Type --</option> <option value="url" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'url') ? 'selected' ''?>>URL/Website</option> <option value="email" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'email') ? 'selected' ''?>>Email</option> <option value="phone" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'phone') ? 'selected' ''?>>Phone Call</option> <option value="sms" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'sms') ? 'selected' ''?>>SMS Message</option> <option value="contact" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'contact') ? 'selected' ''?>>Contact</option> <option value="vcard"<?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'vcard') ? 'selected' ''?>>vCard (Business Card)</option> <option value="wifi" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'wifi') ? 'selected' ''?>>WiFi Network</option> <option value="event" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'event') ? 'selected' ''?>>Event/Calendar</option> <option value="location" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'location') ? 'selected' ''?>>GPS Location</option> <option value="app" <?php echo (isset($_POST['qr_type']) && $_POST['qr_type'] === 'app') ? 'selected' ''?>>App Download Link</option> </select> </div> <!-- URL Fields --> <div id="url-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="url">Website URL:</label> <input type="url" id="url" name="url" placeholder="https://example.com" value="<?php echo htmlspecialchars($_POST['url'] ?? ''); ?>"> </div> </div> <!-- Email Fields --> <div id="email-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="email">Email Address:</label> <input type="email" id="email" name="email" placeholder="[email protected]" value="<?php echo htmlspecialchars($_POST['email'] ?? ''); ?>"> </div> <div class="form-group"> <label for="email_subject">Subject (Optional):</label> <input type="text" id="email_subject" name="email_subject" placeholder="Email subject" value="<?php echo htmlspecialchars($_POST['email_subject'] ?? ''); ?>"> </div> <div class="form-group"> <label for="email_body">Message Body (Optional):</label> <textarea id="email_body" name="email_body" placeholder="Email message" rows="3"><?php echo htmlspecialchars($_POST['email_body'] ?? ''); ?></textarea> </div> </div> <!-- Phone Fields --> <div id="phone-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="phone">Phone Number:</label> <input type="tel" id="phone" name="phone" placeholder="+1-555-123-4567" value="<?php echo htmlspecialchars($_POST['phone'] ?? ''); ?>"> </div> </div> <!-- SMS Fields --> <div id="sms-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="sms_phone">Phone Number:</label> <input type="tel" id="sms_phone" name="sms_phone" placeholder="+1-555-123-4567" value="<?php echo htmlspecialchars($_POST['sms_phone'] ?? ''); ?>"> </div> <div class="form-group"> <label for="sms_message">SMS Message (Optional):</label> <textarea id="sms_message" name="sms_message" placeholder="SMS message" rows="3"><?php echo htmlspecialchars($_POST['sms_message'] ?? ''); ?></textarea> </div> </div> <!-- Contact Fields --> <div id="contact-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="contact_name">Name:</label> <input type="text" id="contact_name" name="contact_name" placeholder="John Doe" value="<?php echo htmlspecialchars($_POST['contact_name'] ?? ''); ?>"> </div> <div class="form-group"> <label for="contact_phone">Phone (Optional):</label> <input type="tel" id="contact_phone" name="contact_phone" placeholder="+1-555-123-4567" value="<?php echo htmlspecialchars($_POST['contact_phone'] ?? ''); ?>"> </div> <div class="form-group"> <label for="contact_email">Email (Optional):</label> <input type="email" id="contact_email" name="contact_email" placeholder="[email protected]" value="<?php echo htmlspecialchars($_POST['contact_email'] ?? ''); ?>"> </div> </div> <!-- vCard Fields --> <div id="vcard-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="vcard_name">Full Name:</label> <input type="text" id="vcard_name" name="vcard_name" placeholder="John Doe" value="<?php echo htmlspecialchars($_POST['vcard_name'] ?? ''); ?>"> </div> <div class="form-group"> <label for="vcard_phone">Phone (Optional):</label> <input type="tel" id="vcard_phone" name="vcard_phone" placeholder="+1-555-123-4567" value="<?php echo htmlspecialchars($_POST['vcard_phone'] ?? ''); ?>"> </div> <div class="form-group"> <label for="vcard_email">Email (Optional):</label> <input type="email" id="vcard_email" name="vcard_email" placeholder="[email protected]" value="<?php echo htmlspecialchars($_POST['vcard_email'] ?? ''); ?>"> </div> <div class="form-group"> <label for="vcard_org">Organization (Optional):</label> <input type="text" id="vcard_org" name="vcard_org" placeholder="Company Name" value="<?php echo htmlspecialchars($_POST['vcard_org'] ?? ''); ?>"> </div> <div class="form-group"> <label for="vcard_url">Website (Optional):</label> <input type="url" id="vcard_url" name="vcard_url" placeholder="https://example.com" value="<?php echo htmlspecialchars($_POST['vcard_url'] ?? ''); ?>"> </div> </div> <!-- WiFi Fields --> <div id="wifi-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="wifi_ssid">WiFi Network Name (SSID):</label> <input type="text" id="wifi_ssid" name="wifi_ssid" placeholder="MyWiFiNetwork" value="<?php echo htmlspecialchars($_POST['wifi_ssid'] ?? ''); ?>"> </div> <div class="form-group"> <label for="wifi_password">Password (Optional):</label> <input type="password" id="wifi_password" name="wifi_password" placeholder="WiFi password" value="<?php echo htmlspecialchars($_POST['wifi_password'] ?? ''); ?>"> </div> <div class="form-group"> <label for="wifi_security">Security Type:</label> <select id="wifi_security" name="wifi_security"> <option value="WPA" <?php echo (isset($_POST['wifi_security']) && $_POST['wifi_security'] === 'WPA') ? 'selected' ''?>>WPA/WPA2</option> <option value="WEP" <?php echo (isset($_POST['wifi_security']) && $_POST['wifi_security'] === 'WEP') ? 'selected' ''?>>WEP</option> <option value="nopass" <?php echo (isset($_POST['wifi_security']) && $_POST['wifi_security'] === 'nopass') ? 'selected' ''?>>No Password</option> </select> </div> </div> <!-- Event Fields --> <div id="event-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="event_title">Event Title:</label> <input type="text" id="event_title" name="event_title" placeholder="Conference 2024" value="<?php echo htmlspecialchars($_POST['event_title'] ?? ''); ?>"> </div> <div class="form-group"> <label for="event_start">Start Date & Time:</label> <input type="datetime-local" id="event_start" name="event_start" value="<?php echo htmlspecialchars($_POST['event_start'] ?? ''); ?>"> </div> <div class="form-group"> <label for="event_end">End Date & Time (Optional):</label> <input type="datetime-local" id="event_end" name="event_end" value="<?php echo htmlspecialchars($_POST['event_end'] ?? ''); ?>"> </div> <div class="form-group"> <label for="event_location">Location (Optional):</label> <input type="text" id="event_location" name="event_location" placeholder="Conference Hall, 123 Main St" value="<?php echo htmlspecialchars($_POST['event_location'] ?? ''); ?>"> </div> </div> <!-- Location Fields --> <div id="location-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="latitude">Latitude:</label> <input type="number" id="latitude" name="latitude" step="0.000001" placeholder="40.7128" value="<?php echo htmlspecialchars($_POST['latitude'] ?? ''); ?>"> </div> <div class="form-group"> <label for="longitude">Longitude:</label> <input type="number" id="longitude" name="longitude" step="0.000001" placeholder="-74.0060" value="<?php echo htmlspecialchars($_POST['longitude'] ?? ''); ?>"> </div> </div> <!-- App Download Fields --> <div id="app-fields" class="form-fields" style="display:none;"> <div class="form-group"> <label for="app_url">App Download URL:</label> <input type="url" id="app_url" name="app_url" placeholder="https://play.google.com/store/apps/details?id=com.example.app" value="<?php echo htmlspecialchars($_POST['app_url'] ?? ''); ?>"> </div> </div> <button type="submit" class="btn-generate">Generate QR Code</button> </form> </div> <!-- Result Section --> <div class="result-section"> <?php if ($error_message): ?> <div class="alert alert-error"> <strong>Error:</strong> <?php echo htmlspecialchars($error_message); ?> </div> <?php endif; ?> <?php if ($generated_qr): ?> <div class="qr-result"> <h3>Your QR Code</h3> <div class="qr-display"> <img src="<?php echo htmlspecialchars($generated_qr); ?>" alt="Generated QR Code"> </div> <div class="qr-data"> <p><strong>Encoded Data:</strong></p> <code><?php echo htmlspecialchars($qr_data); ?></code> </div> <div class="button-group"> <a href="<?php echo htmlspecialchars($generated_qr); ?>" download class="btn btn-download">πŸ“₯ Download QR Code</a> </div> </div> <?php endif; ?> </div>

JavaScript for Dynamic Form Fields:
The following JavaScript code dynamically shows or hides form fields based on the selected QR code type. Add this script just before the closing </body> tag in index.php.

<script>
function updateFormFields() {
    const type = document.getElementById('qr_type').value;
    
    // Hide all fields
    document.querySelectorAll('.form-fields').forEach(el => {
        el.style.display = 'none';
    });
    
    // Show relevant fields
    if (type) {
        const fieldId = type + '-fields';
        const fieldElement = document.getElementById(fieldId);
        if (fieldElement) {
            fieldElement.style.display = 'block';
        }
    }
}

// Initialize on page load
document.addEventListener('DOMContentLoaded', function() {
    updateFormFields();
    // Scroll to form if there's an error or result to show
    <?php if ($error_message || $generated_qr): ?>
        document.querySelector('.form-section').scrollIntoView({ behavior: 'smooth' });
    <?php endif; ?>
});
</script>

Step 6: REST API Endpoint (api.php)

Create a new file named api.php in the project directory. This file will handle REST API requests for QR code generation and allows you to generate QR codes programmatically.

Some use cases for this API endpoint include:

  • Mobile app integration for dynamic QR code generation.
  • Third-party tool integration to provide QR code services.
  • AJAX-based QR code generation on web pages.
  • Headless applications that require QR code generation without a user interface.
  • Integrating QR code generation into other applications or services.
  • Automating QR code creation based on external data sources.
  • Providing QR code generation as a service to other developers.

API workflow:

  1. Receive JSON payload with QR code data and type.
  2. Validate input data and type.
  3. Generate QR code using QRCodeRenderer class.
  4. Return the generated QR code image as a base64-encoded string in the JSON response.
<?php 
header
('Content-Type: application/json');
header('Access-Control-Allow-Origin: *');
header('Access-Control-Allow-Methods: GET, POST, OPTIONS');

require_once 
'config.php';
require_once 
'includes/QRCodeGenerator.php';

// Include internal QR renderer
require_once 'includes/QRCodeRenderer.php';

// Handle preflight requests
if ($_SERVER['REQUEST_METHOD'] === 'OPTIONS') {
    
http_response_code(200);
    exit(
json_encode(['status' => 'ok']));
}

$response = [
    
'success' => false,
    
'data' => null,
    
'error' => null,
    
'qr_image' => null
];

try {
    
$generator = new QRCodeGenerator();
    
$type $_GET['type'] ?? $_POST['type'] ?? null;
    
    if (!
$type) {
        throw new 
Exception('QR type is required');
    }
    
    
$qr_data null;
    
    switch (
$type) {
        case 
'url':
            
$url $_GET['url'] ?? $_POST['url'] ?? $_GET['data'] ?? null;
            if (!
$url) throw new Exception('URL is required');
            
$qr_data $generator->generateURL($url);
            break;
            
        case 
'email':
            
$email $_GET['email'] ?? $_POST['email'] ?? null;
            
$subject $_GET['subject'] ?? $_POST['subject'] ?? '';
            
$body $_GET['body'] ?? $_POST['body'] ?? '';
            if (!
$email) throw new Exception('Email is required');
            
$qr_data $generator->generateEmail($email$subject$body);
            break;
            
        case 
'phone':
            
$phone $_GET['phone'] ?? $_POST['phone'] ?? null;
            if (!
$phone) throw new Exception('Phone number is required');
            
$qr_data $generator->generatePhone($phone);
            break;
            
        case 
'sms':
            
$phone $_GET['phone'] ?? $_POST['phone'] ?? null;
            
$message $_GET['message'] ?? $_POST['message'] ?? '';
            if (!
$phone) throw new Exception('Phone number is required');
            
$qr_data $generator->generateSMS($phone$message);
            break;
            
        case 
'contact':
            
$name $_GET['name'] ?? $_POST['name'] ?? null;
            
$phone $_GET['phone'] ?? $_POST['phone'] ?? '';
            
$email $_GET['email'] ?? $_POST['email'] ?? '';
            if (!
$name) throw new Exception('Contact name is required');
            
$qr_data $generator->generateContact($name$phone$email);
            break;
            
        case 
'vcard':
            
$name $_GET['name'] ?? $_POST['name'] ?? null;
            
$phone $_GET['phone'] ?? $_POST['phone'] ?? '';
            
$email $_GET['email'] ?? $_POST['email'] ?? '';
            
$org $_GET['org'] ?? $_POST['org'] ?? '';
            
$url $_GET['url'] ?? $_POST['url'] ?? '';
            if (!
$name) throw new Exception('Name is required');
            
$qr_data $generator->generateVCard($name$phone$email$org$url);
            break;
            
        case 
'wifi':
            
$ssid $_GET['ssid'] ?? $_POST['ssid'] ?? null;
            
$password $_GET['password'] ?? $_POST['password'] ?? '';
            
$security $_GET['security'] ?? $_POST['security'] ?? 'WPA';
            if (!
$ssid) throw new Exception('WiFi SSID is required');
            
$qr_data $generator->generateWiFi($ssid$password$security);
            break;
            
        case 
'event':
            
$title $_GET['title'] ?? $_POST['title'] ?? null;
            
$start $_GET['start'] ?? $_POST['start'] ?? '';
            
$end $_GET['end'] ?? $_POST['end'] ?? '';
            
$location $_GET['location'] ?? $_POST['location'] ?? '';
            if (!
$title) throw new Exception('Event title is required');
            
$qr_data $generator->generateEvent($title$start$end$location);
            break;
            
        case 
'location':
            
$lat $_GET['lat'] ?? $_POST['lat'] ?? $_GET['latitude'] ?? $_POST['latitude'] ?? null;
            
$lng $_GET['lng'] ?? $_POST['lng'] ?? $_GET['longitude'] ?? $_POST['longitude'] ?? null;
            if (!
$lat || !$lng) throw new Exception('Latitude and Longitude are required');
            
$qr_data $generator->generateLocation($lat$lng);
            break;
            
        case 
'app':
            
$url $_GET['url'] ?? $_POST['url'] ?? $_GET['app_url'] ?? $_POST['app_url'] ?? null;
            if (!
$url) throw new Exception('App URL is required');
            
$qr_data $generator->generateAppDownload($url);
            break;
            
        default:
            throw new 
Exception('Invalid QR code type: ' $type);
    }
    
    if (
$qr_data) {
        
// Generate QR code image using internal renderer
        
$size = (int)($_GET['size'] ?? $_POST['size'] ?? QR_CODE_SIZE);
        
        
$renderer = new QRCodeRenderer();
        
$qr_image $renderer->generate($qr_data$size);
        
        
$response['success'] = true;
        
$response['data'] = $qr_data;
        
$response['qr_image'] = $qr_image;
        
$response['type'] = $type;
        
$response['size'] = $size;
        
        
http_response_code(200);
    }
    
} catch (
Exception $e) {
    
$response['error'] = $e->getMessage();
    
http_response_code(400);
}

echo 
json_encode($responseJSON_PRETTY_PRINT JSON_UNESCAPED_SLASHES);
?>

API Usage Examples

You can also generate QR codes programmatically using the REST API. Here are some examples to call the API using GET and POST methods.

GET /api.php?type=url&data=https://example.com&size=300x300
POST /api.php (with JSON data)

GET Method
To generate a QR code using the GET method, you can use the following URL format:

https://projectdomain.com/api.php?type={type}&data={data}&size={size}

Replace `{type}` with the type of QR code you want to generate (e.g., url, text, email), `{data}` with the content you want to encode, and `{size}` with the desired dimensions of the QR code (e.g., 300×300).

POST Method
To generate a QR code using the POST method, you can send a JSON payload to the API endpoint. Here is an example using cURL:

curl -X POST https://projectdomain.com/api.php \
-H "Content-Type: application/json" \
-d '{"type": "url", "data": "https://example.com", "size": "300x300"}'

Make sure to set the `Content-Type` header to `application/json` and include the necessary parameters in the JSON body.

API Response
The API will respond with the generated QR code image in base64 format along with other relevant information. Here is an example of a successful response:

{
  "success": true,
  "data": "https://www.example.com",
  "qr_image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAASwAAAEsCAYAAAB5fY51A...",
  "type": "url",
  "size": 300
}

πŸ” Security & Best Practices

To ensure the security and reliability of your QR code generation, consider the following best practices:

  • Input sanitization before QR generation
  • Composer-based dependency management
  • Separation of logic (data vs rendering)
  • Reusable classes for QR generation
  • API and UI separation

You can further enhance it by:

  • Adding CSRF protection
  • Limiting QR content length
  • Adding rate-limiting to the API

πŸš€ Conclusion

This QR Code Generator using PHP is a clean, modern, and production-ready solution. With a structured architecture, reusable classes, and API support, it is suitable for both small tools and enterprise-level applications. If you’re looking for a scalable PHP QR Code solution, this implementation provides the perfect foundation.

Looking for expert assistance to implement or extend this script’s functionality? Submit a Service Request

Leave a reply

construction Need this implemented in your project? Request Implementation Help β†’ keyboard_double_arrow_up