Mysql
 sql >> Datenbank >  >> RDS >> Mysql

So erstellen Sie ein Blog in einer PHP- und MySQL-Datenbank - DB-Design

Die Datenbank

Dies ist der zweite Teil einer Reihe zum Erstellen eines Blogs mit PHP und MySQL. Den ersten Teil erhalten Sie hier

Wir machen dort weiter, wo wir im letzten Tutorial aufgehört haben. In diesem Abschnitt werden wir an unserem Datenbankdesign und der Benutzerauthentifizierung (Registrierung und Anmeldung) arbeiten. Erstellen Sie eine Datenbank namens complete-blog-php. Erstellen Sie in dieser Datenbank zwei Tabellen: Beiträge und Nutzer mit den folgenden Feldern.

Beiträge:

+----+-----------+--------------+------------+
|     field      |     type     | specs      |
+----+-----------+--------------+------------+
|  id            | INT(11)      |            |
|  user_id       | INT(11)      |            |
|  title         | VARCHAR(255) |            |
|  slug          | VARCHAR(255) | UNIQUE     |
|  views         | INT(11)      |            |
|  image         | VARCHAR(255) |            |
|  body          | TEXT         |            |
|  published     | boolean      |            |
|  created_at    | TIMESTAMP    |            |
|  updated_at    | TIMESTAMP    |            |
+----------------+--------------+------------+

Benutzer:

+----+-----------+------------------------+------------+
|     field      |     type               | specs      |
+----+-----------+------------------------+------------+
|  id            | INT(11)                |            |
|  username      | VARCHAR(255)           | UNIQUE     |
|  email         | VARCHAR(255)           | UNIQUE     |
|  role          | ENUM("Admin","Author") |            |
|  password      | VARCHAR(255)           |            |
|  created_at    | TIMESTAMP              |            |
|  updated_at    | TIMESTAMP              |            |
+----------------+--------------+---------+------------+

Sie können diese Tabellen mit diesen Befehlen erstellen.

Benutzer:

