Simple Blog PlatformPHP, MySQL

👤 Sharing: AI
```php
<?php

// Database configuration
$host = 'localhost';
$username = 'your_username'; // Replace with your MySQL username
$password = 'your_password'; // Replace with your MySQL password
$database = 'your_database';   // Replace with your database name

// Establish database connection
try {
    $db = new PDO("mysql:host=$host;dbname=$database;charset=utf8", $username, $password);
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
} catch (PDOException $e) {
    die("Database connection failed: " . $e->getMessage());
}


// --- Helper Functions ---

function escape($html) {
    return htmlspecialchars($html, ENT_QUOTES, 'UTF-8');
}


// --- Routing and Controller Logic ---

$action = isset($_GET['action']) ? $_GET['action'] : 'home';

switch ($action) {
    case 'home':
        include 'controllers/home_controller.php';
        break;
    case 'post':
        include 'controllers/post_controller.php';
        break;
    case 'create':
        include 'controllers/create_controller.php';
        break;
    case 'edit':
        include 'controllers/edit_controller.php';
        break;
    case 'delete':
        include 'controllers/delete_controller.php';
        break;
    default:
        include 'controllers/404_controller.php';
        break;
}
?>
```

**controllers/home_controller.php:**

```php
<?php

// Fetch all blog posts
$stmt = $db->query("SELECT id, title, content, created_at FROM posts ORDER BY created_at DESC");
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);

include 'views/home.php';

?>
```

**controllers/post_controller.php:**

```php
<?php

if (isset($_GET['id']) && is_numeric($_GET['id'])) {
    $postId = (int)$_GET['id'];

    $stmt = $db->prepare("SELECT id, title, content, created_at FROM posts WHERE id = ?");
    $stmt->execute([$postId]);
    $post = $stmt->fetch(PDO::FETCH_ASSOC);

    if ($post) {
        include 'views/post.php';
    } else {
        include 'controllers/404_controller.php';
    }
} else {
    include 'controllers/404_controller.php';
}

?>
```

**controllers/create_controller.php:**

```php
<?php

if ($_SERVER['REQUEST_METHOD'] === 'POST') {
    $title = isset($_POST['title']) ? trim($_POST['title']) : '';
    $content = isset($_POST['content']) ? trim($_POST['content']) : '';

    if (empty($title) || empty($content)) {
        $error = "Title and content are required.";
        include 'views/create.php';
    } else {
        try {
            $stmt = $db->prepare("INSERT INTO posts (title, content, created_at) VALUES (?, ?, NOW())");
            $stmt->execute([$title, $content]);

            header("Location: index.php"); // Redirect to homepage
            exit();

        } catch (PDOException $e) {
            $error = "Error creating post: " . $e->getMessage();
            include 'views/create.php';
        }
    }
} else {
    include 'views/create.php';
}

?>
```

**controllers/edit_controller.php:**

```php
<?php

if (isset($_GET['id']) && is_numeric($_GET['id'])) {
    $postId = (int)$_GET['id'];

    // Fetch the post to edit
    $stmt = $db->prepare("SELECT id, title, content FROM posts WHERE id = ?");
    $stmt->execute([$postId]);
    $post = $stmt->fetch(PDO::FETCH_ASSOC);

    if (!$post) {
        include 'controllers/404_controller.php';
        exit();
    }

    if ($_SERVER['REQUEST_METHOD'] === 'POST') {
        $title = isset($_POST['title']) ? trim($_POST['title']) : '';
        $content = isset($_POST['content']) ? trim($_POST['content']) : '';

        if (empty($title) || empty($content)) {
            $error = "Title and content are required.";
        } else {
            try {
                $stmt = $db->prepare("UPDATE posts SET title = ?, content = ? WHERE id = ?");
                $stmt->execute([$title, $content, $postId]);

                header("Location: index.php?action=post&id=" . $postId); // Redirect to updated post
                exit();

            } catch (PDOException $e) {
                $error = "Error updating post: " . $e->getMessage();
            }
        }
    }

    include 'views/edit.php';

} else {
    include 'controllers/404_controller.php';
}
?>
```

