sql >> Database >  >> RDS >> Mysql

Een blog maken in PHP en MySQL-database - DB-ontwerp

De database

Dit is het tweede deel in een serie over het maken van een blog met PHP en MySQL. Je kunt het eerste deel hier downloaden

We gaan verder waar we gebleven waren in de vorige tutorial. In deze sectie werken we aan ons database-ontwerp en gebruikersauthenticatie (registratie en inloggen). Maak een database met de naam complete-blog-php. Maak in deze database 2 tabellen:berichten en gebruikers met de volgende velden.

berichten:

+----+-----------+--------------+------------+
|     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    |            |
+----------------+--------------+------------+

gebruikers:

+----+-----------+------------------------+------------+
|     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              |            |
+----------------+--------------+---------+------------+

U kunt deze tabellen maken met deze opdrachten.

gebruikers:

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;

berichten:

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

U kunt deze scripts uitvoeren met behulp van de SQL-opdrachtprompt of PHPMyAdmin. Klik/selecteer in PHPMyAdmin de database waaronder u deze tabellen wilt maken (in dit geval complete-blog-php), en klik vervolgens op de SQL-tab op de navigatiebalk ergens bovenaan de pagina. Als u een SQL-script in de onderstaande ruimte ziet, verwijder het dan en plak het bovenstaande script in de daarvoor bestemde ruimte en klik op 'Go' om de tabellen te maken.

Als je ervoor kiest om deze tabellen in plaats daarvan handmatig te maken, vergeet dan niet om het veld slug in de post-tabel UNIEK te maken, en vergeet niet om het user_id veld van de tabel posts in te stellen als de externe sleutel die verwijst naar de id in de tabel met gebruikers. Stel GEEN ACTIE in als de waarde voor de opties ON DELETE en ON UPDATE, zodat wanneer een gebruiker wordt verwijderd of bijgewerkt, hun berichten in de berichtentabel blijven en niet worden verwijderd.

Voeg nu een paar gebruikers toe aan de gebruikerstabel en een paar berichten aan de berichtentabel. U kunt dat doen door deze SQL-query's uit te voeren om in te voegen:

gebruikers:

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')

berichten: 

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')

Laten we verbinding maken met de database, deze berichten opvragen en op de webpagina weergeven.

Laten we in config.php code toevoegen om onze applicatie met de database te verbinden. Na het toevoegen van de code ziet ons config.php-bestand er als volgt uit:

<?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/');
?>

Dit retourneert een databaseverbindingsobject $conn dat we in onze hele applicatie kunnen gebruiken om de database te doorzoeken.

Deze applicatie is zo gestructureerd dat PHP-code zo gescheiden mogelijk is van HTML. Bewerkingen, zoals het doorzoeken van de database en het uitvoeren van enige logica op gegevens, worden uitgevoerd in PHP-functies en de resultaten worden naar HTML verzonden om te worden weergegeven. Om alle berichten uit de database te halen, zullen we dat doen in een functie en de resultaten retourneren als een associatieve array die kan worden doorlopen en weergegeven op de pagina.

Maak daarom een ​​bestand met de naam public_functions.php in de map include. Dit bestand bevat al onze PHP-functies voor de openbare ruimte. Op alle pagina's die een van de functies in dit bestand gebruiken, moet dit bestand in het bovenste gedeelte van de pagina staan.

Laten we onze eerste functie maken in onze nieuw gemaakte public_functions.php. We noemen de functie getPublishedPosts() en deze haalt alle berichten op uit de berichtentabel in de database en retourneert ze als een associatieve array:

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 ...
?>

In het bovenste gedeelte van het index.php-bestand, net onder de regel die config bevat. php , voeg deze code toe om de database te doorzoeken:

<!-- 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(); ?>

We hebben twee regels code toegevoegd. De eerste bevat het bestand public_functions.php (dat de functies bevat) naar ons bestand index.php. De tweede regel code roept de functie getPublishedPosts() aan die de database doorzoekt en berichten teruggeeft die uit de database zijn opgehaald in een variabele met de naam $posts. Laten we nu deze berichten doornemen en weergeven op de index.php-pagina.

Open opnieuw ons beroemde index.php-bestand. In het inhoudsgedeelte ergens in het midden vind je een


-tag en een opmerking die aangeeft waar meer inhoud zal komen. Voeg in de ruimte, direct onder de
-tag, deze code toe:

<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 ?>

