Dette er den 4. og sidste del af en 4-delt serie om, hvordan man bygger en blog med PHP og MySQL-database. Du kan se de andre dele her: del 1, del 2 og del 3.
Indtil videre har vi oprettet et offentligt område, der viser offentliggjorte indlæg fra en tabel med opslag i MySQL-databasen. Vi har også færdiggjort et brugerregistreringssystem, der håndterer login for både admin-brugere og normale brugere. I backend kan den loggede admin-bruger nu oprette andre admin-brugere samt emner.
I dette afsnit vil vi arbejde med blogindlæg. Vi opretter en side, der giver loggede administratorbrugere (eller forfattere) en formular til at oprette et nyt blogindlæg.
Vi vil oprette to filer:posts.php-fil inde i admin-mappen og post_functions.php inde i admin/includes-mappen. Posts.php-filen viser alle de indlæg, der er hentet fra databasen i et tabelformat, mens post_functions.php indeholder funktioner, der udfører handlinger på indlæg, såsom at forespørge dem fra databasen og returnere dem til posts.php-filen.
Indsæt denne kode i din posts.php-fil:
<?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>
I den øverste sektion inkluderer vi den nyoprettede post_functions.php-fil. Lad os åbne den nu og tilføje koden, der henter indlæg fra databasen.
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;
}
}
?>
Gå nu til http://localhost/complete-blog-php/login.php, og log ind med det brugernavn og den adgangskode, du oprettede i det sidste selvstudie. Hvis du ikke logger ind, vil du støde på fejl.
Når du er logget ind, skal du gå til http://localhost/complete-blog-php/admin/posts.php.
Hvis alt gik godt, vil du se, at siden har 2 indlæg (dem vi oprettede tidligere) vist i en tabel.
På dette tidspunkt er vi i stand til at forespørge databasen for indlæg og liste dem i et tabelformat. Lad os give en formular til faktisk oprettelse af indlæg. Opret en fil create_post.php inde i din admin-mappe, og indsæt denne kode i den:
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>
Ofte til et blogindlæg skal du skrive noget tekst med fed, kursiv, understregning, overskrifter, ordnede og uordnede lister samt uploade billeder. For at gøre dette skal du bruge en ckeditor til at give dig et tekstområde rigtigt på disse funktioner. Dette kræver, at vi inkluderer ckeditor-plugin-scriptet, som vi allerede har gjort i filen head_section.php.
For at aktivere denne ckeditor på et tekstområde skal 3 ting gøres:
- Vi skal inkludere CKEditor-kildescriptet (som vi allerede gjorde i filen head_section.php)
- Vi skal have et tekstområde og give det et id (sig id="body", som vi gjorde i dette tilfælde)
- Til sidst skal vi initialisere tekstområdet med dette script (som vi gjorde i create_post.php):
<script>
CKEDITOR.replace('body');
</script>
Åbn http://localhost/complete-blog-php/admin/create_post.php i browseren, og du vil se det transformerede tekstområde.
Vi kommer til at bruge den samme formular til at oprette og redigere indlæg. Det, der er tilbage nu, er, at vi skriver de funktioner, der er ansvarlige for oprettelse, redigering, opdatering og sletning af indlæg. Det gør vi i post_functions.php. Åbn post_functions.php og tilføj disse funktioner og if-sætninger til det.
complete-blog-php/admin/includes/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);
}
}
Nu er vi i stand til at oprette, læse, opdatere og slette indlæg.
En sidste ting, lad os tilføje kode til at publicere/afudgive indlæg. Tilføj denne kode i den samme post_functions.php-fil:
// 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);
}
}
Dette giver brugeren (adminbrugeren) mulighed for at publicere/afpublicere et indlæg. Og det bringer os til slutningen af denne tutorial.
Konklusion
Mange tak for din tålmodighed. Det giver mig en enorm tilfredsstillelse at vide, at nogen faktisk fulgte min tutorial til det sidste. Jeg håber, du har lært noget, der var din tid værd. Hvis du har kommentarer, bekymringer, forslag, bedes du efterlade dem i kommentarfeltet nedenfor. Du kan endda bare sige hej i kommentarerne, hvis du ikke har noget at sige. Jeg skal bare vide, at du er nået så langt, fordi det opmuntrer mig til at lave flere selvstudier som denne.
Husk, at du altid kan hjælpe meget ved at dele med dine venner.
Nyd resten af dagen.