**controllers/delete_controller.php:**

```php
<?php

if (isset($_GET['id']) && is_numeric($_GET['id'])) {
    $postId = (int)$_GET['id'];

    // Confirm deletion (optional: you could add a confirmation page)
    try {
        $stmt = $db->prepare("DELETE FROM posts WHERE id = ?");
        $stmt->execute([$postId]);

        header("Location: index.php"); // Redirect to homepage
        exit();

    } catch (PDOException $e) {
        die("Error deleting post: " . $e->getMessage()); // Handle error more gracefully in a real app.
    }

} else {
    include 'controllers/404_controller.php';
}
?>
```

**controllers/404_controller.php:**

```php
<?php
$title = "Page Not Found";
include 'views/404.php';
?>
```

**views/home.php:**

```php
<!DOCTYPE html>
<html>
<head>
    <title>Simple Blog</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <h1>Simple Blog</h1>
        <nav>
            <a href="index.php">Home</a> | <a href="index.php?action=create">Create New Post</a>
        </nav>
    </header>

    <main>
        <?php if (empty($posts)): ?>
            <p>No posts yet.  <a href="index.php?action=create">Create the first one!</a></p>
        <?php else: ?>
            <?php foreach ($posts as $post): ?>
                <article>
                    <h2><a href="index.php?action=post&id=<?php echo escape($post['id']); ?>"><?php echo escape($post['title']); ?></a></h2>
                    <p class="date">Posted on <?php echo escape(date('F j, Y', strtotime($post['created_at']))); ?></p>
                    <p><?php echo substr(escape($post['content']), 0, 200); ?>...</p>
                    <p><a href="index.php?action=post&id=<?php echo escape($post['id']); ?>">Read More</a> | <a href="index.php?action=edit&id=<?php echo escape($post['id']); ?>">Edit</a> | <a href="index.php?action=delete&id=<?php echo escape($post['id']); ?>" onclick="return confirm('Are you sure you want to delete this post?')">Delete</a></p>
                </article>
            <?php endforeach; ?>
        <?php endif; ?>
    </main>

    <footer>
        <p>&copy; <?php echo date('Y'); ?> Simple Blog</p>
    </footer>
</body>
</html>
```

**views/post.php:**

```php
<!DOCTYPE html>
<html>
<head>
    <title><?php echo escape($post['title']); ?> - Simple Blog</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <h1>Simple Blog</h1>
        <nav>
            <a href="index.php">Home</a> | <a href="index.php?action=create">Create New Post</a>
        </nav>
    </header>

    <main>
        <article>
            <h2><?php echo escape($post['title']); ?></h2>
            <p class="date">Posted on <?php echo escape(date('F j, Y', strtotime($post['created_at']))); ?></p>
            <p><?php echo escape($post['content']); ?></p>
            <p><a href="index.php?action=edit&id=<?php echo escape($post['id']); ?>">Edit</a> | <a href="index.php?action=delete&id=<?php echo escape($post['id']); ?>" onclick="return confirm('Are you sure you want to delete this post?')">Delete</a></p>
        </article>
        <a href="index.php">Back to Home</a>
    </main>

    <footer>
        <p>&copy; <?php echo date('Y'); ?> Simple Blog</p>
    </footer>
</body>
</html>
```

**views/create.php:**

```php
<!DOCTYPE html>
<html>
<head>
    <title>Create New Post - Simple Blog</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <h1>Simple Blog</h1>
        <nav>
            <a href="index.php">Home</a> | <a href="index.php?action=create">Create New Post</a>
        </nav>
    </header>

    <main>
        <h2>Create New Post</h2>

        <?php if (isset($error)): ?>
            <p class="error"><?php echo escape($error); ?></p>
        <?php endif; ?>

        <form method="post" action="index.php?action=create">
            <label for="title">Title:</label><br>
            <input type="text" id="title" name="title" required><br><br>

            <label for="content">Content:</label><br>
            <textarea id="content" name="content" rows="10" cols="50" required></textarea><br><br>

            <button type="submit">Publish</button>
        </form>

        <a href="index.php">Back to Home</a>
    </main>

    <footer>
        <p>&copy; <?php echo date('Y'); ?> Simple Blog</p>
    </footer>
</body>
</html>
```

