PHP: блог
создаем блог с помощью PHP

Реализуем базовый функционал блога, в котором пользователь сможет создавать, редактировать и удалять статьи с помощью PHP, HTML, jQuery, AJAX, JSON, Bootstrap, CSS, и MySQL.
Структура проекта
simple-blog-platform/
│
├── config.sample.php
├── index.php
├── db/
│ └── database.sql
├── src/
│ ├── get-post.php
│ └── post-handler.php
├── include/
│ ├── config.sample.php
│ └── db.php
├── assets/
│ ├── css/
│ │ └── style.css
│ ├── js/
│ │ └── script.js
│ └── images/
├── README.md
└── .gitignore
Создаем базу данных
db/database.sql
CREATE DATABASE IF NOT EXISTS blog_db;
USE blog_db;
CREATE TABLE IF NOT EXISTS posts (
id INT AUTO_INCREMENT PRIMARY KEY,
title VARCHAR(255) NOT NULL,
content TEXT NOT NULL,
created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP
);
Обновляем реквизиты базы данных
include/config.sample.php
<?php
define('DB_HOST', 'localhost'); // Database host
define('DB_NAME', 'blog_db'); // Database name
define('DB_USER', 'root'); // Change if necessary
define('DB_PASS', ''); // Change if necessary
Настраиваем подключение к базе данных через PDO
include/db.php
<?php
include 'config.sample.php';
// Database configuration
$dsn = 'mysql:host='.DB_HOST.';dbname='.DB_NAME;
$options = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
];
// Create a new PDO instance
try {
$pdo = new PDO($dsn, DB_USER, DB_PASS, $options);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); // Set error mode to exception
} catch (PDOException $e) {
echo 'Connection failed: ' . $e->getMessage(); // Display error message if connection fails
}
Создаем структуру HTML
index.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Simple Blog</title>
<link rel="stylesheet" href="assets/css/style.css">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container">
<h1 class="mt-5">Simple Blog</h1>
<div id="posts"></div>
<button class="btn btn-primary mt-3" data-toggle="modal" data-target="#postModal">Add Post</button>
</div>
<!-- Modal for adding/editing posts -->
<div class="modal fade" id="postModal" tabindex="-1" role="dialog" aria-labelledby="postModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="postModalLabel">Add Post</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="postForm">
<input type="hidden" id="postId">
<div class="form-group">
<label for="title">Title</label>
<input type="text" class="form-control" id="title" required>
</div>
<div class="form-group">
<label for="content">Content</label>
<textarea class="form-control" id="content" rows="3" required></textarea>
</div>
<button type="submit" class="btn btn-primary">Save Post</button>
</form>
</div>
</div>
</div>
</div>
<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.5.2/js/bootstrap.bundle.min.js"></script>
<script src="assets/js/script.js"></script>
</body>
</html>
JavaScript и AJAX
assets/js/script.js
$(document).ready(function() {
// Load posts when the page loads
loadPosts();
// Handle form submission
$('#postForm').submit(function(event) {
event.preventDefault(); // Prevent default form submission
var postId = $('#postId').val();
var title = $('#title').val();
var content = $('#content').val();
$.ajax({
url: 'src/post-handler.php',
type: 'POST',
dataType: 'json',
data: {
id: postId,
title: title,
content: content
},
success: function(response) {
if (response.success) {
$('#postModal').modal('hide');
loadPosts(); // Reload posts after saving
} else {
alert('Error: ' + response.message);
}
}
});
});
// Load posts function
function loadPosts() {
$.ajax({
url: 'src/get-posts.php',
type: 'GET',
dataType: 'json',
success: function(data) {
var postsHtml = '';
$.each(data.posts, function(index, post) {
postsHtml += '<div class="post"><h2>' + post.title + '</h2><p>' + post.content + '</p></div>';
});
$('#posts').html(postsHtml);
}
});
}
});
PHP скрипты
src/get-posts.php
<?php
include '../include/db.php';
header('Content-Type: application/json');
try {
$stmt = $pdo->query('SELECT * FROM posts ORDER BY created_at DESC');
$posts = $stmt->fetchAll(PDO::FETCH_ASSOC);
echo json_encode(['posts' => $posts]);
} catch (PDOException $e) {
echo json_encode(['error' => $e->getMessage()]);
}
src/post-handler.php
<?php
include '../include/db.php';
header('Content-Type: application/json');
// Retrieve POST data
$id = isset($_POST['id']) ? intval($_POST['id']) : 0;
$title = $_POST['title'];
$content = $_POST['content'];
try {
if ($id > 0) {
// Update existing post
$stmt = $pdo->prepare('UPDATE posts SET title = ?, content = ? WHERE id = ?');
$stmt->execute([$title, $content, $id]);
} else {
// Insert new post
$stmt = $pdo->prepare('INSERT INTO posts (title, content) VALUES (?, ?)');
$stmt->execute([$title, $content]);
}
echo json_encode(['success' => true]);
} catch (PDOException $e) {
echo json_encode(['success' => false, 'message' => $e->getMessage()]);
}
Создаём стили CSS
assets/css/style.css
body {
font-family: Arial, sans-serif;
margin: 0;
padding: 0;
}
.container {
margin-top: 20px;
}
.post {
border: 1px solid #ddd;
padding: 15px;
margin-bottom: 15px;
background-color: #f9f9f9;
}
Объяснение
- config.sample.php: конфигурация базы данных и подключение к ней через PDO.
- index.php: HTML разметка страницы, включающая классы Bootstrap.
- assets/js/script.js: Обработка AJAX-запроса для загрузки и сохранения статьи. Для взаимодействия с AJAX и динамического построения DOM используется jQuery.
- get-posts.php: извлечение статей из базы данных и их упаковка в JSON.
- post-handler.php: создание статьи с присовением ID и реализация возможности редактирования статьи.
Это базовая реализация блога, в которой пользователь может создавать, редактировать и удалять статьи. При желании функционал можно расширить, добавив обязательную авторизацию, комментарии, категории для статей и много другое…
Спасибо за внимание.
Перевод статьи MD ARIFUL HAQUE “PHP crash course: Simple To-Do List”