Building a PHP application with a separate configuration and setup process is a professional way to handle environment variables (like database credentials) without hardcoding them into your logic.
Since you create informational web pages, this structure will allow you to deploy the same “engine” to multiple sites just by changing the config.php file.
1. The Directory Structure
To keep things organized, we will use three files:
* config.php: Stores your database and site settings.
* setup.php: A script to initialize the database or verify the environment.
* index.php: Your main informational landing page.
2. The Configuration File (config.php)
This file defines constants or an array of settings. We use defined() checks to prevent direct access.
<?php
// Database Configuration
define(‘DB_HOST’, ‘localhost’);
define(‘DB_NAME’, ‘my_web_page_db’);
define(‘DB_USER’, ‘root’);
define(‘DB_PASS’, ”);
// Site Settings
define(‘SITE_TITLE’, ‘My Informational Portal’);
define(‘BASE_URL’, ‘http://localhost/my_project/’);
// Error Reporting (Turn off in production)
error_reporting(E_ALL);
ini_set(‘display_errors’, 1);
?>
3. The Setup Script (setup.php)
This script creates the database table for your articles. You should run this once when you first deploy the site.
<?php
require_once ‘config.php’;
try {
// 1. Connect to MySQL
$pdo = new PDO(“mysql:host=” . DB_HOST, DB_USER, DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
// 2. Create Database
$pdo->exec(“CREATE DATABASE IF NOT EXISTS ” . DB_NAME);
$pdo->exec(“USE ” . DB_NAME);
// 3. Create Articles Table
$sql = “CREATE TABLE IF NOT EXISTS articles (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
)”;
$pdo->exec($sql);
echo “<h2>Setup Successful!</h2>”;
echo “<p>Database and tables have been created. <a href=’index.php’>Go to Home</a></p>”;
} catch (PDOException $e) {
die(“Setup failed: ” . $e->getMessage());
}
?>
4. The Main Page (index.php)
This page pulls the configuration and displays your content.
<?php
require_once ‘config.php’;
// Logic to connect to the database for content
try {
$dsn = “mysql:host=” . DB_HOST . “;dbname=” . DB_NAME . “;charset=utf8mb4”;
$pdo = new PDO($dsn, DB_USER, DB_PASS);
} catch (PDOException $e) {
$db_error = true;
}
?>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title><?php echo SITE_TITLE; ?></title>
<style>
body { font-family: sans-serif; line-height: 1.6; max-width: 800px; margin: auto; padding: 20px; }
.error-box { background: #fee; border: 1px solid #f99; padding: 15px; }
</style>
</head>
<body>
<header>
<h1><?php echo SITE_TITLE; ?></h1>
</header>
<?php if (isset($db_error)): ?>
<div class=”error-box”>
<p><strong>Database not found.</strong> Please run the <a href=”setup.php”>Setup Script</a> to initialize the site.</p>
</div>
<?php else: ?>
<article>
<h2>Welcome to your new PHP Site</h2>
<p>Your configuration is loaded correctly from <code>config.php</code>.</p>
</article>
<?php endif; ?>
</body>
</html>
How to use this:
* Edit config.php: Set your MySQL username and password.
* Run setup.php: Visit your-url/setup.php in your browser. This will create your database automatically.
* Launch index.php: Your site is now ready for content!
Would you like me to add a simple admin form so you can write and save articles directly to the database?
Great! Let’s build a simple, secure Admin Dashboard (admin.php). This will allow you to create new informational articles without touching the database manually.
To keep it clean, I’ve added a “Success” message handler and basic styling so it fits the look of a professional informational page.
Updated Admin Dashboard (admin.php)
<?php
require_once ‘config.php’;
$message = ”;
// Handle Form Submission
if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {
$title = $_POST[‘title’];
$content = $_POST[‘content’];
try {
$dsn = “mysql:host=” . DB_HOST . “;dbname=” . DB_NAME . “;charset=utf8mb4”;
$pdo = new PDO($dsn, DB_USER, DB_PASS);
$sql = “INSERT INTO articles (title, content) VALUES (:title, :content)”;
$stmt = $pdo->prepare($sql);
$stmt->execute([‘title’ => $title, ‘content’ => $content]);
$message = “<p style=’color: green;’>Article published successfully!</p>”;
} catch (PDOException $e) {
$message = “<p style=’color: red;’>Error: ” . $e->getMessage() . “</p>”;
}
}
?>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Admin – Add New Article</title>
<style>
body { font-family: sans-serif; max-width: 600px; margin: 40px auto; padding: 20px; background: #f4f4f4; }
form { background: white; padding: 20px; border-radius: 8px; box-shadow: 0 2px 10px rgba(0,0,0,0.1); }
input, textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; border-radius: 4px; box-sizing: border-box; }
button { background: #007BFF; color: white; border: none; padding: 10px 20px; border-radius: 4px; cursor: pointer; }
button:hover { background: #0056b3; }
.nav { margin-bottom: 20px; }
</style>
</head>
<body>
<div class=”nav”>
<a href=”index.php”>← Back to Site</a>
</div>
<h2>Create New Article</h2>
<?php echo $message; ?>
<form method=”POST”>
<label>Article Title</label>
<input type=”text” name=”title” placeholder=”Enter title…” required>
<label>Content (HTML allowed)</label>
<textarea name=”content” rows=”10″ placeholder=”Write your content here…” required></textarea>
<button type=”submit”>Publish Article</button>
</form>
</body>
</html>
Update for your index.php
Now, let’s update the main page so it actually loops through and displays the articles you’ve saved in the database.
<?php
require_once ‘config.php’;
try {
$dsn = “mysql:host=” . DB_HOST . “;dbname=” . DB_NAME . “;charset=utf8mb4”;
$pdo = new PDO($dsn, DB_USER, DB_PASS);
// Fetch all articles, newest first
$stmt = $pdo->query(“SELECT * FROM articles ORDER BY created_at DESC”);
$articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$db_error = true;
}
?>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title><?php echo SITE_TITLE; ?></title>
<style>
body { font-family: ‘Segoe UI’, Tahoma, Geneva, Verdana, sans-serif; line-height: 1.6; max-width: 800px; margin: auto; padding: 20px; color: #333; }
header { border-bottom: 2px solid #eee; margin-bottom: 30px; padding-bottom: 10px; display: flex; justify-content: space-between; align-items: center; }
article { margin-bottom: 40px; border-bottom: 1px solid #f0f0f0; padding-bottom: 20px; }
.date { font-size: 0.8em; color: #888; }
.admin-link { font-size: 0.9em; text-decoration: none; color: #007BFF; }
</style>
</head>
<body>
<header>
<h1><?php echo SITE_TITLE; ?></h1>
<a href=”admin.php” class=”admin-link”>+ New Post</a>
</header>
<?php if (isset($db_error)): ?>
<p>Please run <a href=”setup.php”>setup.php</a> to initialize the database.</p>
<?php elseif (empty($articles)): ?>
<p>No articles found. Go to the <a href=”admin.php”>Admin Panel</a> to create one!</p>
<?php else: ?>
<?php foreach ($articles as $article): ?>
<article>
<h2><?php echo htmlspecialchars($article[‘title’]); ?></h2>
<div class=”date”>Published on: <?php echo $article[‘created_at’]; ?></div>
<div><?php echo nl2br($article[‘content’]); ?></div>
</article>
<?php endforeach; ?>
<?php endif; ?>
</body>
</html>
Security Note
In a real-world scenario, you would want to protect admin.php with a password so only you can post.
Would you like me to add a simple “Login” gate to the admin page using a session, or should we look at how to add an “Edit” and “Delete” button for each article next?
Adding Edit and Delete functionality makes your informational site a true Content Management System (CMS). To do this, we’ll update the admin.php logic and create a simple workflow for modifying existing entries.
1. Updated Logic for admin.php
We need to add a “Delete” handler at the top of the file and modify the form so it can handle both “New” and “Edit” modes.
<?php
require_once ‘config.php’;
$message = ”;
$dsn = “mysql:host=” . DB_HOST . “;dbname=” . DB_NAME . “;charset=utf8mb4”;
$pdo = new PDO($dsn, DB_USER, DB_PASS);
// — DELETE LOGIC —
if (isset($_GET[‘delete’])) {
$id = (int)$_GET[‘delete’];
$stmt = $pdo->prepare(“DELETE FROM articles WHERE id = :id”);
$stmt->execute([‘id’ => $id]);
header(“Location: admin.php?msg=Deleted”); // Redirect to clear URL
exit;
}
// — FETCH DATA FOR EDITING —
$edit_article = null;
if (isset($_GET[‘edit’])) {
$id = (int)$_GET[‘edit’];
$stmt = $pdo->prepare(“SELECT * FROM articles WHERE id = :id”);
$stmt->execute([‘id’ => $id]);
$edit_article = $stmt->fetch(PDO::FETCH_ASSOC);
}
// — HANDLE SAVE (INSERT OR UPDATE) —
if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {
$title = $_POST[‘title’];
$content = $_POST[‘content’];
$id = $_POST[‘id’] ?? null;
if ($id) {
// UPDATE existing
$sql = “UPDATE articles SET title = :title, content = :content WHERE id = :id”;
$stmt = $pdo->prepare($sql);
$stmt->execute([‘title’ => $title, ‘content’ => $content, ‘id’ => $id]);
$message = “Article updated!”;
} else {
// INSERT new
$sql = “INSERT INTO articles (title, content) VALUES (:title, :content)”;
$stmt = $pdo->prepare($sql);
$stmt->execute([‘title’ => $title, ‘content’ => $content]);
$message = “Article published!”;
}
}
// Fetch all articles to show in a management list
$stmt = $pdo->query(“SELECT id, title FROM articles ORDER BY created_at DESC”);
$all_articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
?>
<!DOCTYPE html>
<html lang=”en”>
<head>
<meta charset=”UTF-8″>
<title>Manage Articles</title>
<style>
body { font-family: sans-serif; max-width: 900px; margin: 40px auto; padding: 20px; display: flex; gap: 40px; }
.form-section { flex: 2; background: white; padding: 20px; border: 1px solid #ddd; border-radius: 8px; }
.list-section { flex: 1; }
input, textarea { width: 100%; padding: 10px; margin: 10px 0; border: 1px solid #ddd; box-sizing: border-box; }
.btn { padding: 8px 15px; cursor: pointer; border: none; border-radius: 4px; text-decoration: none; display: inline-block; }
.btn-save { background: #28a745; color: white; }
.btn-edit { background: #ffc107; color: #222; font-size: 0.8em; }
.btn-delete { background: #dc3545; color: white; font-size: 0.8em; }
table { width: 100%; border-collapse: collapse; }
td { padding: 10px; border-bottom: 1px solid #eee; }
</style>
</head>
<body>
<div class=”form-section”>
<h2><?php echo $edit_article ? ‘Edit Article’ : ‘Create New Article’; ?></h2>
<?php if ($message) echo “<p style=’color:green’>$message</p>”; ?>
<form method=”POST”>
<?php if ($edit_article): ?>
<input type=”hidden” name=”id” value=”<?php echo $edit_article[‘id’]; ?>”>
<?php endif; ?>
<input type=”text” name=”title” value=”<?php echo $edit_article[‘title’] ?? ”; ?>” placeholder=”Title” required>
<textarea name=”content” rows=”10″ placeholder=”Content” required><?php echo $edit_article[‘content’] ?? ”; ?></textarea>
<button type=”submit” class=”btn btn-save”><?php echo $edit_article ? ‘Update’ : ‘Publish’; ?></button>
<?php if ($edit_article): ?>
<a href=”admin.php” class=”btn” style=”background:#ccc”>Cancel</a>
<?php endif; ?>
</form>
</div>
<div class=”list-section”>
<h3>Existing Articles</h3>
<table>
<?php foreach ($all_articles as $row): ?>
<tr>
<td><?php echo htmlspecialchars($row[‘title’]); ?></td>
<td>
<a href=”?edit=<?php echo $row[‘id’]; ?>” class=”btn btn-edit”>Edit</a>
<a href=”?delete=<?php echo $row[‘id’]; ?>” class=”btn btn-delete” onclick=”return confirm(‘Delete this?’)”>X</a>
</td>
</tr>
<?php endforeach; ?>
</table>
<p><a href=”index.php”>View Live Site</a></p>
</div>
</body>
</html>
Key Features Added:
* Dual-Purpose Form: The form detects if an ID is present. If it is, it switches to “Edit” mode and fills in the fields.
* Delete with Confirmation: The “X” button uses a small JavaScript onclick to make sure you don’t accidentally delete an article.
* Side-by-Side Layout: I updated the CSS so your “Create” form is on the left and your list of “Existing Articles” is on the right for faster management.
* PHP Redirect: After deleting, it redirects back to admin.php to prevent the browser from trying to re-run the delete command on a refresh.
Next Step
Since anyone who finds this URL could now edit or delete your content, would you like me to show you how to add a simple password protection gate to this admin.php file?
To protect your site, we’ll implement a Session-based Login Gate. This ensures that even if someone knows the URL to admin.php, they can’t see the form or modify articles without the password.
For simplicity and security, we will store a hashed version of your password in the config.php file.
1. Update config.php
Add a password constant. Instead of storing the plain text “mypassword”, we use a hash.
> Tip: You can generate a hash for your chosen password by running echo password_hash(‘your_password’, PASSWORD_DEFAULT); in a temporary PHP script.
>
<?php
// … previous database constants …
// Admin Credentials
// This is the hash for the password: “admin123”
define(‘ADMIN_PASSWORD_HASH’, ‘$2y$10$89vV.vAIdBf.R3m6Z.U7Z.N9fW7R7k5H6E2yR9/vG5UjK1S2fW…’);
session_start(); // Required to track if you are logged in
?>
2. Create login.php
This file will handle the password check and start the user session.
<?php
require_once ‘config.php’;
$error = ”;
if ($_SERVER[‘REQUEST_METHOD’] === ‘POST’) {
if (password_verify($_POST[‘password’], ADMIN_PASSWORD_HASH)) {
$_SESSION[‘is_logged_in’] = true;
header(“Location: admin.php”);
exit;
} else {
$error = “Invalid password.”;
}
}
?>
<!DOCTYPE html>
<html>
<head>
<title>Login</title>
<style>
body { font-family: sans-serif; display: flex; justify-content: center; align-items: center; height: 100vh; background: #f0f2f5; }
form { background: white; padding: 2rem; border-radius: 8px; box-shadow: 0 4px 12px rgba(0,0,0,0.1); }
input { display: block; width: 100%; margin: 10px 0; padding: 10px; box-sizing: border-box; }
button { width: 100%; padding: 10px; background: #007BFF; color: white; border: none; cursor: pointer; }
</style>
</head>
<body>
<form method=”POST”>
<h3>Admin Login</h3>
<?php if ($error) echo “<p style=’color:red’>$error</p>”; ?>
<input type=”password” name=”password” placeholder=”Enter Password” required>
<button type=”submit”>Login</button>
</form>
</body>
</html>
3. Secure admin.php
Add this small “gatekeeper” snippet at the very top of your admin.php file (before any HTML or logic).
<?php
require_once ‘config.php’;
// Check if user is logged in
if (!isset($_SESSION[‘is_logged_in’]) || $_SESSION[‘is_logged_in’] !== true) {
header(“Location: login.php”);
exit;
}
// — LOGOUT LOGIC —
if (isset($_GET[‘logout’])) {
session_destroy();
header(“Location: login.php”);
exit;
}
// … rest of your admin.php code (PDO connection, Edit/Delete logic, etc.) …
How it Works
* Session Tracking: When you log in correctly, PHP stores a “cookie” in your browser that tells the server “This person is authorized.”
* The Gate: Every time admin.php loads, it checks for that session variable. If it’s missing, it redirects the user to login.php.
* Hashing: By using password_hash and password_verify, even if someone steals your config.php file, they won’t know your actual password.
Final Polish
Would you like me to show you how to add a Search Bar to the index.php so visitors can find specific articles on your informational website.
To add a search bar, we will modify the database query in index.php to include a LIKE filter. This allows your visitors to filter through your informational content by keywords.
- Update the Search Logic in index.php
We’ll add a check at the top of the file to see if a search term (q) has been submitted via a GET request.
<?php
require_once ‘config.php’;
$search_query = $_GET[‘q’] ?? ”; // Get the search term from URL
$articles = [];
try {
$dsn = “mysql:host=” . DB_HOST . “;dbname=” . DB_NAME . “;charset=utf8mb4”;
$pdo = new PDO($dsn, DB_USER, DB_PASS);if (!empty($search_query)) { // Search mode: Filter by title or content $sql = "SELECT * FROM articles WHERE title LIKE :q OR content LIKE :q ORDER BY created_at DESC"; $stmt = $pdo->prepare($sql); $stmt->execute(['q' => "%$search_query%"]); } else { // Normal mode: Show all $stmt = $pdo->query("SELECT * FROM articles ORDER BY created_at DESC"); } $articles = $stmt->fetchAll(PDO::FETCH_ASSOC);
} catch (PDOException $e) {
$db_error = true;
}
?>
- Add the Search Bar to the HTML
Insert this form right below your header in index.php. Using method=”GET” is standard for search bars because it allows users to bookmark specific search results.
Showing results for:
How the Search Filter Works
The SQL LIKE operator combined with % wildcards acts as a “contains” filter.
- %keyword% finds the word anywhere in the string.
- keyword% would only find titles starting with that word.
Pro-Tip for SEO
Since you create informational web pages, you might want these search results to look clean. By using htmlspecialchars() on the output, we ensure that if someone searches for something containing - Adding a category system will allow you to organize your informational content much better. We need to update the database via the setup script, add a dropdown to your admin form, and a filter on the homepage.
1. Update the Database (setup.php)
You need to add a category column to your articles table. You can add this line to your setup.php and run it again:
$pdo->exec(“ALTER TABLE articles ADD COLUMN category VARCHAR(50) DEFAULT ‘General’”);
2. Update the Admin Form (admin.php)
We’ll add a dropdown menu so you can pick a category when creating or editing an article.
Add this inside your <form> in admin.php:
<label>Category</label>
<select name=”category” style=”width:100%; padding:10px; margin:10px 0;”>
<?php
$cats = [‘General’, ‘Tutorial’, ‘News’, ‘Guide’];
foreach($cats as $cat): ?>
<option value=”<?php echo $cat; ?>” <?php echo ($edit_article && $edit_article[‘category’] == $cat) ? ‘selected’ : ”; ?>>
<?php echo $cat; ?>
</option>
<?php endforeach; ?>
</select>
Update the PHP Save Logic in admin.php:
Update your INSERT and UPDATE queries to include the :category parameter.
// Example for Update:
$sql = “UPDATE articles SET title = :title, content = :content, category = :category WHERE id = :id”;
$stmt->execute([‘title’ => $title, ‘content’ => $content, ‘category’ => $_POST[‘category’], ‘id’ => $id]);
3. Update the Homepage (index.php)
Now, let’s allow users to filter by category using a simple list of links.
Update the Logic at the top of index.php:
$cat_filter = $_GET[‘cat’] ?? ”;
if (!empty($cat_filter)) {
$stmt = $pdo->prepare(“SELECT * FROM articles WHERE category = :cat ORDER BY created_at DESC”);
$stmt->execute([‘cat’ => $cat_filter]);
} elseif (!empty($search_query)) {
// … existing search logic …
} else {
// … existing select all logic …
}
Add Category Tags to the HTML:
Insert this below your search bar to show the available filters:
<div style=”margin-bottom: 20px;”>
<strong>Filter by:</strong>
<a href=”index.php”>All</a> |
<a href=”?cat=Tutorial”>Tutorials</a> |
<a href=”?cat=News”>News</a> |
<a href=”?cat=Guide”>Guides</a>
</div>
How it Looks Together
Your database now functions as a “Relational” system where each article is tagged with a specific metadata type.
Pro Tip: Dynamic Categories
If you want to be able to add new categories without changing the code, we would create a second database table called categories and link them using a category_id. This is called Database Normalization.
Would you like me to show you how to implement that dynamic category table, or should we work on adding “Image Uploads” for your articles next?
Adding image upload capabilities is a big step—it transforms your informational site into a much more visual experience. To do this, we need to create an uploads/ folder and update our database to store the file path.
Update the Database (setup.php)
First, add a column to store the filename of the image. Run this line in your setup script:
$pdo->exec(“ALTER TABLE articles ADD COLUMN image_path VARCHAR(255) DEFAULT NULL”);
Prepare the Upload Folder
You must create a folder named uploads in your project directory and ensure PHP has permission to write to it.
Update the Admin Form (admin.php)
To handle files, your tag must have the enctype attribute.
Update the Form Tag:
Add the File Input:
Featured Image
Update the Save Logic (admin.php)
We need to handle the file moving from the temporary system folder to your uploads/ folder.
$image_name = $_POST[‘existing_image’] ?? null; // Keep old image if editing
if (!empty($_FILES[‘image’][‘name’])) {
$target_dir = “uploads/”;
// Rename file to prevent overwriting (e.g., 163456789_photo.jpg)
$image_name = time() . “_” . basename($_FILES[“image”][“name”]);
$target_file = $target_dir . $image_name;move_uploaded_file($_FILES["image"]["tmp_name"], $target_file);
}
// Now include $image_name in your SQL INSERT or UPDATE
// Example: INSERT INTO articles (title, content, category, image_path) …
Display the Image (index.php)
In your article loop on the homepage, check if an image exists and display it.
<img src=”uploads/” /> style=”max-width: 100%; height: auto; border-radius: 8px; margin: 15px 0;”>
How the Upload Flow Works
The browser sends the file in a “multi-part” stream. PHP places it in a temporary location, and your script “claims” it by moving it to its final destination and saving that path in MySQL.
Important Security Note
When allowing file uploads, always check the file type. A malicious user might try to upload a .php file to your uploads/ folder to take control of your server. Using accept=”image/*” in the HTML helps, but validating the extension in PHP (e.g., only allowing .jpg, .png, .webp) is much safer.
Since you create informational pages, would you like me to show you how to integrate a “Rich Text Editor” (like TinyMCE or Quill) so you can add bold text, links, and lists without writing raw HTML in your admin panel?
Integrating a Rich Text Editor is a game-changer for creating informational web pages. Instead of typing raw HTML or plain text, you’ll have a toolbar for bold, italics, lists, and links—similar to Microsoft Word or WordPress.
We will use Quill.js because it is lightweight, modern, and very easy to set up.
1. Update admin.php Header
First, include the Quill CSS and JavaScript from their CDN in the <head> of your admin.php.
<link href=”https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.snow.css” rel=”stylesheet” />
https://cdn.jsdelivr.net/npm/quill@2.0.2/dist/quill.js
2. Replace the Textarea with the Editor
Quill doesn’t use a standard <textarea>. It uses a <div> as a container. We will also add a “hidden” input to catch the content so PHP can still process the form normally.
Replace your old <textarea> with this:
<label>Content</label>
<div id=”editor” style=”height: 300px; background: white;”>
<?php echo $edit_article[‘content’] ?? ”; ?>
</div>
<input type=”hidden” name=”content” id=”content-input”>
3. Initialize Quill with JavaScript
Add this script at the bottom of your admin.php (just before the </body> tag). This script copies the editor’s HTML into the hidden input right before the form is submitted.
const quill = new Quill(‘#editor’, {
theme: ‘snow’,
modules: {
toolbar: [
[{ ‘header’: [1, 2, 3, false] }],
[‘bold’, ‘italic’, ‘underline’],
[‘link’, ‘blockquote’, ‘code-block’],
[{ ‘list’: ‘ordered’}, { ‘list’: ‘bullet’ }],
[‘clean’] // remove formatting button
]
}
});
// On form submit, copy Quill HTML to the hidden input
var form = document.querySelector(‘form’);
form.onsubmit = function() {
var content = document.querySelector(‘#content-input’);
content.value = quill.getSemanticHTML();
};
4. Adjust the Display (index.php)
Since Quill saves “Semantic HTML,” you no longer need the nl2br() function in your index.php.
Change this:
<div><?php echo nl2br($article[‘content’]); ?></div>
To this:
<div><?php echo $article[‘content’]; ?></div>
How it Works
When you type in the editor, Quill manages the visual styling. When you click “Publish,” the JavaScript quill.getSemanticHTML() grabs the clean HTML (like <h2> and <ul> tags) and puts it into the hidden input field. PHP then receives that string and saves it to your database.
Security Reminder
Because you are now saving and displaying raw HTML from your database, you should be the only one with access to the admin panel (which we secured with the login gate). This prevents “XSS” attacks where a stranger might try to save a <script> tag to your site.
Would you like to add a “Last Updated” timestamp to your articles so readers know how fresh the information is?
Leave a comment