**views/edit.php:**

```php
<!DOCTYPE html>
<html>
<head>
    <title>Edit Post - Simple Blog</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <h1>Simple Blog</h1>
        <nav>
            <a href="index.php">Home</a> | <a href="index.php?action=create">Create New Post</a>
        </nav>
    </header>

    <main>
        <h2>Edit Post</h2>

        <?php if (isset($error)): ?>
            <p class="error"><?php echo escape($error); ?></p>
        <?php endif; ?>

        <form method="post" action="index.php?action=edit&id=<?php echo escape($post['id']); ?>">
            <label for="title">Title:</label><br>
            <input type="text" id="title" name="title" value="<?php echo escape($post['title']); ?>" required><br><br>

            <label for="content">Content:</label><br>
            <textarea id="content" name="content" rows="10" cols="50" required><?php echo escape($post['content']); ?></textarea><br><br>

            <button type="submit">Update</button>
        </form>

        <a href="index.php?action=post&id=<?php echo escape($post['id']); ?>">Back to Post</a> | <a href="index.php">Back to Home</a>
    </main>

    <footer>
        <p>&copy; <?php echo date('Y'); ?> Simple Blog</p>
    </footer>
</body>
</html>
```

**views/404.php:**

```php
<!DOCTYPE html>
<html>
<head>
    <title><?php echo escape($title); ?> - Simple Blog</title>
    <link rel="stylesheet" href="css/style.css">
</head>
<body>
    <header>
        <h1>Simple Blog</h1>
        <nav>
            <a href="index.php">Home</a> | <a href="index.php?action=create">Create New Post</a>
        </nav>
    </header>

    <main>
        <h2><?php echo escape($title); ?></h2>
        <p>Sorry, the page you requested could not be found.</p>
        <a href="index.php">Back to Home</a>
    </main>

    <footer>
        <p>&copy; <?php echo date('Y'); ?> Simple Blog</p>
    </footer>
</body>
</html>
```

**css/style.css:**

```css
body {
    font-family: sans-serif;
    margin: 20px;
    line-height: 1.6;
}

header {
    background-color: #f0f0f0;
    padding: 10px;
    text-align: center;
    margin-bottom: 20px;
}

nav a {
    margin: 0 10px;
}

main {
    max-width: 800px;
    margin: 0 auto;
}

article {
    margin-bottom: 30px;
    padding: 15px;
    border: 1px solid #ddd;
}

article h2 a {
    text-decoration: none;
    color: #333;
}

.date {
    font-style: italic;
    color: #777;
    margin-bottom: 10px;
}

footer {
    text-align: center;
    margin-top: 30px;
    padding-top: 10px;
    border-top: 1px solid #ddd;
}

.error {
    color: red;
}
```

**Database Setup:**

1.  **Create a Database:** In your MySQL environment (e.g., phpMyAdmin, MySQL Workbench), create a database named `your_database` (or whatever you specified in `$database`).

2.  **Create the `posts` table:**  Execute the following SQL query in your database:

```sql
CREATE TABLE posts (
    id INT AUTO_INCREMENT PRIMARY KEY,
    title VARCHAR(255) NOT NULL,
    content TEXT NOT NULL,
    created_at DATETIME NOT NULL
);
```

**Key Improvements and Explanations:**

