├── .gitignore ├── .htaccess ├── LICENSE ├── README.md ├── _config.yml ├── admin.php ├── cat.php ├── categories.php ├── config.php ├── connect.php ├── database.sql ├── del.php ├── edit.php ├── footer.php ├── functions.php ├── generate_slugs.php ├── header.php ├── index.php ├── login.php ├── logout.php ├── new.php ├── search.php ├── security.php └── view.php /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | -------------------------------------------------------------------------------- /.htaccess: -------------------------------------------------------------------------------- 1 | RewriteEngine On 2 | 3 | RewriteRule ^p/(.*)$ view.php?id=$1 [QSA,L] -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018- Philip Okugbe 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Simple-PHP-Blog 2 | Simple blog system for personal development using procedural PHP and MYSQL. 3 | 4 | For educational purposes only. 5 | 6 | # Setup 7 | 8 | Update the `connect.php` file with your database credentials. 9 | Import the `database.sql` file. 10 | 11 | If installed on a sub-folder, edit the `config.php` and replace the empty constant with the folder's name. 12 | 13 | The pagination results per page can be set on the `config.php` file. 14 | 15 | ### URL Rewrite 16 | The latest update introduces 'slugs', also known as 'SEO URLs'. 17 | After you update to the latest version, click on the "Generate slugs (SEO URLs)" button on the admin dashboard and slugs will be generated for all existing posts. 18 | 19 | The blog posts URL structure is like this: `http://localhost/p/4/apple-reveals-apple-watch-series-7` 20 | 21 | If you use Apache, enable the Apache rewrite module for the .htaccess rewrite rule to work. 22 | 23 | If you use NGINX, you can insert something similar to the code below in your NGINX configuration block. 24 | ``` 25 | location / { 26 | rewrite ^p/(.*) view.php?id=$1; 27 | } 28 | ``` 29 | 30 | # Default Admin Login 31 | Username: admin 32 | Password: 12345 33 | 34 | There is no way to update the admin password through the dashboard yet. 35 | To change your password, hash your password with PHP's `password_hash()` function. Then update the database value with the new password hash. 36 | 37 | # Screenshots 38 | 39 | ![screenshot_01](https://user-images.githubusercontent.com/16838612/66112823-78d32e00-e5c3-11e9-9b38-93ba488071e0.jpg) 40 | ![screenshot_02](https://user-images.githubusercontent.com/16838612/66112874-8d172b00-e5c3-11e9-97e4-590da5675100.jpg) 41 | -------------------------------------------------------------------------------- /_config.yml: -------------------------------------------------------------------------------- 1 | theme: jekyll-theme-cayman -------------------------------------------------------------------------------- /admin.php: -------------------------------------------------------------------------------- 1 | 6 |

Admin Dashboard

7 |
8 |

Welcome ,

9 |

Create new post

10 |

Generate slugs (SEO URLs)

