ساخت چت روم با PHP و jQuery فناوری Ajax
ساخت چت روم با PHP و jQuery – در این آموزش یاد خواهید گرفت که چگونه یک چت روم نیمه حرفه ای با استفاده از PHP و جی کوئری بسازید که از فناوری Ajax بهره می برد .
در این آموزش از :
1- PHP برای مدیریت درخواست ها در سمت سرور استفاده می کنیم
2- MYSQL برای ذخیره اطلاعات کاربر استفاده می کنیم
3- Javascript (jQuery) برای ارسال درخواست Ajax و تجربه یک برنامه SPA استفاده می کنیم .
2 بخش اصلی یعنی :
فایل app.js که برای ارسال درخواست و مدیریت سمت کلاینت است .
فایل process.php که برای مدیریت درخواست های ارسال شده کاربر می باشد مثل : ارسال پیام ، دریافت پیام
فایل app.js مدیریت سمت کلاینت با Javascript
ابتدا ارتفاع پنجره چت را متناسب با صفحه دستگاه تنظیم می کنید سپس با استفاده از متد Head درخواستی را می فرستیم که آیا پیام جدید برای کاربری فعلی وجود دارد یا خیر .
در صورتی که وجود نداشت status code 304 دریافت می کنیم ، اگر وجود داشت 200 دریافت می کنیم و مجدد این بار درخواست GET می فرستیم . این روند هر 2.5 ثانیه اجرا می شود تا اطلاعات را بروزرسانی کند .
همچنین برای ارسال پیام در صورتی که کاربر پیام را در keypad وارد کرده بود ، خالی نبود و دکمه ارسال را زد پیام را می فرستد ، البته در سمت سرور بررسی می شود که پیام ارسال شده برای کاربر دیگر (کاربر وجود دارد) .
$(document).ready(function() { let userMessageList = JSON.stringify({}); let users = undefined; let requestCounter = 0; let oldLength = -1; const chatroomDOM = $('.chatroom'); const messageViewDOM = $('#message-view'); const keypadWrapperDOM = $('.keypad-wrapper'); const sendMessageBtnDOM = keypadWrapperDOM.find("button"); const keypadDom = keypadWrapperDOM.find("#keypad"); const sendToDOM = keypadWrapperDOM.find("#send_to"); const WH = window.innerHeight; const chatroomHeight = WH - 187; const httpURL = location.origin; // set default propery chatroomDOM.css("height", chatroomHeight + "px"); chatroomDOM.find(".list-contact-wrapper,.message-view-wrapper").css("height", chatroomHeight + "px"); sendMessageBtnDOM.click(sendMessageBtnHandler); // helper functions function helperTimestampToReadableTime(time) { const d = new Date(); d.setTime(time * 1000); const year = d.getFullYear(), month = d.getMonth() + 1, day = d.getDate(), hour = d.getHours(), minute = d.getMinutes(), seconds = d.getSeconds(); const readableTime = year + "/" + month + "/" + day + " | " + hour + ":" + minute + ":" + seconds; return readableTime; } function helperMessageViewReset() { messageViewDOM.html(""); } function helperMessageViewDynamicContent() { if (sendToDOM.val() != "") { helperMessageViewReset(); listMessagesOnChatroom(sendToDOM.val()); } } // *********** chat ajax request *********** function addNewOwnMessageToMessageView(e) { const timestampSent = e.time_sent; const userRoom = sendToDOM.val(); if (timestampSent) { const messageObject = { unique_user: 1, from_user: 2, timestamp_sent: timestampSent, message: keypadDom.val() } userMessageList = JSON.parse(userMessageList); userMessageList[userRoom].push(messageObject); userMessageList = JSON.stringify(userMessageList); listMessagesOnChatroom(userRoom) keypadDom.val(""); } } function removeUnreadUserMessage(e) { if (e.user_room == "") return; const user = e.user_room; $(`[data-username=${user}]`).find("#contact-number-message").text("پیام جدیدی وجود ندارد"); } function updateSeenUser() { getDataChat({ state: "snd_msg_state", from_user: sendToDOM.val() }, removeUnreadUserMessage, false); } function listMessagesOnChatroom(userRoom) { userMessageList = JSON.parse(userMessageList); const userMessages = userMessageList[userRoom]; userMessageList = JSON.stringify(userMessageList); let counter = 0; helperMessageViewReset(); for (const message of userMessages) { const messageDetails = {}; counter++; messageDetails.who = message.unique_user != message.from_user ? "owner" : "other"; messageDetails.number = counter; messageDetails.time = helperTimestampToReadableTime(message.timestamp_sent); messageDetails.content = message.message; generateMessageBox(messageDetails); } const currentLength = userMessages.length; if(oldLength == -1 || oldLength != currentLength){ oldLength = currentLength; updateSeenUser(); } } function addUserUnreadMessagesToList(e) { if (e === undefined) return; const messageList = e; for (const message of messageList) { const uniqueUname = message["unique_user"]; userMessageList = JSON.parse(userMessageList); let oldMessage = userMessageList[uniqueUname]; oldMessage = oldMessage[oldMessage.length - 1]; const newMessage = message; if (oldMessage === undefined || oldMessage.timestamp_sent != newMessage.timestamp_sent) { userMessageList[uniqueUname].push(message); } userMessageList = JSON.stringify(userMessageList); } } function addUserUnreadMessagesElements(e) { if (e === undefined) return; const user = e['from_user']; const messageNumber = e['countMessage']; const msg = messageNumber == 0 ? "پیام جدیدی وجود ندارد" : messageNumber + " پیام جدید"; $(`[data-username=${user}]`).find("#contact-number-message").text(msg) } function getUserUnreadMessages() { for (const user of users) { const userName = user.username; requestCounter++; getDataChat({ state: "rcv_msg", from: userName, count: true }, addUserUnreadMessagesElements, false); if (requestCounter == 1) getDataChat({ state: "rcv_msg", from: userName, all_msg_unique: true }, addUserUnreadMessagesToList, false); else { getDataChat({ state: "rcv_msg", from: userName }, addUserUnreadMessagesToList, false); helperMessageViewDynamicContent(); } } } getDataChat({ state: "rcv_usr" }, userRcvHandler, false); function userRcvHandler(e) { users = e; let counter = 1; for (const user of users) { const userName = user.username; userMessageList = JSON.parse(userMessageList); userMessageList[userName] = []; userMessageList = JSON.stringify(userMessageList); $("#list-contact").append(`${user.fullname}پیام جدیدی وجود ندارد`); counter++; } getUserUnreadMessages(); setInterval(getUserUnreadMessages, 2500); } function getDataChat(query, cbk, loop = false) { const queryString = jQuery.param(query); $.ajax({ type: "head", url: httpURL + "/process.php", data: queryString, dataType: "json", complete: function(e) { if (200 <= e.status < 300) { $.get({ url: httpURL + "/process.php", data: queryString, dataType: "json", success: cbk, complete: function(e) { if (loop) setTimeout(getDataChat, 2000, query, cbk, loop); } }); } else { if (loop) setTimeout(getDataChat, 2000, query, cbk, loop); } } }); } // *********** dom event *********** $(document).on("click", ".contact-box", contactHandler); function contactHandler(e) { const thisElement = $(this); const sendToUser = thisElement.data("username"); $('.contact-box').removeClass("active"); thisElement.addClass("active"); if (sendToUser !== undefined) { oldLength = -1; keypadWrapperDOM.removeClass("ds-none"); sendToDOM.val(sendToUser); helperMessageViewDynamicContent(); } } function sendMessageBtnHandler() { const thisElement = $(this); const message = keypadDom.val(); const sendToUser = sendToDOM.val() if (message != "" && sendToUser != "") { getDataChat({ state: "snd_msg", to_user: sendToUser, msg: message }, addNewOwnMessageToMessageView, false); } } function generateMessageBox(messageDetails) { messageViewDOM.append(` `); } });
فایل process.php مدیریت سمت سرور با PHP
در ابتدا کوکی کاربر را اعتبارسنجی می کنیم که آیا امکان دسترسی دارد یا خیر .
به طور کلی سمت سرور را با استفاده از Query String کنترل می کنیم :
state برای دریافت نوع ارسال داده ها است اگر باشد :
rcv_msg پیام های کاربر را دریافت می کند
rcv_msg_unread یعنی کاربر قرار است پیام های خوانده نشده را دریافت کند
snd_msg یعنی کاربر پیامی را می خواهد ارسال کند
snd_msg_state زمانی که کاربر پیام را خواند آن را بروزرسانی کند به خوانده شده
rcv_usr برای لیست کردن تمامی کاربران در چت روم
header("Content-Type: application/json"); if (!empty($_COOKIE['username'])) { require_once "define.php"; require_once ABSPATH . "inc" . DSPR . "class-loader.php"; $db = new DB(); $uname = $_COOKIE['username']; $get_data = $_GET; $state = !empty($get_data["state"]) ? $get_data["state"] : ""; $from_user = !empty($get_data["from"]) ? $get_data["from"] : ""; if ($state == "rcv_msg" && !empty($from_user)) { $all_msg_unique = !empty($get_data["all_msg_unique"]) ? $get_data["all_msg_unique"] : ""; if ($all_msg_unique === "true") { $user_messages = $db->row_select(['table' => 'message_repo', 'content' => "((`to_usr`=? AND `from_usr`=?) OR (`to_usr`=? AND `from_usr`=?)) ORDER BY `id` ASC", "types" => "ssss", "values" => [$uname, $from_user, $from_user, $uname]]); } else { $user_messages = $db->row_select(['table' => 'message_repo', 'content' => "`to_usr`=? AND `from_usr`=? AND `seen`=? ORDER BY `id` ASC", "types" => "sss", "values" => [$uname, $from_user, 0]]); } if (!$user_messages) { header("HTTP/1.0 304 Not Modified", true); } if (!empty($get_data['count']) && $get_data['count'] === "true") { $sanitized_messages = ["countMessage" => count($user_messages), "from_user" => $from_user]; } else { $sanitized_messages = []; foreach ($user_messages as $user_message) { $sanitized_messages[] = [ 'unique_user' => $from_user, 'from_user' => $user_message['from_usr'], 'from_user_fullname' => $user_message['from_usr_name'], 'to_user' => $user_message['to_usr'], 'message' => $user_message['message'], 'timestamp_sent' => $user_message['timestamp_sent'], ]; } } echo json_encode($sanitized_messages); } elseif ($state == "rcv_msg_unread") { $user_messages = $db->row_select(['table' => 'message_repo', 'content' => "`to_usr`=? AND `seen`=? ORDER BY `id` ASC", "types" => "ss", "values" => [$uname, 0]]); if (!$user_messages) { header("HTTP/1.0 304 Not Modified", true); } if (!empty($get_data['count']) && $get_data['count'] === "true") { $sanitized_messages = ["countMessage" => count($user_messages), "from_user" => $from_user]; } else { $sanitized_messages = []; foreach ($user_messages as $user_message) { $sanitized_messages[] = [ 'unique_user' => $user_message['from_usr'], 'from_user' => $user_message['from_usr'], 'from_user_fullname' => $user_message['from_usr_name'], 'to_user' => $user_message['to_usr'], 'message' => $user_message['message'], 'timestamp_sent' => $user_message['timestamp_sent'], ]; } } echo json_encode($sanitized_messages); } else if ($state == "snd_msg" && $_SERVER['REQUEST_METHOD'] != "HEAD") { if (isset($get_data['to_user']) && $get_data['to_user'] !== $uname && isset($get_data['msg'])) { $user_exist = $db->row_exist(['table' => 'users', 'content' => "username=?", "types" => "s", "values" => [$get_data['to_user']]]); if ($user_exist) { $time = time(); Helper::verify_user_by_session(); $user_fullname = $GLOBALS['current_user']['fullname']; $res = $db->row_insert([ 'table' => 'message_repo', 'content' => "(`from_usr`, `from_usr_name` , `to_usr` , `message` , `timestamp_sent` , `timestamp_seen`) VALUES (? , ? , ? , ? , ? , ?)", "types" => "ssssss", "values" => [$uname, $user_fullname, $get_data['to_user'], $get_data['msg'], $time, '0'], ]); echo "{\"time_sent\":\"{$time}\",\"msg\" : \"success\",\"status\" : \"1\"}"; header("HTTP/1.0 201 Created", true); } else { header("HTTP/1.0 304 Not Modified", true); } } else { echo '{"msg" : "require complete data" , "status" : "0"}'; } } else if ($state === "snd_msg_state") { if (isset($get_data['from_user']) && $get_data['from_user'] !== $uname) { $time = time(); $res = $db->row_update(["table" => "message_repo", "content" => "`seen`=? , `timestamp_seen`=? WHERE `to_usr`=? AND `from_usr`=?", "types" => "ssss", "values" => [1, $time, $uname, $get_data['from_user']]]); if ($res) { echo "{\"time_sent\":\"{$time}\",\"user_room\" : \"{$get_data['from_user']}\",\"msg\" : \"success\",\"status\" : \"1\"}"; } } else { header("HTTP/1.0 304 Not Modified", true); } } else if ($state === "rcv_usr") { $users = $db->row_select(['table' => 'users', 'content' => "`username` != ? AND `verified`=?", "types" => "ss", "values" => [$uname, 1]]); if (!$users) { header("HTTP/1.0 304 Not Modified", true); } $sanitized_users = []; foreach ($users as $user) { $sanitized_messages[] = [ 'username' => $user['username'], 'fullname' => $user['fullname'], ]; } echo json_encode($sanitized_messages); } }
دموی پروژه ساخت چت روم با PHP و jQuery
قبل از اجرای برنامه وارد پوشه chatroom DATABASE to import شده دیتابیس را import کنید
لیست نظرات
سلام شما طراحی هم میکنید؟لطفا با من تماس بگیرید m2773@gmail.com
درود ، از طریق ارتباط با ما اقدام کنید
معنی این ارور چیست ؟ Fatal error: Uncaught Error: mysqli_stmt object is not fully initialized in D:\xampp\htdocs\chatroom\inc\class-DB.php:24 Stack trace: #0 D:\xampp\htdocs\chatroom\inc\class-DB.php(24): mysqli_stmt->close() #1 [internal function]: DB->__destruct() #2 {main} thrown in D:\xampp\htdocs\chatroom\inc\class-DB.php on line 24
فکر می کنم موقعیت stmt رو تغییر داده باشید یا close اون stmt رو تغییر دادین
من PDO کار میکنم . چطور درستش کنم ؟
می تونید از این داکیومنت استفاده کنید .
ببخشید شما دوره هاتون هم همین قدر حرفه ایه ؟
درود فعلا در حال ضبظ هستیم و منتشر نشده توی دوره مون سعی می کنیم بالاترین کیفیت رو به هنرجو انتقال بدیم .
سلام خوبید میتونید بگید چجوری دیتابیس رو ایمپورت کنم من دیتابیس رو ساختم ولی نمیتونم ایمپورتش کنم ترو خدا کمکم کنید
درود شما نیازی نیست که دیتابیسی بسازید فقط کافیه که دیتابیس chatroom.sql رو import کنید .
سلام ببخشید در هنگام راه اندازی سورس ها در برنامه ومپ سرور به کد خطای زیر مواجه شدم میشه راه نمایی بفرمایید
Parse error: syntax error, unexpected ',', expecting ')' in C:\wamp\www\chatroom-php-jquery\inc\class-DB.php on line 12 این کد بوده
درود خطای سینتکسی احتمالا پرانتز اضافه یا کاما یا سیمیکالن نذاشتید
سلام اگه میشه آموزش ویدیویی رو هم بزارید.
درود ، حتما
سلام اگر می خواهیم آدرس localhost/chat باز کنیم به مشکل می خوریم چه کنیم
فایل ها را وارد پوشه ای به نام chat کنید .