*   **PDO for Database Interaction:**  Uses PDO (PHP Data Objects) for database interaction. PDO provides a consistent interface to access different databases and supports prepared statements, which help prevent SQL injection vulnerabilities.
*   **Error Handling:**  Includes basic error handling using `try...catch` blocks for database operations.  A more robust application would log errors and handle them more gracefully.
*   **Prepared Statements:**  Uses prepared statements with placeholders (e.g., `?`) to prevent SQL injection.  The values are bound separately using `$stmt->execute()`.
*   **Input Validation and Sanitization:**  `trim()` is used to remove whitespace from user inputs.  `htmlspecialchars()` with `ENT_QUOTES` is used to escape HTML entities, preventing XSS (Cross-Site Scripting) vulnerabilities.  It is vital to ALWAYS sanitize user input.
*   **Clear Routing:**  Uses a simple routing system based on the `action` GET parameter.  This makes the code more organized and easier to maintain.
*   **Controller-View Separation:** Separates the application logic (controllers) from the presentation (views). This follows the MVC (Model-View-Controller) pattern, improving code organization and maintainability.
*   **Includes:**  Uses `include` statements to include the appropriate controller and view files.
*   **`escape()` function:**  Creates a reusable helper function to escape output for HTML.  This makes the code more DRY (Don't Repeat Yourself) and easier to read.
*   **CSS Styling:** Includes a basic `style.css` file to provide some basic styling.
*   **Delete Confirmation:** Includes a JavaScript confirmation dialog before deleting a post to prevent accidental deletions.
*   **Clearer File Structure:**  Uses separate directories for controllers (`controllers/`) and views (`views/`).  This makes the project structure more organized.
*   **Error Messages:**  Provides more informative error messages to the user.
*   **Redirects:** Uses `header("Location: ...")` to redirect the user after successful form submissions.  `exit()` is called after `header()` to prevent further script execution.
*   **404 Handling:**  Includes a 404 (Page Not Found) controller and view.
*   **`created_at` field:** The `posts` table now includes a `created_at` field to store the date and time when the post was created, allowing for sorting by date.
*   **Improved Comments:**  Added more comments to explain the code.
*   **`substr()` for Home Page Excerpt:**  Uses `substr()` on the home page to create a short excerpt of the post content.
*   **Back to Home Links:** Added "Back to Home" links for easier navigation.
*   **No sessions or user authentication:** This is a *very* basic blog.  It has no user authentication.  Adding that would significantly increase the complexity.  You'd need to hash passwords, store sessions, etc.
*   **No image uploading:**  This only handles text-based posts.

**How to Run:**

1.  **Save the Files:** Save the code into separate files in your web server's document root (e.g., `/var/www/html/` or `C:\xampp\htdocs\`) with the specified names (e.g., `index.php`, `controllers/home_controller.php`, `views/home.php`, `css/style.css`).  Create the `controllers` and `views` directories.
2.  **Configure Database:** Update the database connection details in `index.php` with your MySQL username, password, and database name.
3.  **Create Database and Table:**  Create the database and the `posts` table using the SQL query provided above.
4.  **Access in Browser:** Open your web browser and go to `http://localhost/` (or the appropriate URL for your web server).

**Important Security Considerations:**

*   **SQL Injection:** The code *attempts* to prevent SQL injection by using prepared statements.  However, always be vigilant and double-check that all user inputs are properly sanitized and validated.
*   **XSS (Cross-Site Scripting):** The code uses `htmlspecialchars()` to escape output for HTML.  Make sure you escape *all* user-generated content that is displayed on the page.
*   **CSRF (Cross-Site Request Forgery):**  For a more secure application, you should implement CSRF protection, especially for forms that modify data (e.g., create, edit, delete).
*   **User Authentication:** This example does *not* include user authentication.  If you need user accounts, you'll need to implement a secure authentication system.
*   **Error Handling:** The error handling is basic.  In a production environment, you should log errors and handle them more gracefully, without exposing sensitive information to the user.
*   **File Uploads:** This example does not handle file uploads.  If you need to allow users to upload files, you must implement strict security measures to prevent malicious uploads.

This complete example provides a functional, albeit basic, blog platform.  Remember to address the security considerations before deploying this code to a production environment.  It's a starting point; you can expand upon it to add more features and improve security.
👁️ Viewed: 29

Comments