11 | 12 |
13 |
Posts
14 | $totalpages) { 28 | $page = $totalpages; 29 | } 30 | if ($page < 1) { 31 | $page = 1; 32 | } 33 | $offset = ($page - 1) * $rowsperpage; 34 | 35 | $sql = "SELECT * FROM posts ORDER BY id DESC LIMIT $offset, $rowsperpage"; 36 | $result = mysqli_query($dbcon, $sql); 37 | 38 | if (mysqli_num_rows($result) < 1) { 39 | echo "No post found"; 40 | } 41 | echo ""; 42 | echo ""; 43 | echo ""; 44 | echo ""; 45 | echo ""; 46 | echo ""; 47 | echo ""; 48 | echo ""; 49 | 50 | while ($row = mysqli_fetch_assoc($result)) { 51 | $id = $row['id']; 52 | $title = $row['title']; 53 | $slug = $row['slug']; 54 | $author = $row['posted_by']; 55 | $time = $row['date']; 56 | 57 | $permalink = "p/".$id ."/".$slug; 58 | ?> 59 | 60 | 61 | 62 | 63 | 64 | 67 | 68 | 69 | "; 72 | 73 | // pagination 74 | echo "

"; 75 | if ($page > 1) { 76 | echo "<<"; 77 | $prevpage = $page - 1; 78 | echo "<"; 79 | } 80 | $range = 3; 81 | for ($i = ($page - $range); $i < ($page + $range) + 1; $i++) { 82 | if (($i > 0) && ($i <= $totalpages)) { 83 | if ($i == $page) { 84 | echo "
$i
"; 85 | } else { 86 | echo "$i"; 87 | } 88 | } 89 | } 90 | if ($page != $totalpages) { 91 | $nextpage = $page + 1; 92 | echo ">"; 93 | echo ">>"; 94 | } 95 | echo "

"; 96 | 97 | include("footer.php"); 98 | -------------------------------------------------------------------------------- /cat.php: -------------------------------------------------------------------------------- 1 | '; 20 | echo "

" . $catname . "

"; 21 | } 22 | 23 | 24 | $sql1 = "SELECT * FROM posts WHERE post_cat = '$post_cat' ORDER BY id DESC"; 25 | $res = mysqli_query($dbcon, $sql1); 26 | 27 | if (mysqli_num_rows($res) == 0) { 28 | echo "No post yet"; 29 | } 30 | 31 | while ($r = mysqli_fetch_assoc($res)) { 32 | $id = $r['id']; 33 | $title = $r['title']; 34 | $des = $r['description']; 35 | $time = $r['date']; 36 | 37 | echo '
'; 38 | echo "

$title

"; 39 | 40 | if (strlen($des) > 100) { 41 | echo substr($des, 0, 100) . "..."; 42 | } else { 43 | echo $des; 44 | } 45 | 46 | echo '

'; 47 | echo "Read more"; 48 | 49 | echo '
'; 50 | echo "$time
"; 51 | echo '
'; 52 | } 53 | 54 | include("footer.php"); -------------------------------------------------------------------------------- /categories.php: -------------------------------------------------------------------------------- 1 |

Categories

2 | "; 8 | while ($row = mysqli_fetch_assoc($result)) { 9 | $id = $row['id']; 10 | $catname = $row['catname']; 11 | $description = $row['description']; 12 | ?> 13 | 14 |

15 | 16 |
17 | "; 20 | }else{ 21 | echo "
No Category found.
"; 22 | } 23 | -------------------------------------------------------------------------------- /config.php: -------------------------------------------------------------------------------- 1 |

\r\n\r\nManchester United is delighted to confirm the signing of Cristiano Ronaldo on a two-year contract with the option to extend for a further year, subject to international clearance.\r\n\r\n\r\nCristiano, a five-time Ballon D’or winner, has so far won over 30 major trophies during his career, including five UEFA Champions League titles, four FIFA Club World Cups, seven league titles in England, Spain and Italy, and the UEFA European Championship for his native Portugal. Cristiano is the first player to have won league titles in England, Spain and Italy. He was also the highest goalscorer in last season’s Serie A and won the golden boot at this year’s European Championship. In his first spell for Manchester United, he scored 118 goals in 292 games.

Cristiano Ronaldo said:\r\n\r\n“Manchester United is a club that has always had a special place in my heart, and I have been overwhelmed by all the messages I have received since the announcement on Friday. I cannot wait to play at Old Trafford in front of a full stadium and see all the fans again. I\'m looking forward to joining up with the team after the international games, and I hope we have a very successful season ahead.”

Ole Gunnar Solskjaer said:\r\n\r\n“You run out of words to describe Cristiano. He is not only a marvellous player, but also a great human being. To have the desire and the ability to play at the top level for such a long period requires a very special person. I have no doubt that he will continue to impress us all and his experience will be so vital for the younger players in the squad. Ronaldo’s return demonstrates the unique appeal of this club and I am absolutely delighted he is coming home to where it all started.”

', 'cristiano-ronaldo-returns-to-manchester-united', 'Admin', '2022-02-11 15:50:41'), 79 | (2, 'Leo Messi signs for Paris Saint-Germain', '

\"\"

Paris Saint-Germain is delighted to announce the signing of Leo Messi on a two-year contract with an option of a third year.\r\n\r\nThe six-time Ballon d’Or winner is justifiably considered a legend of the game and a true inspiration for those of all ages inside and outside football.

The signing of Leo reinforces Paris Saint-Germain’s aspirations as well as providing the club’s loyal fans with not only an exceptionally talented squad, but also moments of incredible football in the coming years.

Leo Messi said: “I am excited to begin a new chapter of my career at Paris Saint-Germain. Everything about the club matches my football ambitions. I know how talented the squad and the coaching staff are here. I am determined to help build something special for the club and the fans, and I am looking forward to stepping out onto the pitch at the Parc des Princes.”

Nasser Al-Khelaifi, Chairman and CEO of Paris Saint-Germain said: “I am delighted that Lionel Messi has chosen to join Paris Saint-Germain and we are proud to welcome him and his family to Paris. He has made no secret of his desire to continue competing at the very highest level and winning trophies, and naturally our ambition as a club is to do the same. The addition of Leo to our world class squad continues a very strategic and successful transfer window for the club. Led by our outstanding coach and his staff, I look forward to the team making history together for our fans all around the world.”

', 'leo-messi-signs-for-paris-saint-germain', 'Admin', '2022-02-11 15:50:41'), 80 | (3, 'Apple Introduces iPhone 13 and iPhone 13 Mini', '

\"\"

CUPERTINO, CALIFORNIA Apple today introduced iPhone 13 and iPhone 13 mini, the next generation of the world’s best smartphone, featuring a beautiful design with sleek flat edges in five gorgeous new colours. Both models feature major innovations, including the most advanced dual-camera system ever on iPhone — with a new Wide camera with bigger pixels and sensor-shift optical image stabilisation (OIS) offering improvements in low-light photos and videos, a new way to personalise the camera with Photographic Styles, and Cinematic mode, which brings a new dimension to video storytelling. iPhone 13 and iPhone 13 mini also boast super-fast performance and power efficiency with A15 Bionic, longer battery life, a brighter Super Retina XDR display that brings content to life, incredible durability with the Ceramic Shield front cover, double the entry-level storage at 128GB, an industry-leading IP68 rating for water resistance, and an advanced 5G experience.

', 'apple-introduces-iphone-13-and-iphone-13-mini', 'admin', '2022-02-11 15:50:41'), 81 | (4, 'Apple Reveals Apple Watch Series 7', '\"\"

\r\nCUPERTINO, CALIFORNIA Apple today announced Apple Watch Series 7, featuring a reengineered Always-On Retina display with significantly more screen area and thinner borders, making it the largest and most advanced display ever. The narrower borders allow the display to maximise screen area, while minimally changing the dimensions of the watch itself. The design of Apple Watch Series 7 is refined with softer, more rounded corners, and the display has a unique refractive edge that makes full-screen watch faces and apps appear to seamlessly connect with the curvature of the case. Apple Watch Series 7 also features a user interface optimised for the larger display, offering greater readability and ease of use, plus two unique watch faces — Contour and Modular Duo — designed specifically for the new device. With the improvements to the display, users benefit from the same all-day 18-hour battery life,1 now complemented by 33 percent faster charging.

', 'apple-reveals-apple-watch-series-7', 'admin', '2022-02-11 15:50:41'); 82 | 83 | -- 84 | -- Indexes for dumped tables 85 | -- 86 | 87 | -- 88 | -- Indexes for table `admin` 89 | -- 90 | ALTER TABLE `admin` 91 | ADD PRIMARY KEY (`id`), 92 | ADD UNIQUE KEY `username` (`username`), 93 | ADD UNIQUE KEY `email` (`email`); 94 | 95 | -- 96 | -- Indexes for table `page` 97 | -- 98 | ALTER TABLE `page` 99 | ADD PRIMARY KEY (`id`), 100 | ADD UNIQUE KEY `page_name` (`page_name`); 101 | 102 | -- 103 | -- Indexes for table `posts` 104 | -- 105 | ALTER TABLE `posts` 106 | ADD PRIMARY KEY (`id`); 107 | 108 | -- 109 | -- AUTO_INCREMENT for dumped tables 110 | -- 111 | 112 | -- 113 | -- AUTO_INCREMENT for table `admin` 114 | -- 115 | ALTER TABLE `admin` 116 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=2; 117 | 118 | -- 119 | -- AUTO_INCREMENT for table `page` 120 | -- 121 | ALTER TABLE `page` 122 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT; 123 | 124 | -- 125 | -- AUTO_INCREMENT for table `posts` 126 | -- 127 | ALTER TABLE `posts` 128 | MODIFY `id` int(11) NOT NULL AUTO_INCREMENT, AUTO_INCREMENT=5; 129 | COMMIT; 130 | 131 | /*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */; 132 | /*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */; 133 | /*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */; 134 | -------------------------------------------------------------------------------- /del.php: -------------------------------------------------------------------------------- 1 | '; 33 | } else { 34 | echo "failed to edit." . mysqli_connect_error(); 35 | } 36 | } 37 | ?> 38 | 39 |
40 |
41 | 42 |
43 |