CREATE TABLE `users` (
  `id` int(11) AUTO_INCREMENT PRIMARY KEY NOT NULL,
  `username` varchar(255) NOT NULL,
  `email` varchar(255) NOT NULL,
  `role` enum('Author','Admin') DEFAULT NULL,
  `password` varchar(255) NOT NULL,
  `created_at` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
  `updated_at` timestamp NULL DEFAULT NULL
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

Beiträge:

CREATE TABLE `posts` (
 `id` int(11) NOT NULL AUTO_INCREMENT PRIMARY KEY,
 `user_id` int(11) DEFAULT NULL,
 `title` varchar(255) NOT NULL,
 `slug` varchar(255) NOT NULL UNIQUE,
 `views` int(11) NOT NULL DEFAULT '0',
 `image` varchar(255) NOT NULL,
 `body` text NOT NULL,
 `published` tinyint(1) NOT NULL,
 `created_at` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
 `updated_at` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
  FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB DEFAULT CHARSET=latin1

Sie können diese Skripts über die SQL-Eingabeaufforderung oder PHPMyAdmin ausführen. Klicken/wählen Sie in PHPMyAdmin die Datenbank aus, unter der diese Tabellen erstellt werden sollen (in diesem Fall complete-blog-php), und klicken Sie dann auf die Registerkarte SQL in der Navigationsleiste irgendwo oben auf der Seite. Wenn Sie im unteren Bereich ein SQL-Skript sehen, entfernen Sie es und fügen Sie das obige Skript in den dafür vorgesehenen Bereich ein und klicken Sie auf „Los“, um die Tabellen zu erstellen.

Wenn Sie diese Tabellen stattdessen manuell erstellen möchten, denken Sie daran, das Slug-Feld in der Post-Tabelle EINZIGARTIG zu machen, und denken Sie daran, das Feld user_id der Posts-Tabelle als Fremdschlüssel festzulegen, der auf die ID in der Benutzertabelle verweist. Legen Sie KEINE AKTION als Wert für die Optionen BEI LÖSCHEN und BEI UPDATE fest, damit beim Löschen oder Aktualisieren eines Benutzers dessen Beiträge in der Beitragstabelle verbleiben und nicht gelöscht werden.

Fügen Sie nun einige Benutzer in die Benutzertabelle und einige Beiträge in die Posts-Tabelle ein. Sie können dies tun, indem Sie diese SQL-Abfragen ausführen, um Folgendes einzufügen:

Benutzer:

INSERT INTO `users` (`id`, `username`, `email`, `role`, `password`, `created_at`, `updated_at`) VALUES
(1, 'Awa', '[email protected]', 'Admin', 'mypassword', '2018-01-08 12:52:58', '2018-01-08 12:52:58')

Beiträge: 

INSERT INTO `posts` (`id`, `user_id`, `title`, `slug`, `views`, `image`, `body`, `published`, `created_at`, `updated_at`) VALUES
(1, 1, '5 Habits that can improve your life', '5-habits-that-can-improve-your-life', 0, 'banner.jpg', 'Read every day', 1, '2018-02-03 07:58:02', '2018-02-01 19:14:31'),
(2, 1, 'Second post on LifeBlog', 'second-post-on-lifeblog', 0, 'banner.jpg', 'This is the body of the second post on this site', 0, '2018-02-02 11:40:14', '2018-02-01 13:04:36')

Lassen Sie uns eine Verbindung zur Datenbank herstellen, diese Beiträge abfragen und auf der Webseite anzeigen.

Lassen Sie uns in config.php Code hinzufügen, um unsere Anwendung mit der Datenbank zu verbinden. Nach dem Hinzufügen des Codes sieht unsere config.php-Datei so aus:

<?php 
	session_start();
	// connect to database
	$conn = mysqli_connect("localhost", "root", "", "complete-blog-php");

	if (!$conn) {
		die("Error connecting to database: " . mysqli_connect_error());
	}
    // define global constants
	define ('ROOT_PATH', realpath(dirname(__FILE__)));
	define('BASE_URL', 'http://localhost/complete-blog-php/');
?>

Dies gibt ein Datenbankverbindungsobjekt $conn zurück, das wir in unserer gesamten Anwendung zum Abfragen der Datenbank verwenden können.

Diese Anwendung wurde so strukturiert, dass der PHP-Code so weit wie möglich von HTML getrennt ist. Vorgänge wie das Abfragen der Datenbank und das Ausführen einer Logik für Daten werden in PHP-Funktionen ausgeführt und die Ergebnisse zur Anzeige an HTML gesendet. Um alle Posts aus der Datenbank zu bekommen, werden wir das in einer Funktion machen und die Ergebnisse als assoziatives Array zurückgeben, das durchgeschleift und auf der Seite angezeigt wird.

Erstellen Sie daher im Ordner „includes“ eine Datei mit dem Namen „public_functions.php“. Diese Datei wird alle unsere PHP-Funktionen für den öffentlichen Bereich enthalten. Alle Seiten, die eine der Funktionen in dieser Datei verwenden, müssen diese Datei im oberen Abschnitt der Seite enthalten.

Lassen Sie uns unsere erste Funktion in unserer neu erstellten public_functions.php erstellen. Wir nennen die Funktion getPublishedPosts() und sie ruft alle Posts aus der Posts-Tabelle in der Datenbank ab und gibt sie als assoziatives Array zurück:

public_functions.php:

<?php 
/* * * * * * * * * * * * * * *
* Returns all published posts
* * * * * * * * * * * * * * */
function getPublishedPosts() {
	// use global $conn object in function
	global $conn;
	$sql = "SELECT * FROM posts WHERE published=true";
	$result = mysqli_query($conn, $sql);

	// fetch all posts as an associative array called $posts
	$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);

	return $posts;
}

// more functions to come here ...
?>

Im oberen Abschnitt der Datei index.php, direkt unter der Zeile, die config. enthält php , fügen Sie diesen Code hinzu, um die Datenbank abzufragen:

<!-- config.php should be here as the first include  -->

<?php require_once( ROOT_PATH . '/includes/public_functions.php') ?>

<!-- Retrieve all posts from database  -->
<?php $posts = getPublishedPosts(); ?>

Wir haben zwei Codezeilen hinzugefügt. Die erste schließt die Datei public_functions.php (die die Funktionen enthält) in unsere Datei index.php ein. Die zweite Codezeile ruft die Funktion getPublishedPosts() auf, die die Datenbank abfragt und aus der Datenbank abgerufene Posts in einer Variablen namens $posts zurückgibt. Lassen Sie uns nun diese Posts auf der Seite index.php durchgehen und anzeigen.

Öffnen Sie unsere berühmte index.php-Datei erneut. Irgendwo in der Mitte des Inhaltsbereichs finden Sie ein


-Tag und einen Kommentar, der angibt, wo weitere Inhalte erscheinen sollen. Fügen Sie im Feld direkt unter dem Tag
diesen Code hinzu:

<hr>
<!-- more content still to come here ... -->

<!-- Add this ... -->
<?php foreach ($posts as $post): ?>
	<div class="post" style="margin-left: 0px;">
		<img src="<?php echo BASE_URL . '/static/images/' . $post['image']; ?>" class="post_image" alt="">
		<a href="single_post.php?post-slug=<?php echo $post['slug']; ?>">
			<div class="post_info">
				<h3><?php echo $post['title'] ?></h3>
				<div class="info">
					<span><?php echo date("F j, Y ", strtotime($post["created_at"])); ?></span>
					<span class="read_more">Read more...</span>
				</div>
			</div>
		</a>
	</div>
<?php endforeach ?>

Okay, bitte laden Sie die Seite noch nicht neu. Lassen Sie uns dieser Beitragsliste ein Styling hinzufügen. Öffnen Sie public_styling.css und fügen Sie diesen Code hinzu:

/* CONTENT */
.content {
	margin: 5px auto;
	border-radius: 5px;
	min-height: 400px;
}
.content:after {
	content: "";
	display: block;
	clear: both;
}
.content .content-title {
	margin: 10px 0px;
	color: #374447;
	font-family: 'Averia Serif Libre', cursive;
}
.content .post {
	width: 335px;
	margin: 9px;
	min-height: 320px;
	float: left;
	border-radius: 2px;
	border: 1px solid #b3b3b3;
	position: relative;
}
.content .post .category {
	margin-top: 0px;
	padding: 3px 8px;
	color: #374447;
	background: white;
	display: inline-block;
	border-radius: 2px;
	border: 1px solid #374447;
	box-shadow: 3px 2px 2px;
	position: absolute;
	left: 5px; top: 5px;
	z-index: 3;
}
.content .post .category:hover {
	box-shadow: 3px 2px 2px;
	color: white;
	background: #374447;
	transition: .4s;
	opacity: 1;
}
.content .post .post_image {
	height: 260px;
	width: 100%;
	background-size: 100%;
}
.content .post .post_image {
	width: 100%;
	height: 260px;
}
.content .post .post_info {
	height: 100%;
	padding: 0px 5px;
	font-weight: 200;
    font-family: 'Noto Serif', serif;
}
.content .post .post_info {
	color: #222;
}
.content .post .post_info span {
	color: #A6A6A6;
	font-style: italic;
}
.content .post .post_info span.read_more {
	position: absolute;
	right: 5px; bottom: 5px;
}

Jetzt können Sie die Seite neu laden.

Wenn alles gut gelaufen ist, sehen Sie unter dem Titel "Neueste Artikel" einen einzelnen Beitrag, der als Miniaturansicht gestaltet ist. Denken Sie daran, dass wir zwei Datensätze in die Datenbank eingefügt haben, aber nur einer angezeigt wird. Das liegt daran, dass das veröffentlichte Feld eines der Datensätze auf „false“ (d. h. 0) gesetzt war und da nur veröffentlichte Artikel angezeigt werden, sehen wir nur einen, den veröffentlichten.

Aber unsere Beiträge sind noch keinem Thema zugeordnet. Lassen Sie uns eine Thementabelle erstellen und eine Viele-zu-Viele-Beziehung zwischen den Beiträgen und der Thementabelle herstellen. Dazu erstellen wir zwei neue Tabellen:themen, um Themen zu speichern, und eine post_topic-Tabelle, um die Beziehung zwischen Beiträgen und Themen zu handhaben.

Themen:

+----+-----------+------------------------+------------+
|     field      |     type               | specs      |
+----+-----------+------------------------+------------+
|  id            | INT(11)                |            |
|  name          | VARCHAR(255)           |            |
|  slug          | VARCHAR(255)           | UNIQUE     |
+----------------+--------------+---------+------------+

post_topic:

+----+-----------+------------------------+------------+
|     field      |     type               | specs      |
+----+-----------+------------------------+------------+
|  id            | INT(11)                |            |
|  post_id       | INT(11)                |  UNIQUE    |
|  topic_id      | INT(11)                |            |
+----------------+--------------+---------+------------+

Was uns wirklich interessiert, ist die Tabelle post_topic. Dies ist die Tabelle, die die Beziehung zwischen Beiträgen und Themen handhabt. Wenn ein Beitrag unter einem bestimmten Thema erstellt wird, werden die ID dieses Beitrags (post_id) sowie die ID des Themas (topic_id), unter dem dieser Beitrag erstellt wird, in die post_topic-Tabelle eingefügt.

Lassen Sie uns diese Beziehung so einrichten, dass beim Löschen eines Beitrags auch dessen Eintrag in der post_topic-Tabelle automatisch gelöscht wird; Sie möchten keine Informationen über die Beziehung eines Beitrags behalten, wenn der Beitrag nicht existiert, oder?

Klicken/wählen Sie die post_topic-Tabelle aus und klicken Sie dann auf die Struktur-Registerkarte der PHPMyAdmin-Navigationsleiste. Klicken Sie als Nächstes direkt unter der Registerkarte "Struktur" auf "Beziehungsansicht" (je nach Ihrer Version von PHPMyAdmin kann sie auch woanders zu finden sein). Dann füllen Sie das folgende Formular wie folgt aus:

Tipp:Der Link +Einschränkung hinzufügen wird verwendet, um eine neue Einschränkung hinzuzufügen.

ON DELETE und ON UPDATE sind alle auf CASCADE bzw. NO ACTION eingestellt, sodass beim Löschen eines Beitrags oder Themas automatisch auch die Beziehungsinformationen in der post_topic-Tabelle gelöscht werden. (Im Bild habe ich einen Fehler gemacht, ON UPDATE auf CASCADE anstatt auf NO ACTION zu setzen, sorry dafür).

Klicken Sie auf Speichern und das war's. Die Tabellen sind jetzt miteinander verbunden. Aber um eine Beziehung zwischen Beiträgen und Themen herzustellen, müssen wir die Thementabelle mit Themen füllen und schließlich die post_topic-Tabelle, die die eigentlichen Beziehungsinformationen enthält.

Fügen wir nun ein paar Einträge in die beiden Tabellen ein:

Themen:

INSERT INTO `topics` (`id`, `name`, `slug`) VALUES
(1, 'Inspiration', 'inspiration'),
(2, 'Motivation', 'motivation'),
(3, 'Diary', 'diary')

post_topic:

INSERT INTO `post_topic` (`id`, `post_id`, `topic_id`) VALUES
(1, 1, 1),
(2, 2, 2)

Die in der Tabelle „post_topic“ definierte Beziehung besagt, dass das Thema mit der ID 1 in der Tabelle „topics“ zu dem Beitrag mit der ID 1 in der Tabelle „posts“ gehört. Dasselbe gilt für das Thema mit der ID 2 und den Beitrag mit der ID 2.

Auf jeder Post-Liste auf der Seite index.php zeigen wir das Thema an, unter dem der Post erstellt wurde.

Dazu müssen wir unser in public_functions.php erstelltes getPublishedPosts() ändern, um das Thema jedes Beitrags aus der Datenbank abzufragen und den Beitrag zusammen mit seinem Thema zurückzugeben.

Ändern Sie die Datei public_functions.php so, dass sie wie folgt aussieht:

<?php 
/* * * * * * * * * * * * * * *
* Returns all published posts
* * * * * * * * * * * * * * */
function getPublishedPosts() {
	// use global $conn object in function
	global $conn;
	$sql = "SELECT * FROM posts WHERE published=true";
	$result = mysqli_query($conn, $sql);
	// fetch all posts as an associative array called $posts
	$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);

	$final_posts = array();
	foreach ($posts as $post) {
		$post['topic'] = getPostTopic($post['id']); 
		array_push($final_posts, $post);
	}
	return $final_posts;
}
/* * * * * * * * * * * * * * *
* Receives a post id and
* Returns topic of the post
* * * * * * * * * * * * * * */
function getPostTopic($post_id){
	global $conn;
	$sql = "SELECT * FROM topics WHERE id=
			(SELECT topic_id FROM post_topic WHERE post_id=$post_id) LIMIT 1";
	$result = mysqli_query($conn, $sql);
	$topic = mysqli_fetch_assoc($result);
	return $topic;
}
?>

