Blog Series
- Part 1 - The Build
- Part 2 - SEO URLS
- Part 3 Comments with Disqus
- Part 4 Categories
- Part 5 Sidebar, Categories and Archives
- Part 6 Pagination
- Part 7 Tags
- Part 8 Tags Sidebar
- Part 9 Cover Image
In this tutorial we will add the ability to add an image for each post.
admin demo: https://demos.dcblog.dev/simpleblog-coverphoto/admin
username: demo
password: demo
The image will be added into another column of the database table so add another column your database table called postImage that's a varchar data type and uses 255 chars.
First lets update the add-post.php
After the form is submitted, set the path to where uploaded images will go. Make sure to make a folder in the root called images this is where the images will be uploaded to,
// location where initial upload will be moved to
$target = "images/" . $_FILES['postImage']['name'];
$path = '../'.$target;
Next, add a check to ensure only image extensions are used. At the same time call move_uploaded_file() and pass in the tmp name of the file and the upload path.
if(isset($_FILES['postImage'])){
// find thevtype of image
switch ($_FILES["postImage"]["type"]) {
case $_FILES["postImage"]["type"] == "image/gif":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/jpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/pjpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/x-png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
default:
$error[] = 'Wrong image type selected. Only JPG, PNG or GIF accepted!.';
}
}
After the post has been saved check if there has been an image uploaded and if so then save it in the database:
if(isset($_FILES['postImage'])){
$stmt = $db->prepare('UPDATE blog_posts SET postImage = :image WHERE postID = :postID') ;
$stmt->execute(array(
':postID' => $postID,
':image' => $target
));
}
For the form to be able to upload files it needs a new attribute enctype="multipart/form-data"
<form action='' method='post' enctype="multipart/form-data">
The file upload element is very simple, its an input with a type of file.
<p><label>Image</label><br />
<input type='file' name='postImage'></p>
Putting it all together:
<?php //include config
require_once('../includes/config.php');
//if not logged in redirect to login page
if(!$user->is_logged_in()){ header('Location: login.php'); }
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Admin - Add Post</title>
<link rel="stylesheet" href="../style/normalize.css">
<link rel="stylesheet" href="../style/main.css">
<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script>
tinymce.init({
selector: "textarea",
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media table contextmenu paste"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-46100971-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<div id="wrapper">
<?php include('menu.php');?>
<p><a href="./">Blog Admin Index</a></p>
<h2>Add Post</h2>
<?php
//if form has been submitted process it
if(isset($_POST['submit'])){
// location where initial upload will be moved to
$target = "images/" . $_FILES['postImage']['name'];
$path = '../'.$target;
//collect form data
extract($_POST);
//very basic validation
if($postTitle ==''){
$error[] = 'Please enter the title.';
}
if($postDesc ==''){
$error[] = 'Please enter the description.';
}
if($postCont ==''){
$error[] = 'Please enter the content.';
}
if(isset($_FILES['postImage'])){
// find thevtype of image
switch ($_FILES["postImage"]["type"]) {
case $_FILES["postImage"]["type"] == "image/gif":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/jpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/pjpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/x-png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
default:
$error[] = 'Wrong image type selected. Only JPG, PNG or GIF accepted!.';
}
}
if(!isset($error)){
try {
$postSlug = slug($postTitle);
//insert into database
$stmt = $db->prepare('INSERT INTO blog_posts (postTitle,postSlug,postDesc,postCont,postDate,postTags) VALUES (:postTitle, :postSlug, :postDesc, :postCont, :postDate, :postTags)') ;
$stmt->execute(array(
':postTitle' => $postTitle,
':postSlug' => $postSlug,
':postDesc' => $postDesc,
':postCont' => $postCont,
':postDate' => date('Y-m-d H:i:s'),
':postTags' => $postTags
));
$postID = $db->lastInsertId();
if(isset($_FILES['postImage'])){
$stmt = $db->prepare('UPDATE blog_posts SET postImage = :image WHERE postID = :postID') ;
$stmt->execute(array(
':postID' => $postID,
':image' => $target
));
}
//add categories
if(is_array($catID)){
foreach($_POST['catID'] as $catID){
$stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)');
$stmt->execute(array(
':postID' => $postID,
':catID' => $catID
));
}
}
//redirect to index page
header('Location: index.php?action=added');
exit;
} catch(PDOException $e) {
echo $e->getMessage();
}
}
}
//check for any errors
if(isset($error)){
foreach($error as $error){
echo '<p class="error">'.$error.'</p>';
}
}
?>
<form action='' method='post' enctype="multipart/form-data">
<p><label>Title</label><br />
<input type='text' name='postTitle' value='<?php if(isset($error)){ echo $_POST['postTitle'];}?>'></p>
<p><label>Image</label><br />
<input type='file' name='postImage'></p>
<p><label>Description</label><br />
<textarea name='postDesc' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postDesc'];}?></textarea></p>
<p><label>Content</label><br />
<textarea name='postCont' cols='60' rows='10'><?php if(isset($error)){ echo $_POST['postCont'];}?></textarea></p>
<p><label>Tags (comma seperated)</label><br />
<input type='text' name='postTags' value='<?php if(isset($error)){ echo $_POST['postTags'];}?>' style="width:400px;"></p>
<fieldset>
<legend>Categories</legend>
<?php
$stmt2 = $db->query('SELECT catID, catTitle FROM blog_cats ORDER BY catTitle');
while($row2 = $stmt2->fetch()){
if(isset($_POST['catID'])){
if(in_array($row2['catID'], $_POST['catID'])){
$checked="checked='checked'";
}else{
$checked = null;
}
}
echo "<input type='checkbox' name='catID[]' value='".$row2['catID']."' $checked> ".$row2['catTitle']."<br />";
}
?>
</fieldset>
<p><input type='submit' name='submit' value='Submit'></p>
</form>
</div>
The edit-post.php page is essentially the same steps as above the only difference is postImage needs to be added to the select query:
$stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont, postTags, postImage FROM blog_posts WHERE postID = :postID');
When showing the file upload element also show the image if there has been one uploaded.
<p><label>Image</label><br />
<input type='file' name='postImage'></p>
<?php if ($row['postImage'] !=''){ ?>
<p><img src="<?=$url.$row['postImage'];?>"></p>
<?php } ?>
I've added a new variable to config.php called $url this is the full url of the website. This allows the image to have a full path when being displayed.
Add this to config.php (put your own website address)
$url = 'https://yourdomain.com/';
The complete edit-post.php page looks like:
<?php //include config
require_once('../includes/config.php');
//if not logged in redirect to login page
if(!$user->is_logged_in()){ header('Location: login.php'); }
?>
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Admin - Edit Post</title>
<link rel="stylesheet" href="../style/normalize.css">
<link rel="stylesheet" href="../style/main.css">
<script src="//tinymce.cachefly.net/4.0/tinymce.min.js"></script>
<script>
tinymce.init({
selector: "textarea",
plugins: [
"advlist autolink lists link image charmap print preview anchor",
"searchreplace visualblocks code fullscreen",
"insertdatetime media table contextmenu paste"
],
toolbar: "insertfile undo redo | styleselect | bold italic | alignleft aligncenter alignright alignjustify | bullist numlist outdent indent | link image"
});
</script>
<script>
(function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
ga('create', 'UA-46100971-1', 'auto');
ga('send', 'pageview');
</script>
</head>
<body>
<div id="wrapper">
<?php include('menu.php');?>
<p><a href="./">Blog Admin Index</a></p>
<h2>Edit Post</h2>
<?php
//if form has been submitted process it
if(isset($_POST['submit'])){
// location where initial upload will be moved to
$target = "images/" . $_FILES['postImage']['name'];
$path = '../'.$target;
//collect form data
extract($_POST);
//very basic validation
if($postID ==''){
$error[] = 'This post is missing a valid id!.';
}
if($postTitle ==''){
$error[] = 'Please enter the title.';
}
if($postDesc ==''){
$error[] = 'Please enter the description.';
}
if($postCont ==''){
$error[] = 'Please enter the content.';
}
if(isset($_FILES['postImage'])){
// find thevtype of image
switch ($_FILES["postImage"]["type"]) {
case $_FILES["postImage"]["type"] == "image/gif":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/jpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/pjpeg":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
case $_FILES["postImage"]["type"] == "image/x-png":
move_uploaded_file($_FILES["postImage"]["tmp_name"], $path);
break;
default:
$error[] = 'Wrong image type selected. Only JPG, PNG or GIF accepted!.';
}
}
if(!isset($error)){
try {
$postSlug = slug($postTitle);
//insert into database
$stmt = $db->prepare('UPDATE blog_posts SET postTitle = :postTitle, postSlug = :postSlug, postDesc = :postDesc, postCont = :postCont, postTags = :postTags WHERE postID = :postID') ;
$stmt->execute(array(
':postTitle' => $postTitle,
':postSlug' => $postSlug,
':postDesc' => $postDesc,
':postCont' => $postCont,
':postID' => $postID,
':postTags' => $postTags
));
if(isset($_FILES['postImage'])){
$stmt = $db->prepare('UPDATE blog_posts SET postImage = :image WHERE postID = :postID') ;
$stmt->execute(array(
':postID' => $postID,
':image' => $target
));
}
//delete all items with the current postID
$stmt = $db->prepare('DELETE FROM blog_post_cats WHERE postID = :postID');
$stmt->execute(array(':postID' => $postID));
if(is_array($catID)){
foreach($_POST['catID'] as $catID){
$stmt = $db->prepare('INSERT INTO blog_post_cats (postID,catID)VALUES(:postID,:catID)');
$stmt->execute(array(
':postID' => $postID,
':catID' => $catID
));
}
}
//redirect to index page
header('Location: index.php?action=updated');
exit;
} catch(PDOException $e) {
echo $e->getMessage();
}
}
}
?>
<?php
//check for any errors
if(isset($error)){
foreach($error as $error){
echo $error.'<br />';
}
}
try {
$stmt = $db->prepare('SELECT postID, postTitle, postDesc, postCont, postTags, postImage FROM blog_posts WHERE postID = :postID') ;
$stmt->execute(array(':postID' => $_GET['id']));
$row = $stmt->fetch();
} catch(PDOException $e) {
echo $e->getMessage();
}
?>
<form action='' method='post' enctype="multipart/form-data">
<input type='hidden' name='postID' value='<?php echo $row['postID'];?>'>
<p><label>Title</label><br />
<input type='text' name='postTitle' value='<?php echo $row['postTitle'];?>'></p>
<p><label>Image</label><br />
<input type='file' name='postImage'></p>
<?php if ($row['postImage'] !=''){ ?>
<p><img src="<?=$url.$row['postImage'];?>"></p>
<?php } ?>
<p><label>Description</label><br />
<textarea name='postDesc' cols='60' rows='10'><?php echo $row['postDesc'];?></textarea></p>
<p><label>Content</label><br />
<textarea name='postCont' cols='60' rows='10'><?php echo $row['postCont'];?></textarea></p>
<p><label>Tags (comma seperated)</label><br />
<input type='text' name='postTags' value='<?php echo $row['postTags'];?>' style="width:400px;"></p>
<fieldset>
<legend>Categories</legend>
<?php
$stmt2 = $db->query('SELECT catID, catTitle FROM blog_cats ORDER BY catTitle');
while($row2 = $stmt2->fetch()){
$stmt3 = $db->prepare('SELECT catID FROM blog_post_cats WHERE catID = :catID AND postID = :postID') ;
$stmt3->execute(array(':catID' => $row2['catID'], ':postID' => $row['postID']));
$row3 = $stmt3->fetch();
if($row3['catID'] == $row2['catID']){
$checked = 'checked=checked';
} else {
$checked = null;
}
echo "<input type='checkbox' name='catID[]' value='".$row2['catID']."' $checked> ".$row2['catTitle']."<br />";
}
?>
</fieldset>
<p><input type='submit' name='submit' value='Update'></p>
</form>
</div>
</body>
</html>
Front End
Now its time to display image with the post, open index.php add postImage to your query:
$stmt = $db->query('SELECT postID, postTitle, postSlug, postDesc, postDate, postTags, postImage FROM blog_posts ORDER BY postID DESC');
This returns the column from the database, next we use an if statement where we want the image to be displayed:
if ($row['postImage'] !=''){
echo "<p><img src='".$url.$row['postImage']."' style='max-width:100%;'></p>";
}
The image that has been uploaded will not be resized there for its a good idea to resize it before upload. Having said that here I'm using inline styling to set the image width to be 100% which should help to keep the image from expanding beyond the post.
That's it! repeat the steps above to all files displaying the posts.