Edit Post -

44 |
45 |

Goto post

46 | 47 |
48 | 49 |

50 | 51 | 52 |

53 |

54 | 55 | 56 |

57 |

58 | 59 | 60 |

61 |

62 | 63 |

64 | 65 |

66 |

69 |

70 | 71 |
72 |
73 | 74 | 2 |
3 |

All rights reserved |

4 |
5 |

6 | 7 | 8 | 11 | 12 | -------------------------------------------------------------------------------- /functions.php: -------------------------------------------------------------------------------- 1 | "; 11 | } 12 | 13 | $sql = "SELECT * FROM posts WHERE slug IS NULL"; 14 | 15 | $result = mysqli_query($dbcon, $sql); 16 | if (mysqli_num_rows($result) == 0) { 17 | echo "It looks like there is nothing to update."; 18 | die(); 19 | } 20 | 21 | echo "Generating slugs.
"; 22 | 23 | while ($row = mysqli_fetch_assoc($result)) { 24 | $id = $row['id']; 25 | $title = $row['title']; 26 | $description = $row['description']; 27 | $slug = $row['slug']; 28 | 29 | if (is_null($slug)){ 30 | $new_slug = slug($title); 31 | 32 | $sql2 = "UPDATE posts SET slug = '$new_slug' WHERE id = $id"; 33 | 34 | if (mysqli_query($dbcon, $sql2)) { 35 | $permalink = "p/".$id."/".$new_slug; 36 | 37 | echo "Slug successfully generated for $title
" ; 38 | } else { 39 | echo "Failed to generate slug for post ID: $id." . mysqli_connect_error(); 40 | } 41 | 42 | } 43 | 44 | } 45 | 46 | mysqli_close($dbcon); -------------------------------------------------------------------------------- /header.php: -------------------------------------------------------------------------------- 1 | 12 | 13 | 14 | 15 | 16 | 17 | PHP Blog 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 |
26 |

