これは、PHPおよびMySQLデータベースを使用してブログを構築する方法に関する4部構成のシリーズの4番目で最後の部分です。他の部分はここで確認できます:パート1、パート2、パート3。
これまでに、MySQLデータベースの投稿テーブルから公開された投稿を一覧表示するパブリックエリアを作成しました。また、管理者ユーザーと通常ユーザーの両方のログインを処理するユーザー登録システムを完成させました。バックエンドで、ログインした管理者ユーザーがトピックだけでなく他の管理者ユーザーも作成できるようになりました。
このセクションでは、ブログ投稿に取り組んでいきます。ログインした管理者ユーザー(または作成者)に新しいブログ投稿を作成するためのフォームを提供するページを作成します。
adminフォルダー内のposts.phpファイルとadmin/includesフォルダー内のpost_functions.phpの2つのファイルを作成します。 posts.phpファイルには、データベースから取得したすべての投稿が表形式で一覧表示されます。post_functions.phpには、データベースからのクエリやposts.phpファイルへの返送などの操作を実行する関数が含まれています。
このコードをposts.phpファイルに配置します:
<?php include('../config.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/admin_functions.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/post_functions.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/head_section.php'); ?>
<!-- Get all admin posts from DB -->
<?php $posts = getAllPosts(); ?>
<title>Admin | Manage Posts</title>
</head>
<body>
<!-- admin navbar -->
<?php include(ROOT_PATH . '/admin/includes/navbar.php') ?>
<div class="container content">
<!-- Left side menu -->
<?php include(ROOT_PATH . '/admin/includes/menu.php') ?>
<!-- Display records from DB-->
<div class="table-div" style="width: 80%;">
<!-- Display notification message -->
<?php include(ROOT_PATH . '/includes/messages.php') ?>
<?php if (empty($posts)): ?>
<h1 style="text-align: center; margin-top: 20px;">No posts in the database.</h1>
<?php else: ?>
<table class="table">
<thead>
<th>N</th>
<th>Title</th>
<th>Author</th>
<th>Views</th>
<!-- Only Admin can publish/unpublish post -->
<?php if ($_SESSION['user']['role'] == "Admin"): ?>
<th><small>Publish</small></th>
<?php endif ?>
<th><small>Edit</small></th>
<th><small>Delete</small></th>
</thead>
<tbody>
<?php foreach ($posts as $key => $post): ?>
<tr>
<td><?php echo $key + 1; ?></td>
<td><?php echo $post['author']; ?></td>
<td>
<a target="_blank"
href="<?php echo BASE_URL . 'single_post.php?post-slug=' . $post['slug'] ?>">
<?php echo $post['title']; ?>
</a>
</td>
<td><?php echo $post['views']; ?></td>
<!-- Only Admin can publish/unpublish post -->
<?php if ($_SESSION['user']['role'] == "Admin" ): ?>
<td>
<?php if ($post['published'] == true): ?>
<a class="fa fa-check btn unpublish"
href="posts.php?unpublish=<?php echo $post['id'] ?>">
</a>
<?php else: ?>
<a class="fa fa-times btn publish"
href="posts.php?publish=<?php echo $post['id'] ?>">
</a>
<?php endif ?>
</td>
<?php endif ?>
<td>
<a class="fa fa-pencil btn edit"
href="create_post.php?edit-post=<?php echo $post['id'] ?>">
</a>
</td>
<td>
<a class="fa fa-trash btn delete"
href="create_post.php?delete-post=<?php echo $post['id'] ?>">
</a>
</td>
</tr>
<?php endforeach ?>
</tbody>
</table>
<?php endif ?>
</div>
<!-- // Display records from DB -->
</div>
</body>
</html>
上部のセクションには、新しく作成されたpost_functions.phpファイルが含まれています。今すぐ開いて、データベースから投稿を取得するコードを追加しましょう。
post_functions.php:
<?php
// Post variables
$post_id = 0;
$isEditingPost = false;
$published = 0;
$title = "";
$post_slug = "";
$body = "";
$featured_image = "";
$post_topic = "";
/* - - - - - - - - - -
- Post functions
- - - - - - - - - - -*/
// get all posts from DB
function getAllPosts()
{
global $conn;
// Admin can view all posts
// Author can only view their posts
if ($_SESSION['user']['role'] == "Admin") {
$sql = "SELECT * FROM posts";
} elseif ($_SESSION['user']['role'] == "Author") {
$user_id = $_SESSION['user']['id'];
$sql = "SELECT * FROM posts WHERE user_id=$user_id";
}
$result = mysqli_query($conn, $sql);
$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);
$final_posts = array();
foreach ($posts as $post) {
$post['author'] = getPostAuthorById($post['user_id']);
array_push($final_posts, $post);
}
return $final_posts;
}
// get the author/username of a post
function getPostAuthorById($user_id)
{
global $conn;
$sql = "SELECT username FROM users WHERE id=$user_id";
$result = mysqli_query($conn, $sql);
if ($result) {
// return username
return mysqli_fetch_assoc($result)['username'];
} else {
return null;
}
}
?>
次に、http://localhost/complete-blog-php/login.phpにアクセスし、前回のチュートリアルで作成したユーザー名とパスワードを使用してログインします。ログインしないと、エラーが発生します。
ログイン後、http://localhost/complete-blog-php/admin/posts.phpにアクセスします。
すべてがうまくいけば、ページに2つの投稿(前に作成した投稿)がテーブルに表示されていることがわかります。
この時点で、データベースに投稿を照会し、表形式で一覧表示することができます。実際に投稿を作成するためのフォームを提供しましょう。 adminフォルダ内にcreate_post.phpファイルを作成し、このコードを貼り付けます:
complete-blog-php / admin / create_post.php:
<?php include('../config.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/admin_functions.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/post_functions.php'); ?>
<?php include(ROOT_PATH . '/admin/includes/head_section.php'); ?>
<!-- Get all topics -->
<?php $topics = getAllTopics(); ?>
<title>Admin | Create Post</title>
</head>
<body>
<!-- admin navbar -->
<?php include(ROOT_PATH . '/admin/includes/navbar.php') ?>
<div class="container content">
<!-- Left side menu -->
<?php include(ROOT_PATH . '/admin/includes/menu.php') ?>
<!-- Middle form - to create and edit -->
<div class="action create-post-div">
<h1 class="page-title">Create/Edit Post</h1>
<form method="post" enctype="multipart/form-data" action="<?php echo BASE_URL . 'admin/create_post.php'; ?>" >
<!-- validation errors for the form -->
<?php include(ROOT_PATH . '/includes/errors.php') ?>
<!-- if editing post, the id is required to identify that post -->
<?php if ($isEditingPost === true): ?>
<input type="hidden" name="post_id" value="<?php echo $post_id; ?>">
<?php endif ?>
<input type="text" name="title" value="<?php echo $title; ?>" placeholder="Title">
<label style="float: left; margin: 5px auto 5px;">Featured image</label>
<input type="file" name="featured_image" >
<textarea name="body" id="body" cols="30" rows="10"><?php echo $body; ?></textarea>
<select name="topic_id">
<option value="" selected disabled>Choose topic</option>
<?php foreach ($topics as $topic): ?>
<option value="<?php echo $topic['id']; ?>">
<?php echo $topic['name']; ?>
</option>
<?php endforeach ?>
</select>
<!-- Only admin users can view publish input field -->
<?php if ($_SESSION['user']['role'] == "Admin"): ?>
<!-- display checkbox according to whether post has been published or not -->
<?php if ($published == true): ?>
<label for="publish">
Publish
<input type="checkbox" value="1" name="publish" checked="checked">
</label>
<?php else: ?>
<label for="publish">
Publish
<input type="checkbox" value="1" name="publish">
</label>
<?php endif ?>
<?php endif ?>
<!-- if editing post, display the update button instead of create button -->
<?php if ($isEditingPost === true): ?>
<button type="submit" class="btn" name="update_post">UPDATE</button>
<?php else: ?>
<button type="submit" class="btn" name="create_post">Save Post</button>
<?php endif ?>
</form>
</div>
<!-- // Middle form - to create and edit -->
</div>
</body>
</html>
<script>
CKEDITOR.replace('body');
</script>
多くの場合、ブログ投稿の場合、画像をアップロードするだけでなく、太字、斜体、下線、見出し、順序付きリストと順序なしリストでテキストを書く必要があります。これを行うには、これらの機能が豊富なテキストエリアを提供するckeditorが必要です。これには、head_section.phpファイルにすでに行ったckeditorプラグインスクリプトを含める必要があります。
テキストエリアでこのckeditorをアクティブにするには、次の3つのことを行う必要があります。
- CKEditorソーススクリプトを含める必要があります(head_section.phpファイルですでに行ったように)
- textareaがあり、それにIDを指定する必要があります(この場合のように、id ="body"と言います)
- 最後に、このスクリプトを使用してtextareaを初期化する必要があります(create_post.phpで行ったように):
<script>
CKEDITOR.replace('body');
</script>
ブラウザでhttp://localhost/complete-blog-php/admin/create_post.phpを開くと、変換されたテキストエリアが表示されます。
同じフォームを使用して投稿を作成および編集します。現在残っているのは、投稿の作成、編集、更新、削除を担当する関数を作成することです。 post_functions.phpでそれを行います。 post_functions.phpを開き、これらの関数とifステートメントを追加します。
complete-blog-php / admin / contains / post_functions.php:
/* - - - - - - - - - -
- Post actions
- - - - - - - - - - -*/
// if user clicks the create post button
if (isset($_POST['create_post'])) { createPost($_POST); }
// if user clicks the Edit post button
if (isset($_GET['edit-post'])) {
$isEditingPost = true;
$post_id = $_GET['edit-post'];
editPost($post_id);
}
// if user clicks the update post button
if (isset($_POST['update_post'])) {
updatePost($_POST);
}
// if user clicks the Delete post button
if (isset($_GET['delete-post'])) {
$post_id = $_GET['delete-post'];
deletePost($post_id);
}
/* - - - - - - - - - -
- Post functions
- - - - - - - - - - -*/
function createPost($request_values)
{
global $conn, $errors, $title, $featured_image, $topic_id, $body, $published;
$title = esc($request_values['title']);
$body = htmlentities(esc($request_values['body']));
if (isset($request_values['topic_id'])) {
$topic_id = esc($request_values['topic_id']);
}
if (isset($request_values['publish'])) {
$published = esc($request_values['publish']);
}
// create slug: if title is "The Storm Is Over", return "the-storm-is-over" as slug
$post_slug = makeSlug($title);
// validate form
if (empty($title)) { array_push($errors, "Post title is required"); }
if (empty($body)) { array_push($errors, "Post body is required"); }
if (empty($topic_id)) { array_push($errors, "Post topic is required"); }
// Get image name
$featured_image = $_FILES['featured_image']['name'];
if (empty($featured_image)) { array_push($errors, "Featured image is required"); }
// image file directory
$target = "../static/images/" . basename($featured_image);
if (!move_uploaded_file($_FILES['featured_image']['tmp_name'], $target)) {
array_push($errors, "Failed to upload image. Please check file settings for your server");
}
// Ensure that no post is saved twice.
$post_check_query = "SELECT * FROM posts WHERE slug='$post_slug' LIMIT 1";
$result = mysqli_query($conn, $post_check_query);
if (mysqli_num_rows($result) > 0) { // if post exists
array_push($errors, "A post already exists with that title.");
}
// create post if there are no errors in the form
if (count($errors) == 0) {
$query = "INSERT INTO posts (user_id, title, slug, image, body, published, created_at, updated_at) VALUES(1, '$title', '$post_slug', '$featured_image', '$body', $published, now(), now())";
if(mysqli_query($conn, $query)){ // if post created successfully
$inserted_post_id = mysqli_insert_id($conn);
// create relationship between post and topic
$sql = "INSERT INTO post_topic (post_id, topic_id) VALUES($inserted_post_id, $topic_id)";
mysqli_query($conn, $sql);
$_SESSION['message'] = "Post created successfully";
header('location: posts.php');
exit(0);
}
}
}
/* * * * * * * * * * * * * * * * * * * * *
* - Takes post id as parameter
* - Fetches the post from database
* - sets post fields on form for editing
* * * * * * * * * * * * * * * * * * * * * */
function editPost($role_id)
{
global $conn, $title, $post_slug, $body, $published, $isEditingPost, $post_id;
$sql = "SELECT * FROM posts WHERE id=$role_id LIMIT 1";
$result = mysqli_query($conn, $sql);
$post = mysqli_fetch_assoc($result);
// set form values on the form to be updated
$title = $post['title'];
$body = $post['body'];
$published = $post['published'];
}
function updatePost($request_values)
{
global $conn, $errors, $post_id, $title, $featured_image, $topic_id, $body, $published;
$title = esc($request_values['title']);
$body = esc($request_values['body']);
$post_id = esc($request_values['post_id']);
if (isset($request_values['topic_id'])) {
$topic_id = esc($request_values['topic_id']);
}
// create slug: if title is "The Storm Is Over", return "the-storm-is-over" as slug
$post_slug = makeSlug($title);
if (empty($title)) { array_push($errors, "Post title is required"); }
if (empty($body)) { array_push($errors, "Post body is required"); }
// if new featured image has been provided
if (isset($_POST['featured_image'])) {
// Get image name
$featured_image = $_FILES['featured_image']['name'];
// image file directory
$target = "../static/images/" . basename($featured_image);
if (!move_uploaded_file($_FILES['featured_image']['tmp_name'], $target)) {
array_push($errors, "Failed to upload image. Please check file settings for your server");
}
}
// register topic if there are no errors in the form
if (count($errors) == 0) {
$query = "UPDATE posts SET title='$title', slug='$post_slug', views=0, image='$featured_image', body='$body', published=$published, updated_at=now() WHERE id=$post_id";
// attach topic to post on post_topic table
if(mysqli_query($conn, $query)){ // if post created successfully
if (isset($topic_id)) {
$inserted_post_id = mysqli_insert_id($conn);
// create relationship between post and topic
$sql = "INSERT INTO post_topic (post_id, topic_id) VALUES($inserted_post_id, $topic_id)";
mysqli_query($conn, $sql);
$_SESSION['message'] = "Post created successfully";
header('location: posts.php');
exit(0);
}
}
$_SESSION['message'] = "Post updated successfully";
header('location: posts.php');
exit(0);
}
}
// delete blog post
function deletePost($post_id)
{
global $conn;
$sql = "DELETE FROM posts WHERE id=$post_id";
if (mysqli_query($conn, $sql)) {
$_SESSION['message'] = "Post successfully deleted";
header("location: posts.php");
exit(0);
}
}
これで、投稿を作成、読み取り、更新、削除できるようになりました。
最後に、投稿を公開/非公開にするコードを追加しましょう。同じpost_functions.phpファイルに、次のコードを追加します:
// if user clicks the publish post button
if (isset($_GET['publish']) || isset($_GET['unpublish'])) {
$message = "";
if (isset($_GET['publish'])) {
$message = "Post published successfully";
$post_id = $_GET['publish'];
} else if (isset($_GET['unpublish'])) {
$message = "Post successfully unpublished";
$post_id = $_GET['unpublish'];
}
togglePublishPost($post_id, $message);
}
// delete blog post
function togglePublishPost($post_id, $message)
{
global $conn;
$sql = "UPDATE posts SET published=!published WHERE id=$post_id";
if (mysqli_query($conn, $sql)) {
$_SESSION['message'] = $message;
header("location: posts.php");
exit(0);
}
}
これにより、ユーザー(管理者ユーザー)は投稿を公開/非公開にできます。これで、このチュートリアルは終了です。
結論
お待ちいただき、誠にありがとうございます。誰かが実際に私のチュートリアルを最後まで実行したことを知って、私は非常に満足しています。あなたがあなたの時間の価値がある何かを学んだことを願っています。コメント、心配事、提案があれば、下のコメント欄に残してください。何も言うことがない場合は、コメントでこんにちはと言うこともできます。このようなチュートリアルをもっとやる気にさせてくれるので、あなたがここまでやってきたことを知っておく必要があります。
友達と共有することで、いつでも大いに役立つことができることを忘れないでください。
一日の残りをお楽しみください。