Gehen Sie nun zur Datei index.php. Fügen Sie innerhalb der foreach-Schleife direkt unter dem Bild-Tag die if-Anweisung hinzu, um das Thema anzuzeigen. Ihre foreach-Schleife sollte nach der Änderung so aussehen:

<?php foreach ($posts as $post): ?>
	<div class="post" style="margin-left: 0px;">
		<img src="<?php echo BASE_URL . '/static/images/' . $post['image']; ?>" class="post_image" alt="">
        <!-- Added this if statement... -->
		<?php if (isset($post['topic']['name'])): ?>
			<a 
				href="<?php echo BASE_URL . 'filtered_posts.php?topic=' . $post['topic']['id'] ?>"
				class="btn category">
				<?php echo $post['topic']['name'] ?>
			</a>
		<?php endif ?>

		<a href="single_post.php?post-slug=<?php echo $post['slug']; ?>">
			<div class="post_info">
				<h3><?php echo $post['title'] ?></h3>
				<div class="info">
					<span><?php echo date("F j, Y ", strtotime($post["created_at"])); ?></span>
					<span class="read_more">Read more...</span>
				</div>
			</div>
		</a>
	</div>
<?php endforeach ?>

Laden Sie nun die Seite neu und Sie sehen das Thema im Beitrag angezeigt.