PHP Blog

27 |
28 | 29 |
30 | Home 31 | New Post"; 34 | echo "Admin Panel"; 35 | echo "Logout"; 36 | } else { 37 | echo "Login"; 38 | } 39 | ?> 40 |
41 | 42 |
43 |
44 |

45 | 46 |

47 |

48 | 49 |

50 | 51 |
-------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | 5 | 6 |
7 |

This is a simple blog project for my PHP development skills.

8 |
9 | 10 | $totalpages) { 26 | $page = $totalpages; 27 | } 28 | 29 | if ($page < 1) { 30 | $page = 1; 31 | } 32 | $offset = ($page - 1) * $rowsperpage; 33 | 34 | $sql = "SELECT * FROM posts ORDER BY id DESC LIMIT $offset, $rowsperpage"; 35 | $result = mysqli_query($dbcon, $sql); 36 | 37 | if (mysqli_num_rows($result) < 1) { 38 | echo '
No post yet!
'; 39 | } else { 40 | while ($row = mysqli_fetch_assoc($result)) { 41 | 42 | $id = htmlentities($row['id']); 43 | $title = htmlentities($row['title']); 44 | $des = htmlentities(strip_tags($row['description'])); 45 | $slug = htmlentities($row['slug']); 46 | $time = htmlentities($row['date']); 47 | 48 | $permalink = "p/".$id ."/".$slug; 49 | 50 | echo '
'; 51 | echo "

$title

"; 52 | 53 | echo substr($des, 0, 100); 54 | 55 | echo '

'; 56 | echo "Read more...

"; 57 | 58 | echo '
'; 59 | echo "
$time
"; 60 | echo '
'; 61 | } 62 | 63 | 64 | echo "

"; 65 | 66 | if ($page > 1) { 67 | echo "«"; 68 | $prevpage = $page - 1; 69 | echo "<"; 70 | } 71 | 72 | $range = 5; 73 | for ($x = $page - $range; $x < ($page + $range) + 1; $x++) { 74 | if (($x > 0) && ($x <= $totalpages)) { 75 | if ($x == $page) { 76 | echo "
$x
"; 77 | } else { 78 | echo "$x"; 79 | } 80 | } 81 | } 82 | 83 | if ($page != $totalpages) { 84 | $nextpage = $page + 1; 85 | echo ">"; 86 | echo "»"; 87 | } 88 | 89 | echo "

"; 90 | } 91 | 92 | include("categories.php"); 93 | include("footer.php"); 94 | -------------------------------------------------------------------------------- /login.php: -------------------------------------------------------------------------------- 1 | Login'; 6 | 7 | if (isset($_POST['log'])) { 8 | $username = mysqli_real_escape_string($dbcon, $_POST['username']); 9 | $password = mysqli_real_escape_string($dbcon, $_POST['password']); 10 | 11 | $sql = "SELECT * FROM admin WHERE username = '$username'"; 12 | 13 | $result = mysqli_query($dbcon, $sql); 14 | $row = mysqli_fetch_assoc($result); 15 | $row_count = mysqli_num_rows($result); 16 | 17 | 18 | if ($row_count == 1 && password_verify($password, $row['password'])) { 19 | $_SESSION['username'] = $username; 20 | header("location: admin.php"); 21 | } else { 22 | echo "
Incorrect username or password.
"; 23 | } 24 | } 25 | ?> 26 | 27 | 28 | 29 | 30 | 31 | 32 |

33 | 34 | 35 | ", 19 | $permalink); 20 | 21 | } else { 22 | ?> 23 |
24 |
25 |
26 |

New Post

27 |
28 | 29 |
30 | 31 |

32 | 33 | 34 |

35 | 36 |

37 | 38 | 39 |

40 |

41 | 42 |

43 | 44 | 45 |
46 |
47 | Showing results for $q"; 16 | 17 | while ($row = mysqli_fetch_assoc($result)) { 18 | 19 | $id = htmlentities($row['id']); 20 | $title = htmlentities($row['title']); 21 | $des = htmlentities(strip_tags($row['description'])); 22 | $slug = htmlentities(strip_tags($row['slug'])); 23 | $time = htmlentities($row['date']); 24 | 25 | $permalink = "p/".$id ."/".$slug; 26 | 27 | echo '
'; 28 | echo "

$title

"; 29 | 30 | echo substr($des, 0, 100); 31 | 32 | echo '

'; 33 | echo "Read more..."; 34 | 35 | echo '
'; 36 | echo "$time
"; 37 | echo '
'; 38 | 39 | } 40 | 41 | } 42 | } 43 | include("footer.php"); 44 | -------------------------------------------------------------------------------- /security.php: -------------------------------------------------------------------------------- 1 | '; 28 | 29 | echo "

$title

"; 30 | echo '
'; 31 | echo "$description
"; 32 | echo '
'; 33 | echo "Posted by: " . $author . "
"; 34 | echo "$time
"; 35 | ?> 36 | 37 | 38 | 41 |
[Edit]
42 |
43 | [Delete]
45 |
'; 48 | 49 | 50 | include("footer.php"); 51 | --------------------------------------------------------------------------------
IDTitleDateViewsAction
Edit | Delete 66 |