Why Choose CodeIgniter 4 + PHP QR Code Library for Generating QR Codes?
CodeIgniter 4 is lightweight, fast, secure, and fully compatible with modern PHP (8.2+). Pairing it with the free, open-source PHP QR Code library (from sourceforge) gives you:
- Full control: Customize size, error correction level (L/M/Q/H), colors, and output format without external services.
- Server-side storage: Save PNG files permanently on your server for caching, logging, or embedding in emails/PDFs.
- Multiple data types: Easily support URL, plain text, phone (tel:), SMS, email (mailto:), Skype, vCard, Wi-Fi, and more in one tool.
- No API keys or internet required: Everything runs locally — great for privacy-sensitive or offline-capable apps.
- Cost-free and reliable: No subscription fees, and the library has been battle-tested for years.
Alternatives like simplesoftwareio/simple-qrcode (Composer package) are more modern and Laravel-friendly, but the classic PHP QR Code works perfectly in pure CodeIgniter 4 with minimal setup. This tutorial uses it for simplicity and broad compatibility.
Drawbacks to note: The library is older (no built-in logo overlay or advanced styling), so for fancy designs consider adding GD/ImageMagick post-processing or switching packages later.

Table Of Content
1 Prerequisites
- PHP 8.2 or higher
- GD extension enabled (for image generation)
- Composer installed
- Basic CodeIgniter 4 knowledge
2 How to Generate and Store QR Codes in CodeIgniter 4 (Overview)
This step-by-step tutorial shows you how to build a complete QR code generator in CodeIgniter 4 that:
- Installs the PHP QR Code library and wraps it in a custom CodeIgniter library.
- Handles form input for multiple QR types (URL, text, phone, SMS, email, vCard, etc.).
- Generates high-quality PNG images with customizable error correction and size.
- Stores images permanently in a server folder (publicly accessible).
- Displays the generated QR instantly with success feedback.
By the end, you'll have a working app at http://your-site/qrcode — ready for production use or extension (e.g., user accounts, download buttons, analytics tracking).
Time required: 30–60 minutes
Skill level: Intermediate PHP/CodeIgniter
Updated for: CodeIgniter 4.5+ and PHP 8.2+ =
3 Create / Install a Codeigniter 4 Project
3.1 Install Codeigniter 4 Project
Use the following command to set up a new project:
composer create-project codeigniter4/appstarter ci4-qr-generator
Then, navigate to your project directory:
cd ci4-qr-generator
3.2 Configure Environment (.env)
Also we can do this in command Line.
Open project in Command Line
sudo cp env .env
Above command will create a copy of env file to .env file. Now we are ready to set environment variables.
Configure Development Mode
CodeIgniter starts up in production mode by default. You need to make it in development mode to debug or check any error if you are working with application.
Open .env file from root.
# CI_ENVIRONMENT = production
CI_ENVIRONMENT = development
Now application is in development mode.
4 Install the QR Code Library & Wrapper
Download PHP QR Code and extract to app/ThirdParty/qrcode/.
Create app/Libraries/Ciqrcode.php:
<?php
namespace App\Libraries;
class Ciqrcode {
public function __construct() {
include_once APPPATH . 'ThirdParty/qrcode/qrlib.php';
}
public function generate($data, $savename = false, $level = 'L', $size = 10, $margin = 2, $colorFg = [0,0,0], $colorBg = [255,255,255]) {
$config = [
'cacheable' => true,
'cachedir' => WRITEPATH . 'cache/',
'errorcorrection_level' => $level,
'quality' => false,
'size' => $size,
'margin' => $margin,
'color_fg' => $colorFg,
'color_bg' => $colorBg,
];
if ($savename !== false) {
QRcode::png($data, $savename, $level, $size, $margin, false, $config['color_fg'][0], $config['color_fg'][1], $config['color_fg'][2], $config['color_bg'][0], $config['color_bg'][1], $config['color_bg'][2]);
return $savename;
} else {
QRcode::png($data, null, $level, $size, $margin);
}
}
}
5 Supported QR Code Types & Examples
1.URL QR Code: Specify the website URL, including the protocol:
Specify the website URL including the protocol (HTTP or HTTPS) to recognize the QR code as a URL.
$qrContent = 'https://getsamplecode.com/';
2.Text QR Code: Specify the text to generate the QR code:Specify the Text to Generate QR Code.
$qrContent = 'QR Code Generated by GetSampleCode';
3.Phone NumberSpecify the Phone Number including Country Code to Generate QR Code.
$qrContent = 'tel:+16471234567';
4.SMSSpecify the Phone Number including Country Code and pre filled message to Generate QR Code.
$qrContent = 'sms:+16471234567:Samplemessage';
5.EMAILSpecify the Email Address to Generate QR Code.
$qrContent = ''mailto:getsamplecode@gmail.com';';
6 Create Controller: QrcodeController
Create app/Controllers/QrcodeController.php:
<?php
namespace App\Controllers;
use CodeIgniter\Controller;
use App\Libraries\Ciqrcode;
class QrcodeController extends Controller {
protected $ciqrcode;
public function __construct() {
$this->ciqrcode = new Ciqrcode();
}
public function index() {
$data = [];
if (session()->has('qr_code_path')) {
$data['qr_code_path'] = session()->getFlashdata('qr_code_path');
$data['success'] = session()->getFlashdata('success');
}
return view('qrcode/index', $data);
}
public function store() {
$type = $this->request->getPost('qrcode_type');
$data = '';
switch ($type) {
case 'url':
$data = $this->request->getPost('url');
break;
case 'text':
$data = $this->request->getPost('text');
break;
case 'phone':
$data = 'tel:' . $this->request->getPost('phone');
break;
case 'sms':
$data = 'sms:' . $this->request->getPost('sms_phone') . ':' . $this->request->getPost('sms_text');
break;
case 'email':
$data = 'mailto:' . $this->request->getPost('email') . '?subject=' . urlencode($this->request->getPost('email_subject')) . '&body=' . urlencode($this->request->getPost('email_body'));
break;
case 'skype':
$data = 'skype:' . $this->request->getPost('skype_username') . '?' . $this->request->getPost('skype_action');
break;
case 'vcard':
$data = "BEGIN:VCARD\nVERSION:3.0\nFN:" . $this->request->getPost('vcard_name') . "\nORG:" . $this->request->getPost('vcard_org') . "\nTEL:" . $this->request->getPost('vcard_phone') . "\nEMAIL:" . $this->request->getPost('vcard_email') . "\nEND:VCARD";
break;
default:
return redirect()->back()->with('error', 'Invalid QR type');
}
if (empty($data)) {
return redirect()->back()->with('error', 'Data is required');
}
// Generate unique filename
$hex = bin2hex(random_bytes(8)); // Unique hash
$dir = FCPATH . 'assets/media/qrcode/';
if (!is_dir($dir)) {
mkdir($dir, 0777, true);
}
$filename = $hex . '.png';
$fullpath = $dir . $filename;
// Generate QR code with high error correction
$this->ciqrcode->generate($data, $fullpath, 'H', 10);
$publicPath = 'assets/media/qrcode/' . $filename;
return redirect()->to('/qrcode')->with('qr_code_path', $publicPath)->with('success', 'QR Code Generated Successfully!');
}
}
7 Create Index View File
Create app/Views/qrcode/index.php:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>QR Code Generator</title>
<style>
.qr-form { max-width: 600px; }
.field-group { display: none; }
</style>
</head>
<body>
<h2>Generate QR Code</h2>
<?php if (isset($success)): ?>
<p style="color: green;"><?= $success ?></p>
<img src="<?= base_url($qr_code_path) ?>" alt="Generated QR Code">
<?php endif; ?>
<form method="post" action="<?= base_url('qrcode/store') ?>" class="qr-form">
<label for="qrcode_type">QR Code Type:</label>
<select id="qrcode_type" name="qrcode_type" onchange="showFields(this.value)">
<option value="url">URL</option>
<option value="text">Text</option>
<option value="phone">Phone</option>
<option value="sms">SMS</option>
<option value="email">Email</option>
<option value="skype">Skype</option>
<option value="vcard">vCard</option>
</select>
<br><br>
<div id="url_fields" class="field-group">
<label for="url">URL:</label>
<input type="url" name="url" id="url">
</div>
<div id="text_fields" class="field-group">
<label for="text">Text:</label>
<input type="text" name="text" id="text">
</div>
<div id="phone_fields" class="field-group">
<label for="phone">Phone Number:</label>
<input type="tel" name="phone" id="phone">
</div>
<div id="sms_fields" class="field-group">
<label for="sms_phone">Phone Number:</label>
<input type="tel" name="sms_phone" id="sms_phone">
<label for="sms_text">Message:</label>
<input type="text" name="sms_text" id="sms_text">
</div>
<div id="email_fields" class="field-group">
<label for="email">Email Address:</label>
<input type="email" name="email" id="email">
<label for="email_subject">Subject:</label>
<input type="text" name="email_subject" id="email_subject">
<label for="email_body">Body:</label>
<textarea name="email_body" id="email_body"></textarea>
</div>
<div id="skype_fields" class="field-group">
<label for="skype_username">Skype Username:</label>
<input type="text" name="skype_username" id="skype_username">
<label for="skype_action">Action (e.g., call, chat):</label>
<input type="text" name="skype_action" id="skype_action">
</div>
<div id="vcard_fields" class="field-group">
<label for="vcard_name">Full Name:</label>
<input type="text" name="vcard_name" id="vcard_name">
<label for="vcard_org">Organization:</label>
<input type="text" name="vcard_org" id="vcard_org">
<label for="vcard_phone">Phone:</label>
<input type="tel" name="vcard_phone" id="vcard_phone">
<label for="vcard_email">Email:</label>
<input type="email" name="vcard_email" id="vcard_email">
</div>
<br>
<button type="submit">Generate QR Code</button>
</form>
<script>
function showFields(type) {
document.querySelectorAll('.field-group').forEach(el => el.style.display = 'none');
document.getElementById(type + '_fields').style.display = 'block';
}
// Show default
showFields('url');
</script>
</body>
</html>
8 Define a Route
app/Config/Routes.php
use CodeIgniter\Router\RouteCollection;
$routes->get('/', 'Home::index');
$routes->get('qrcode', 'QrcodeController::index');
$routes->post('store', 'QrcodeController::store');
9 Folder Structure
ci4-qr-generator/
├── app/
│ ├── Config/
│ │ └── Routes.php
│ ├── Controllers/
│ │ └── QrcodeController.php
│ ├── Libraries/
│ │ └── Ciqrcode.php
│ ├── ThirdParty/
│ │ └── qrcode/
│ │ └── qrlib.php (and other library files)
│ └── Views/
│ └── qrcode/
│ └── index.php
├── public/
│ └── assets/
│ └── media/
│ └── qrcode/ (will be created dynamically)
├── .env
└── composer.json
10 Run Web Server to Test the App
- Start the server:
php spark serve - Visit
http://localhost:8080/qrcode - Select a type, enter data, submit, and see the generated QR code displayed.
Troubleshooting: Ensure GD is enabled (php -i | grep GD). Check write permissions on public/assets/media/qrcode/.
11 Conclusion
You now have a complete, working QR code generator in CodeIgniter 4. For production:
- Use Composer packages like
simplesoftwareio/simple-qrcodefor alternatives:composer require simplesoftwareio/simple-qrcode. - Add input validation with CodeIgniter's Validation library.
- Implement rate limiting to prevent abuse.
- Compress PNG images for better performance.
- Store in cloud (e.g., AWS S3) for scalability.
- Test QR codes with a scanner app to verify.
Written by Revathi M
PHP Developer & Technical Writer · 10+ years building web applications with CodeIgniter and Laravel
Revathi specializes in PHP backend development, authentication systems, and REST API design. She writes practical, production-tested tutorials at Get Sample Code to help developers build secure applications faster.
Frequently Asked Questions
You need PHP 8.2 or higher, the PHP GD extension enabled, Composer, and a fresh CodeIgniter 4 project.
Run `composer create-project codeigniter4/appstarter ci4-qrcode-app`, then `cd ci4-qrcode-app`.
The open-source PHP QR Code library (phpqrcode) from SourceForge, placed manually in `app/ThirdParty/qrcode`.
Download the library from https://sourceforge.net/projects/phpqrcode/, extract it, and place the files in `app/ThirdParty/qrcode`.
Create `app/Libraries/Ciqrcode.php` with a class that loads the third-party library and provides an `initialize()` and `generate()` method.
Run `php spark make:controller QrcodeController`, then add `index()` for the form and `store()` for processing.
In the `assets/media/qrcode/` directory (created automatically if it doesn't exist).
Using `bin2hex($data) . '.png'` to create a unique hash-based filename from the QR content.
Text, URL, Phone, SMS, Email, Skype, and Business Card (vCard-like).
A dropdown selects the type, and JavaScript (`choose_content()`) shows/hides relevant input fields.
The example sets both 'black' and 'white' colors to [255,255,255] (white). Change 'black' to something dark, e.g., [0,0,0].
In the controller, configure `$config` (e.g., 'size' => '1024', 'cacheable' => true) and pass params like 'level' => 'H' and 'size' => 10 to `generate()`.
Yes, for PNG generation. Check with `phpinfo()` or `extension_loaded('gd')`.
Start the server with `php spark serve`, then visit `http://localhost:8080/qrcode` (or the defined route).