In dieser Foreach-Schleife sehen Sie, dass es zwei Links gibt, die Sie beim Anklicken zu zwei Seiten führen:„filtered_posts.php“ und „single_post.php“.

gefilterte_posts.php ist eine Seite, die alle Posts unter einem bestimmten Thema auflistet, wenn der Benutzer auf dieses Thema klickt.

single_post.php ist eine Seite, die den vollständigen Beitrag im Detail zusammen mit Kommentaren anzeigt, wenn der Benutzer auf das Miniaturbild des Beitrags klickt.

Diese beiden Dateien benötigen einige Funktionen aus unserer Datei public_functions.php. „filtered_posts.php“ benötigt zwei Funktionen namens „getPublishedPostsByTopic()“ und „getTopicNameById()“, während „single_posts.php“ getPost() und getAllTopics() benötigt.

Beginnen wir mit der Datei „filtered_posts.php“. Öffnen Sie public_functions.php und fügen Sie diese beiden Funktionen zur Liste der Funktionen hinzu:

/* * * * * * * * * * * * * * * *
* Returns all posts under a topic
* * * * * * * * * * * * * * * * */
function getPublishedPostsByTopic($topic_id) {
	global $conn;
	$sql = "SELECT * FROM posts ps 
			WHERE ps.id IN 
			(SELECT pt.post_id FROM post_topic pt 
				WHERE pt.topic_id=$topic_id GROUP BY pt.post_id 
				HAVING COUNT(1) = 1)";
	$result = mysqli_query($conn, $sql);
	// fetch all posts as an associative array called $posts
	$posts = mysqli_fetch_all($result, MYSQLI_ASSOC);

	$final_posts = array();
	foreach ($posts as $post) {
		$post['topic'] = getPostTopic($post['id']); 
		array_push($final_posts, $post);
	}
	return $final_posts;
}
/* * * * * * * * * * * * * * * *
* Returns topic name by topic id
* * * * * * * * * * * * * * * * */
function getTopicNameById($id)
{
	global $conn;
	$sql = "SELECT name FROM topics WHERE id=$id";
	$result = mysqli_query($conn, $sql);
	$topic = mysqli_fetch_assoc($result);
	return $topic['name'];
}