Oké, alsjeblieft, laad de pagina nog niet opnieuw. Laten we styling toevoegen aan deze berichtlijst. Open public_styling.css en voeg deze code eraan toe:

/* 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;
}

Nu kunt u de pagina opnieuw laden.

Als alles goed is gegaan, zie je één bericht in de vorm van een miniatuur onder de titel 'Recente artikelen'. Onthoud dat we twee records in de database hadden ingevoegd, maar er wordt er maar één weergegeven. Dit is zo omdat het gepubliceerde veld van een van de records is ingesteld op false (dat wil zeggen, 0), en omdat alleen gepubliceerde artikelen worden weergegeven, zien we er maar één, de gepubliceerde.

Maar onze berichten zijn vanaf nu onder geen enkel onderwerp geclassificeerd. Laten we een tabel met onderwerpen maken en een veel-op-veel-relatie vormen tussen de berichten en de tabel met onderwerpen. Om dit te doen, maken we twee nieuwe tabellen:onderwerpen om onderwerpen op te slaan, en post_topic tabel om de relatie tussen berichten en onderwerpen af ​​te handelen.

onderwerpen:

+----+-----------+------------------------+------------+
|     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)                |            |
+----------------+--------------+---------+------------+

Waar we echt in geïnteresseerd zijn, is de post_topic-tabel. Dit is de tabel die de relatie tussen berichten en onderwerpen afhandelt. Wanneer een bericht wordt gemaakt onder een bepaald onderwerp, worden de id van dat bericht (post_id), evenals de id van het onderwerp (topic_id) waaronder dat bericht is gemaakt, ingevoegd in de tabel post_topic.

Laten we deze relatie tot stand brengen, zodat wanneer een bericht wordt verwijderd, hun invoer in de post_topic-tabel ook automatisch wordt verwijderd; je wilt geen informatie over de relatie van een bericht bewaren als het bericht niet bestaat, toch?

Klik/selecteer de post_topic-tabel en klik vervolgens op het tabblad Structuur van de PHPMyAdmin-navigatiebalk. Klik vervolgens op Relatieweergave net onder het tabblad Structuur (deze kan ergens anders worden gevonden, afhankelijk van uw versie van PHPMyAdmin). Vul dan het onderstaande formulier als volgt in:

Tip:de link +Beperking toevoegen wordt gebruikt om een ​​nieuwe beperking toe te voegen.

ON DELETE en ON UPDATE zijn allemaal ingesteld op respectievelijk CASCADE en GEEN ACTIE, zodat wanneer een bericht of een onderwerp wordt verwijderd, de relatie-informatie in de post_topic-tabel ook automatisch wordt verwijderd. (In de afbeelding heb ik een fout gemaakt door ON UPDATE in te stellen op CASCADE in plaats van GEEN ACTIE, sorry daarvoor).

Klik op opslaan en dat is alles. De tabellen zijn nu gerelateerd. Maar om een ​​relatie tot stand te brengen tussen berichten en onderwerpen, moeten we de onderwerpentabel vullen met onderwerpen en uiteindelijk de post_topic-tabel die de feitelijke relatie-informatie is.

Laten we nu een paar items invoegen in de twee tabellen:

onderwerpen:

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)

De relatie die is gedefinieerd in de post_topic-tabel zegt dat het onderwerp met id 1 in de topic-tabel bij de post met id 1 in de posts-tabel hoort. Hetzelfde geldt voor het onderwerp met id 2 en post met id 2.

Op elke postvermelding op de index.php-pagina gaan we het onderwerp weergeven waaronder de post is gemaakt.

Om dit te doen, moeten we onze getPublishedPosts() die we in public_functions.php hebben gemaakt, aanpassen om het onderwerp van elk bericht uit de database te doorzoeken en het bericht samen met het onderwerp terug te sturen.

Pas het bestand public_functions.php aan zodat het er als volgt uitziet:

<?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;
}
?>

Ga nu naar het bestand index.php. Voeg binnen de foreach-lus, direct onder de afbeeldingstag , het if-statement toe om het onderwerp weer te geven. Uw foreach-lus zou er na wijziging als volgt uit moeten zien:

<?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 ?>

Laad nu de pagina opnieuw en je zult het onderwerp in het bericht zien.

Binnen deze foreach-lus zie je dat er twee links zijn die je naar twee pagina's brengen wanneer je erop klikt:filtered_posts.php en single_post.php.

filtered_posts.php is een pagina die alle berichten onder een bepaald onderwerp weergeeft wanneer de gebruiker op dat onderwerp klikt.

single_post.php is een pagina die het volledige bericht in detail weergeeft, samen met opmerkingen wanneer de gebruiker op de miniatuur van het bericht klikt.

Deze twee bestanden hebben enkele functies nodig uit ons bestand public_functions.php. filtered_posts.php heeft twee functies nodig, genaamd getPublishedPostsByTopic() en getTopicNameById() terwijl single_posts.php getPost() en getAllTopics() nodig heeft.

Laten we beginnen met het bestand filtered_posts.php. Open public_functions.php en voeg deze twee functies toe aan de lijst met functies:

/* * * * * * * * * * * * * * * *
* 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'];
}

Laten we eerst het bestand filtered_posts.php maken in de hoofdmap van onze applicatie (dat wil zeggen, complete-blog-php/filtered_posts.php). Ik ga gewoon door en plak de hele code van deze pagina in het bestand:

filtered_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 -->

Ververs nu de pagina, klik op het onderwerp en als u naar een pagina gaat met berichten onder dat onderwerp, dan doet u het juiste.

Laten we hetzelfde doen met single_post.php. Open public_functions.php en voeg deze 2 functies eraan toe:

/* * * * * * * * * * * * * * *
* 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;
}

Maak nu het bestand complete-blog-php/single_post.php en plak deze code erin:

<?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'); ?>

Laten we hier nu styling op toepassen. Open public_styling.css en voeg er deze stijlcode aan toe:

/* * * * * * * * *
* 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;
}

Ziet er nu goed uit toch?

Nog een laatste ding om te doen en we zullen zo goed als klaar zijn met het openbare gebied:we zullen gebruikersregistratie en inloggen implementeren.

Gebruikersregistratie en login

Omdat ik al een tutorial heb gemaakt over gebruikersregistratie en inloggen, zal ik met dit onderdeel redelijk ter zake zijn en niet veel uitleggen.

Maak twee bestanden in uw hoofdmap met de namen register.php en login.php. Open ze allemaal en plaats deze code erin:

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 de bovenste secties van beide bestanden hebben we een bestand met de naam registration_login.php opgenomen om de logica van registratie en inloggen af ​​te handelen. Dit is het bestand waarnaar de inlog- en registratieformulierinformatie wordt verzonden en er wordt gecommuniceerd met de database. Laten we het in onze map 'Includes' maken en deze code erin stoppen:

complete-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; 
	}
?>

Ga naar http://localhost/complete-blog-php/register.php en je ziet een foutmelding dat het errors.php-bestand niet is gevonden.

errors.php-bestand is het bestand met code om formuliervalidatiefouten weer te geven. Maak errors.php in complete-blog-php/includes en plak deze code erin:

<?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 ?>

Open opnieuw public_styling.css. Laten we dit laatste stukje stijlcode voor dit errors.php-bestand en een paar andere elementen toevoegen:

/* 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;
}

En nu is de foutmelding weg. Klik op de knop registreren zonder het formulier in te vullen en je ziet prachtige foutmeldingen weergegeven.

Laten we een nieuwe gebruiker maken door het formulier op de register.php-pagina in te vullen en op de knop registreren te klikken. U kunt alle geldige informatie opgeven voor de gebruikersnaam, het e-mailadres en het wachtwoord; zorg ervoor dat u ze onthoudt, want we zullen ze binnenkort gebruiken om in te loggen op de inlogpagina.

Wanneer een gebruiker inlogt, moet hij zeker kunnen uitloggen. Maak in de hoofdmap van de toepassing een bestand met de naam logout.php.

complete-blog-php/logout.php: 

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

Ook wanneer een gebruiker inlogt, willen we hun naam en een link of knop weergeven waarop ze kunnen klikken om uit te loggen. Voor de openbare ruimte doen we dat in het banner.php-bestand dat we hebben toegevoegd. Open het bestand banner.php en wijzig de code zodat deze er als volgt uitziet:

complete-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.


  1. Hoe het aantal weken in datum om te zetten?

  2. Slaapstand gebruikersmodel opslaan in Postgres

  3. Verbinding met Db sterft na>4<24 in spring-boot jpa-slaapstand

  4. Zijn er nadelen aan het gebruik van een generieke varchar(255) voor alle op tekst gebaseerde velden?