聊天API
这是一个使用 Core PHP 的聊天应用程序
每个程序员都希望一生中能开发一次聊天应用程序,无论他/她使用哪种技术栈。开发一个简单的聊天应用程序并不难,但对于初学者来说却有点棘手。现在很多人会问为什么要使用 PHP?好吧,如果你是初学者,那么你应该始终选择像 PHP 这样的脚本语言来开发像这样棘手的应用程序。
因此,在开始制作这样的应用程序之前,您需要一个像Xampp或Wampserver这样的服务器。这有助于在您使用 PHP 编码时创建一个本地工作环境。设置好 xampp 服务器后,转到htdocs文件夹并为您的应用程序创建一个文件夹。我将我的应用程序命名为“Wassup”,因为我不太有创意 :(。我使用的是 xampp,它看起来像这样:
我们先来想想我们的 API 会包含哪些页面。目前,我们打算创建一个登录页面、一个注册页面、一个仪表盘页面、一个搜索结果页面和一个消息页面。
这是该项目的 SQL 转储:
-- phpMyAdmin SQL Dump
-- version 5.0.2
-- https://www.phpmyadmin.net/
--
-- Host: 127.0.0.1
-- Generation Time: Sep 20, 2020 at 11:58 PM
-- Server version: 10.4.11-MariaDB
-- PHP Version: 7.3.18
SET SQL_MODE = "NO_AUTO_VALUE_ON_ZERO";
START TRANSACTION;
SET time_zone = "+00:00";
/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
/*!40101 SET NAMES utf8mb4 */;
--
-- Database: `wassup`
--
-- --------------------------------------------------------
--
-- Table structure for table `messages`
--
CREATE TABLE `messages` (
`id` int(100) NOT NULL,
`sent_by` varchar(255) CHARACTER SET latin1 NOT NULL,
`received_by` varchar(255) CHARACTER SET latin1 NOT NULL,
`message` varchar(255) CHARACTER SET latin1 NOT NULL,
`createdAt` varchar(255) CHARACTER SET latin1 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
-- --------------------------------------------------------
--
-- Table structure for table `users`
--
CREATE TABLE `users` (
`id` int(100) NOT NULL,
`name` varchar(255) CHARACTER SET latin1 NOT NULL,
`email` varchar(255) CHARACTER SET latin1 NOT NULL,
`password` varchar(255) CHARACTER SET latin1 NOT NULL,
`dp` varchar(255) CHARACTER SET latin1 NOT NULL
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4;
--
-- Indexes for dumped tables
--
--
-- Indexes for table `messages`
--
ALTER TABLE `messages`
ADD PRIMARY KEY (`id`);
--
-- Indexes for table `users`
--
ALTER TABLE `users`
ADD PRIMARY KEY (`id`);
--
-- AUTO_INCREMENT for dumped tables
--
--
-- AUTO_INCREMENT for table `messages`
--
ALTER TABLE `messages`
MODIFY `id` int(100) NOT NULL AUTO_INCREMENT;
--
-- AUTO_INCREMENT for table `users`
--
ALTER TABLE `users`
MODIFY `id` int(100) NOT NULL AUTO_INCREMENT;
COMMIT;
/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
该项目的文件结构为:
我们还必须为该项目设置数据库,这是数据库连接的代码:
<?php
// connection to DB
$conn = mysqli_connect("localhost","root","","wassup") or die(mysqli_error($conn));
?>
在注册页面,我们将注册新用户。如果该用户已存在于数据库中,我们将向其发送一条消息,告知其该帐户已存在。以下是注册页面的后端代码:
<?php
// session start
session_start();
// include DB connection
include('./db.php');
// declaring variables
$name = "";
$email = "";
$password = "";
$cpassword = "";
// get form data
if(isset($_POST['name'])) {
$name = $_POST['name'];
}
if(isset($_POST['email'])) {
$email = $_POST['email'];
}
if(isset($_POST['password'])) {
$password = $_POST['password'];
}
if(isset($_POST['password'])) {
$cpassword = $_POST['password'];
}
// setting up the target directory where you want to upload your images!
$target_dir = "../dp/";
$target_file = $target_dir . basename($_FILES["dp"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
$check = getimagesize($_FILES["dp"]["tmp_name"]);
if($check !== false) {
echo "File is an image - " . $check["mime"] . ".";
$uploadOk = 1;
} else {
echo "File is not an image.";
$uploadOk = 0;
}
}
// Check if file already exists
if (file_exists($target_file)) {
echo "Sorry, file already exists.";
$uploadOk = 0;
}
// Check file size
if ($_FILES["dp"]["size"] > 500000) {
echo "Sorry, your file is too large.";
$uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed.";
$uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
if (move_uploaded_file($_FILES["dp"]["tmp_name"], $target_file)) {
echo "The file ". basename( $_FILES["dp"]["name"]). " has been uploaded.";
} else {
echo "Sorry, there was an error uploading your file.";
}
}
if($name != "" && $email != "" && $password != "" && $cpassword != "") { // if the form fields are not empty!
$checkUser = "SELECT * FROM users WHERE email = '$email'";
$checkUserStatus = mysqli_query($conn,$checkUser) or die(mysqli_error($conn));
if(mysqli_num_rows($checkUserStatus) > 0) { // if user exists!
header('Location: ../index.php?message=You have already registered!');
} else {
if($password == $cpassword) { // if the password fields match!
$image = basename($_FILES["dp"]["name"]);
$insertUser = "INSERT INTO users(name,email,password,dp) VALUES('$name','$email','$password','$image')";
$insertUserStatus = mysqli_query($conn,$insertUser) or die(mysqli_error($conn));
if($insertUserStatus) { // if the user is successfully registered!
header('Location: ../index.php?message=You have registered successfully!');
} else { // if user is not registered successfully!
header('Location: ../register.php?message=Unable to register!');
}
} else { // if password fields dont match!
header('Location: ../register.php?message=Password fields do not match!');
}
}
} else { // if any of the fields are empty!
header('Location: ../register.php?message=Please fill the fields properly!');
}
?>
现在对于登录页面,代码看起来像这样:
<?php
// session start
session_start();
// include DB connection
include('./db.php');
// declaring variables
$email = "";
$password = "";
// getting form data!
if(isset($_POST['email'])) {
$email = mysqli_real_escape_string($conn,strip_tags($_POST['email']));
}
if(isset($_POST['password'])) {
$password = mysqli_real_escape_string($conn,strip_tags($_POST['password']));
}
if($email != "" && $password != "") { // if the fields are not empty!
$checkUser = "SELECT * FROM `users` WHERE BINARY `email` = '$email' AND BINARY `password` = '$password'";
$checkUserStatus = mysqli_query($conn,$checkUser) or die(mysqli_error($conn));
if(mysqli_num_rows($checkUserStatus) > 0) { // if user exists!
header('Location: ../chats.php?message=You have logged in!');
} else {
header('Location: ../index.php?message=Unable to login into your account!');
}
} else { // if the fields are empty!
header('Location: ../index.php?message=Please fill all the fields!');
}
$_SESSION['email'] = $email;
?>
一旦用户登录到他/她的帐户,用户将被重定向到仪表板页面,用户可以在该页面查看所有以前的对话,并且该页面还将有一个搜索栏,可以通过电子邮件或姓名搜索任何特定用户。仪表板页面的代码:
<?php
// session start
session_start();
// include DB connection
include('scripts/db.php');
if(!isset($_SESSION['email'])) { // if user not logged in!
header('Location: ./index.php');
} else {
$email = $_SESSION['email'];
}
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wassup</title>
<!-- external stylesheets -->
<link rel="stylesheet" href="assets/css/chats.css">
<!-- Bootstrap CDN -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Wassup</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="./chats.php">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="./logout.php">Logout</a>
</li>
<?php
$getUser = "SELECT * FROM users WHERE email = '$email'";
$getUserStatus = mysqli_query($conn,$getUser) or die(mysqli_error($conn));
$getUserRow = mysqli_fetch_assoc($getUserStatus);
?>
<li class = "nav-item">
<img src="./dp/<?=$getUserRow['dp']?>" alt="Profile image" width = "40" class = "dropdown"/>
</li>
</div>
</nav>
<!-- chats section -->
<div class="container mt-4">
<div class="card">
<div class="card-title text-center">
<form class="form-inline mt-4" style = "display : inline-block" method = "POST" action = "scripts/search-users.php">
<input class="form-control mr-sm-2" type="search" name = "search" placeholder="Search" aria-label="Search">
<button class="btn btn-outline-success my-2 my-sm-0" type="submit">Search</button>
</form>
</div>
<div class="card-body mb-4">
<?php
$lastMessage = "SELECT DISTINCT sent_by FROM messages WHERE received_by = '$email'";
$lastMessageStatus = mysqli_query($conn,$lastMessage) or die(mysqli_error($conn));
if(mysqli_num_rows($lastMessageStatus) > 0) {
while($lastMessageRow = mysqli_fetch_assoc($lastMessageStatus)) {
$sent_by = $lastMessageRow['sent_by'];
$getSender = "SELECT * FROM users WHERE email = '$sent_by'";
$getSenderStatus = mysqli_query($conn,$getSender) or die(mysqli_error($conn));
$getSenderRow = mysqli_fetch_assoc($getSenderStatus);
?>
<div class="card">
<div class="card-body">
<h6><strong><img src = "./dp/<?=$getSenderRow['dp']?>" alt = "dp" width = "40"/> <?=$lastMessageRow['sent_by'];?></strong><a href="./message.php?receiver=<?=$sent_by?>" class="btn btn-outline-primary" style = "float:right">Send message</a></h6>
</div>
</div><br/>
<?php
}
} else {
?>
<div class="card-body text-center">
<h6><strong>No conversations yet!</strong></h6>
</div>
<?php
}
?>
</div>
</div>
</div>
<!-- Bootstrap scripts -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>
现在,当用户点击位于接收方右侧的“发送消息”选项时,系统会将用户重定向到一个消息框,用户可以通过该消息框向相关用户发送消息。当用户点击“发送消息”选项时,接收方的邮箱 ID 将作为请求发送到 URL,并可用于获取接收方的详细信息,以便将数据与消息一起存储在数据库中。发送方和接收方之间的聊天框代码如下所示:
<?php
// session start
session_start();
// include DB connection
include('scripts/db.php');
error_reporting(0);
if(!isset($_SESSION['email'])) { // if user not logged in!
header('Location: ./index.php');
} else {
$email = $_SESSION['email'];
}
$receiver = $_GET['receiver'];
?>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Wassup</title>
<!-- external stylesheets -->
<link rel="stylesheet" href="assets/css/chats.css">
<link rel="stylesheet" href="assets/css/message.css">
<!-- Fontawesome CDN -->
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.14.0/css/all.min.css" integrity="sha512-1PKOgIY59xJ8Co8+NE6FZ+LOAZKjy+KY8iq0G4B3CyeY6wYHN3yt9PW0XpSriVlkMXe40PTKnXrLnZ9+fkDaog==" crossorigin="anonymous" />
<!-- Bootstrap CDN -->
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" integrity="sha384-JcKb8q3iqJ61gNV9KGb8thSsNjpSL0n8PARn9HuZOnIxN0hoP+VmmDGMN5t9UJ0Z" crossorigin="anonymous">
</head>
<body>
<!-- Navbar -->
<nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="#">Wassup</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarSupportedContent" aria-controls="navbarSupportedContent" aria-expanded="false" aria-label="Toggle navigation">
<span class="navbar-toggler-icon"></span>
</button>
<div class="collapse navbar-collapse" id="navbarSupportedContent">
<ul class="navbar-nav ml-auto">
<li class="nav-item active">
<a class="nav-link" href="./chats.php">Home <span class="sr-only">(current)</span></a>
</li>
<li class="nav-item">
<a class="nav-link" href="./logout.php">Logout</a>
</li>
<?php
$getUser = "SELECT * FROM users WHERE email = '$email'";
$getUserStatus = mysqli_query($conn,$getUser) or die(mysqli_error($conn));
$getUserRow = mysqli_fetch_assoc($getUserStatus);
?>
<li class = "nav-item">
<img src="./dp/<?=$getUserRow['dp']?>" alt="Profile image" width = "40" class = "dropdown"/>
</li>
</div>
</nav>
<div class="container">
<?php
$getReceiver = "SELECT * FROM users WHERE email = '$receiver'";
$getReceiverStatus = mysqli_query($conn,$getReceiver) or die(mysqli_error($conn));
$getReceiverRow = mysqli_fetch_assoc($getReceiverStatus);
$received_by = $getReceiverRow['email'];
?>
<div class="card mt-4">
<div class="card-header">
<h6><img src="./dp/<?=$getReceiverRow['dp']?>" alt="Profile image" width = "40"/><strong> <?=$receiver?></strong></h6>
</div>
<?php
$getMessage = "SELECT * FROM messages WHERE sent_by = '$receiver' AND received_by = '$email' OR sent_by = '$email' AND received_by = '$receiver' ORDER BY createdAt asc";
$getMessageStatus = mysqli_query($conn,$getMessage) or die(mysqli_error($conn));
if(mysqli_num_rows($getMessageStatus) > 0) {
while($getMessageRow = mysqli_fetch_assoc($getMessageStatus)) {
$message_id = $getMessageRow['id'];
?>
<div class="card-body">
<h6 style = "color: #007bff"><?=$getMessageRow['sent_by']?></h6>
<div class="message-box ml-4">
<p class="text-center"><?=$getMessageRow['message']?></p>
</div>
</div>
<?php
}
} else {
?>
<div class="card-body">
<p class = "text-muted">No messages yet! Say 'Hi'</p>
</div>
<?php
}
?>
<div class="card-footer text-center">
<form action="scripts/send.php" method = "POST" style = "display: inline-block">
<input type="hidden" name = "sent_by" value = "<?=$email?>"/>
<input type="hidden" name = "received_by" value = "<?=$receiver?>"/>
<div class="row">
<div class="col-md-10">
<div class="form-group">
<input type="text" name = "message" id = "message" class="form-control" placeholder = "Type your message here" required/>
</div>
</div>
<div class="col-md-2">
<button type = "submit" class="btn btn-primary">Send</button>
</div>
</div>
</form>
</div>
</div>
</div>
<!-- Bootstrap scripts -->
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js@1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>
</body>
</html>
现在,当发送者发送消息时,后端会执行一个进程,获取发送者和接收者的详细信息,并获取消息本身以及发送日期和时间,并将这些数据录入数据库。我们在这里使用日期和时间是为了按升序排列消息,否则消息看起来会很混乱。从聊天框发送消息的代码如下:
<?php
// session start
session_start();
// include db connection
include('./db.php');
// declaring variables
$sent_by = "";
$received_by = "";
$message = "";
$createdAt = date("Y-m-d h:i:sa");
// get data from form
if(isset($_POST['sent_by'])) {
$sent_by = $_POST['sent_by'];
}
if(isset($_POST['received_by'])) {
$received_by = $_POST['received_by'];
}
if(isset($_POST['message'])) {
$message = $_POST['message'];
}
if($message != "") { // if message box is not empty!
// send message
$sendMessage = "INSERT INTO messages(sent_by,received_by,message,createdAt) VALUES('$sent_by','$received_by','$message','$createdAt')";
$sendMessageStatus = mysqli_query($conn,$sendMessage) or die(mysqli_error($conn));
if($sendMessageStatus) {
header("Location: ../message.php?receiver=$received_by");
} else {
header("Location: ../message.php?receiver=$received_by");
}
}
?>
这是我创建的聊天 API 的演示视频:
哎呀!今天的代码太多了。这是这个项目的 GitHub 仓库:
希望你们喜欢!如果喜欢,请在评论区告诉我。
鏂囩珷鏉ユ簮锛�https://dev.to/spectrumcetb/chat-application-using-php-20ha