Lassen Sie uns zuerst die Datei „filtered_posts.php“ im Stammordner unserer Anwendung erstellen (also „complete-blog-php/filtered_posts.php“). Ich fahre einfach fort und füge den gesamten Code dieser Seite in die Datei ein:

gefilterte_posts.php:

<?php include('config.php'); ?>
<?php include('includes/public_functions.php'); ?>
<?php include('includes/head_section.php'); ?>
<?php 
	// Get posts under a particular topic
	if (isset($_GET['topic'])) {
		$topic_id = $_GET['topic'];
		$posts = getPublishedPostsByTopic($topic_id);
	}
?>
	<title>LifeBlog | Home </title>
</head>
<body>
<div class="container">
<!-- Navbar -->
	<?php include( ROOT_PATH . '/includes/navbar.php'); ?>
<!-- // Navbar -->
<!-- content -->
<div class="content">
	<h2 class="content-title">
		Articles on <u><?php echo getTopicNameById($topic_id); ?></u>
	</h2>
	<hr>
	<?php foreach ($posts as $post): ?>
		<div class="post" style="margin-left: 0px;">
			<img src="<?php echo BASE_URL . '/static/images/' . $post['image']; ?>" class="post_image" alt="">
			<a href="single_post.php?post-slug=<?php echo $post['slug']; ?>">
				<div class="post_info">
					<h3><?php echo $post['title'] ?></h3>
					<div class="info">
						<span><?php echo date("F j, Y ", strtotime($post["created_at"])); ?></span>
						<span class="read_more">Read more...</span>
					</div>
				</div>
			</a>
		</div>
	<?php endforeach ?>
</div>
<!-- // content -->
</div>
<!-- // container -->

<!-- Footer -->
	<?php include( ROOT_PATH . '/includes/footer.php'); ?>
<!-- // Footer -->

Aktualisieren Sie jetzt die Seite, klicken Sie auf das Thema und wenn Sie zu einer Seite gelangen, die Beiträge zu diesem Thema anzeigt, dann machen Sie das Richtige.

Machen wir dasselbe mit single_post.php. Öffnen Sie public_functions.php und fügen Sie diese 2 Funktionen hinzu:

/* * * * * * * * * * * * * * *
* Returns a single post
* * * * * * * * * * * * * * */
function getPost($slug){
	global $conn;
	// Get single post slug
	$post_slug = $_GET['post-slug'];
	$sql = "SELECT * FROM posts WHERE slug='$post_slug' AND published=true";
	$result = mysqli_query($conn, $sql);

	// fetch query results as associative array.
	$post = mysqli_fetch_assoc($result);
	if ($post) {
		// get the topic to which this post belongs
		$post['topic'] = getPostTopic($post['id']);
	}
	return $post;
}
/* * * * * * * * * * * *
*  Returns all topics
* * * * * * * * * * * * */
function getAllTopics()
{
	global $conn;
	$sql = "SELECT * FROM topics";
	$result = mysqli_query($conn, $sql);
	$topics = mysqli_fetch_all($result, MYSQLI_ASSOC);
	return $topics;
}

Erstellen Sie nun die Datei complete-blog-php/single_post.php und fügen Sie diesen Code darin ein:

<?php  include('config.php'); ?>
<?php  include('includes/public_functions.php'); ?>
<?php 
	if (isset($_GET['post-slug'])) {
		$post = getPost($_GET['post-slug']);
	}
	$topics = getAllTopics();
?>
<?php include('includes/head_section.php'); ?>
<title> <?php echo $post['title'] ?> | LifeBlog</title>
</head>
<body>
<div class="container">
	<!-- Navbar -->
		<?php include( ROOT_PATH . '/includes/navbar.php'); ?>
	<!-- // Navbar -->
	
	<div class="content" >
		<!-- Page wrapper -->
		<div class="post-wrapper">
			<!-- full post div -->
			<div class="full-post-div">
			<?php if ($post['published'] == false): ?>
				<h2 class="post-title">Sorry... This post has not been published</h2>
			<?php else: ?>
				<h2 class="post-title"><?php echo $post['title']; ?></h2>
				<div class="post-body-div">
					<?php echo html_entity_decode($post['body']); ?>
				</div>
			<?php endif ?>
			</div>
			<!-- // full post div -->
			
			<!-- comments section -->
			<!--  coming soon ...  -->
		</div>
		<!-- // Page wrapper -->

		<!-- post sidebar -->
		<div class="post-sidebar">
			<div class="card">
				<div class="card-header">
					<h2>Topics</h2>
				</div>
				<div class="card-content">
					<?php foreach ($topics as $topic): ?>
						<a 
							href="<?php echo BASE_URL . 'filtered_posts.php?topic=' . $topic['id'] ?>">
							<?php echo $topic['name']; ?>
						</a> 
					<?php endforeach ?>
				</div>
			</div>
		</div>
		<!-- // post sidebar -->
	</div>
</div>
<!-- // content -->

<?php include( ROOT_PATH . '/includes/footer.php'); ?>

Wenden wir nun das Styling darauf an. Öffnen Sie public_styling.css und fügen Sie diesen Styling-Code hinzu:

/* * * * * * * * *
* SINGLE PAGE 
* * * * * * * * */
.content .post-wrapper {
	width: 70%;
	float: left;
	min-height: 250px;
}
.full-post-div {
	min-height: 300px;
	padding: 20px;
	border: 1px solid #e4e1e1;
	border-radius: 2px;
}
.full-post-div h2.post-title {
	margin: 10px auto 20px;
	text-align: center;
}
.post-body-div {
	font-family: 'Noto Serif', serif;
	font-size: 1.2em;
}
.post-body-div p {
	margin:20px 0px;
}
.post-sidebar {
	width: 24%;
	float: left;
	margin-left: 5px;
	min-height: 400px;
}
.content .post-comments {
	margin-top: 25px;
	border-radius: 2px;
	border-top: 1px solid #e4e1e1;
	padding: 10px;
}
.post-sidebar .card {
	width: 95%;
	margin: 10px auto;
	border: 1px solid #e4e1e1;
	border-radius: 10px 10px 0px 0px;
}
.post-sidebar .card .card-header {
	padding: 10px;
	text-align: center;
	border-radius: 3px 3px 0px 0px;
	background: #3E606F;
}
.post-sidebar .card .card-header h2 {
	color: white;
}
.post-sidebar .card .card-content a {
	display: block;
	box-sizing: border-box;
	padding: 8px 10px;
	border-bottom: 1px solid #e4e1e1;
	color: #444;
}
.post-sidebar .card .card-content a:hover {
	padding-left: 20px;
	background: #F9F9F9;
	transition: 0.1s;
}

Sieht jetzt gut aus, oder?

Eine letzte Sache noch, und wir sind mit dem öffentlichen Bereich so gut wie fertig:Wir werden die Benutzerregistrierung und den Login implementieren.

Benutzerregistrierung und Anmeldung

Da ich bereits ein Tutorial zur Benutzerregistrierung und -anmeldung erstellt habe, werde ich mit diesem Teil ziemlich auf den Punkt kommen und nicht viel erklären.

Erstellen Sie zwei Dateien in Ihrem Stammordner mit den Namen register.php und login.php. Öffnen Sie jeden von ihnen und platzieren Sie diesen Code darin:

register.php:

<?php  include('config.php'); ?>
<!-- Source code for handling registration and login -->
<?php  include('includes/registration_login.php'); ?>

<?php include('includes/head_section.php'); ?>

<title>LifeBlog | Sign up </title>
</head>
<body>
<div class="container">
	<!-- Navbar -->
		<?php include( ROOT_PATH . '/includes/navbar.php'); ?>
	<!-- // Navbar -->

	<div style="width: 40%; margin: 20px auto;">
		<form method="post" action="register.php" >
			<h2>Register on LifeBlog</h2>
			<?php include(ROOT_PATH . '/includes/errors.php') ?>
			<input  type="text" name="username" value="<?php echo $username; ?>"  placeholder="Username">
			<input type="email" name="email" value="<?php echo $email ?>" placeholder="Email">
			<input type="password" name="password_1" placeholder="Password">
			<input type="password" name="password_2" placeholder="Password confirmation">
			<button type="submit" class="btn" name="reg_user">Register</button>
			<p>
				Already a member? <a href="login.php">Sign in</a>
			</p>
		</form>
	</div>
</div>
<!-- // container -->
<!-- Footer -->
	<?php include( ROOT_PATH . '/includes/footer.php'); ?>
<!-- // Footer -->

login.php:  

<?php  include('config.php'); ?>
<?php  include('includes/registration_login.php'); ?>
<?php  include('includes/head_section.php'); ?>
	<title>LifeBlog | Sign in </title>
</head>
<body>
<div class="container">
	<!-- Navbar -->
	<?php include( ROOT_PATH . '/includes/navbar.php'); ?>
	<!-- // Navbar -->

	<div style="width: 40%; margin: 20px auto;">
		<form method="post" action="login.php" >
			<h2>Login</h2>
			<?php include(ROOT_PATH . '/includes/errors.php') ?>
			<input type="text" name="username" value="<?php echo $username; ?>" value="" placeholder="Username">
			<input type="password" name="password" placeholder="Password">
			<button type="submit" class="btn" name="login_btn">Login</button>
			<p>
				Not yet a member? <a href="register.php">Sign up</a>
			</p>
		</form>
	</div>
</div>
<!-- // container -->

<!-- Footer -->
	<?php include( ROOT_PATH . '/includes/footer.php'); ?>
<!-- // Footer -->

In den oberen Abschnitten beider Dateien haben wir eine Datei mit dem Namen registration_login.php eingefügt, um die Logik der Registrierung und Anmeldung zu handhaben. Dies ist die Datei, an die die Informationen zum Anmelde- und Registrierungsformular gesendet werden, und die Kommunikation mit der Datenbank erfolgt. Lassen Sie uns es in unserem Ordner "includes" erstellen und diesen Code darin spucken:

vollständiger-blog-php/includes/registration_login.php:

<?php 
	// variable declaration
	$username = "";
	$email    = "";
	$errors = array(); 

	// REGISTER USER
	if (isset($_POST['reg_user'])) {
		// receive all input values from the form
		$username = esc($_POST['username']);
		$email = esc($_POST['email']);
		$password_1 = esc($_POST['password_1']);
		$password_2 = esc($_POST['password_2']);

		// form validation: ensure that the form is correctly filled
		if (empty($username)) {  array_push($errors, "Uhmm...We gonna need your username"); }
		if (empty($email)) { array_push($errors, "Oops.. Email is missing"); }
		if (empty($password_1)) { array_push($errors, "uh-oh you forgot the password"); }
		if ($password_1 != $password_2) { array_push($errors, "The two passwords do not match");}

		// Ensure that no user is registered twice. 
		// the email and usernames should be unique
		$user_check_query = "SELECT * FROM users WHERE username='$username' 
								OR email='$email' LIMIT 1";

		$result = mysqli_query($conn, $user_check_query);
		$user = mysqli_fetch_assoc($result);

		if ($user) { // if user exists
			if ($user['username'] === $username) {
			  array_push($errors, "Username already exists");
			}
			if ($user['email'] === $email) {
			  array_push($errors, "Email already exists");
			}
		}
		// register user if there are no errors in the form
		if (count($errors) == 0) {
			$password = md5($password_1);//encrypt the password before saving in the database
			$query = "INSERT INTO users (username, email, password, created_at, updated_at) 
					  VALUES('$username', '$email', '$password', now(), now())";
			mysqli_query($conn, $query);

			// get id of created user
			$reg_user_id = mysqli_insert_id($conn); 

			// put logged in user into session array
			$_SESSION['user'] = getUserById($reg_user_id);

			// if user is admin, redirect to admin area
			if ( in_array($_SESSION['user']['role'], ["Admin", "Author"])) {
				$_SESSION['message'] = "You are now logged in";
				// redirect to admin area
				header('location: ' . BASE_URL . 'admin/dashboard.php');
				exit(0);
			} else {
				$_SESSION['message'] = "You are now logged in";
				// redirect to public area
				header('location: index.php');				
				exit(0);
			}
		}
	}

	// LOG USER IN
	if (isset($_POST['login_btn'])) {
		$username = esc($_POST['username']);
		$password = esc($_POST['password']);

		if (empty($username)) { array_push($errors, "Username required"); }
		if (empty($password)) { array_push($errors, "Password required"); }
		if (empty($errors)) {
			$password = md5($password); // encrypt password
			$sql = "SELECT * FROM users WHERE username='$username' and password='$password' LIMIT 1";

			$result = mysqli_query($conn, $sql);
			if (mysqli_num_rows($result) > 0) {
				// get id of created user
				$reg_user_id = mysqli_fetch_assoc($result)['id']; 

				// put logged in user into session array
				$_SESSION['user'] = getUserById($reg_user_id); 

				// if user is admin, redirect to admin area
				if ( in_array($_SESSION['user']['role'], ["Admin", "Author"])) {
					$_SESSION['message'] = "You are now logged in";
					// redirect to admin area
					header('location: ' . BASE_URL . '/admin/dashboard.php');
					exit(0);
				} else {
					$_SESSION['message'] = "You are now logged in";
					// redirect to public area
					header('location: index.php');				
					exit(0);
				}
			} else {
				array_push($errors, 'Wrong credentials');
			}
		}
	}
	// escape value from form
	function esc(String $value)
	{	
		// bring the global db connect object into function
		global $conn;

		$val = trim($value); // remove empty space sorrounding string
		$val = mysqli_real_escape_string($conn, $value);

		return $val;
	}
	// Get user info from user id
	function getUserById($id)
	{
		global $conn;
		$sql = "SELECT * FROM users WHERE id=$id LIMIT 1";

		$result = mysqli_query($conn, $sql);
		$user = mysqli_fetch_assoc($result);

		// returns user in an array format: 
		// ['id'=>1 'username' => 'Awa', 'email'=>'[email protected]', 'password'=> 'mypass']
		return $user; 
	}
?>

Gehen Sie zu http://localhost/complete-blog-php/register.php und Sie sehen eine Fehlermeldung, die besagt, dass die Datei „errors.php“ nicht gefunden wurde.

errors.php-Datei ist die Datei mit Code zur Anzeige von Formularvalidierungsfehlern. Erstellen Sie die Datei „errors.php“ in „complete-blog-php/includes“ und fügen Sie diesen Code ein:

<?php if (count($errors) > 0) : ?>
  <div class="message error validation_errors" >
  	<?php foreach ($errors as $error) : ?>
  	  <p><?php echo $error ?></p>
  	<?php endforeach ?>
  </div>
<?php endif ?>

Öffnen Sie erneut public_styling.css und fügen Sie dieses letzte Stück Styling-Code für diese Datei errors.php und einige andere Elemente hinzu:

/* NOTIFICATION MESSAGES */
.message {
	width: 100%; 
	margin: 0px auto; 
	padding: 10px 0px; 
	color: #3c763d; 
	background: #dff0d8; 
	border: 1px solid #3c763d;
	border-radius: 5px; 
	text-align: center;
}
.error {
	color: #a94442; 
	background: #f2dede; 
	border: 1px solid #a94442; 
	margin-bottom: 20px;
}
.validation_errors p {
	text-align: left;
	margin-left: 10px;
}
.logged_in_info {
	text-align: right; 
	padding: 10px;
}

Und jetzt ist die Fehlermeldung weg. Klicken Sie auf die Schaltfläche Registrieren, ohne das Formular auszufüllen, und Sie sehen schöne Fehlermeldungen.

Lassen Sie uns einen neuen Benutzer erstellen, indem Sie das Formular auf der Seite register.php ausfüllen und auf die Schaltfläche „Registrieren“ klicken. Sie können beliebige gültige Informationen für den Benutzernamen, die E-Mail-Adresse und das Passwort angeben. Merken Sie sich diese nur, denn wir werden sie sehr bald verwenden, um uns auf der Anmeldeseite anzumelden.

Wenn sich ein Nutzer anmeldet, muss er sich auf jeden Fall abmelden können. Erstellen Sie im Stammordner der Anwendung eine Datei mit dem Namen logout.php.

vollständiger-blog-php/logout.php: 

<?php 
	session_start();
	session_unset($_SESSION['user']);
	session_destroy();
	header('location: index.php');
?>

Außerdem möchten wir, wenn sich ein Benutzer anmeldet, seinen Namen und einen Link oder eine Schaltfläche anzeigen, auf die er klicken kann, um sich abzumelden. Für den öffentlichen Bereich machen wir das in der von uns eingebundenen banner.php-Datei. Öffnen Sie die Datei banner.php und ändern Sie den Code so, dass er folgendermaßen aussieht:

vollständiger-blog-php/includes/banner.php:

<?php if (isset($_SESSION['user']['username'])) { ?>
	<div class="logged_in_info">
		<span>welcome <?php echo $_SESSION['user']['username'] ?></span>
		|
		<span><a href="logout.php">logout</a></span>
	</div>
<?php }else{ ?>
	<div class="banner">
		<div class="welcome_msg">
			<h1>Today's Inspiration</h1>
			<p> 
			    One day your life <br> 
			    will flash before your eyes. <br> 
			    Make sure it's worth watching. <br>
				<span>~ Gerard Way</span>
			</p>
			<a href="register.php" class="btn">Join us!</a>
		</div>

		<div class="login_div">
			<form action="<?php echo BASE_URL . 'index.php'; ?>" method="post" >
				<h2>Login</h2>
				<div style="width: 60%; margin: 0px auto;">
					<?php include(ROOT_PATH . '/includes/errors.php') ?>
				</div>
				<input type="text" name="username" value="<?php echo $username; ?>" placeholder="Username">
				<input type="password" name="password"  placeholder="Password"> 
				<button class="btn" type="submit" name="login_btn">Sign in</button>
			</form>
		</div>
	</div>
<?php } ?>

It checks the session to see if a user is available (logged in). If logged in, the username is displayed with the logout link. When there is a logged in user, the banner does not get displayed since it is some sort of a welcome screen to guest users.

You notice that the banner has a login form and this banner is included inside index.php file. Therefore we need to include the code that handles registration and login inside our index.php file also. Open index.php and add this line directly under the include for public_functions.php:

top section of complete-blog-php/index.php:

<?php require_once( ROOT_PATH . '/includes/registration_login.php') ?>

And that's it with user registration and login. In the next section, we begin work on the admin area.

Thank you so much for sticking around up to this point. I hope you found it helpful. If you have any worries, please leave it in the comments below. Your feedback is always very helpful and if you have any bugs in your code, I will try my best to help you out.

I will be very much encouraged to create more of these tutorials with improved quality if you share, subscribe to my site and recommend my site to your friends.