Building a Live Online Chat Room Based on Laravel + Swoole + Vue (P11): Get History Chat History After Entering The Chat Room
In the last tutorial, we showed you how to get unread messages after the user logs in. Today we enter the chat room to see what happened in the chat room.
The corresponding Vue component of the chat room page is resources/js/pages/Chat.vue
, we open this file and see the initial rendering logic of the page and the interaction with the back-end interface.
First look created
and mounted
hook function of these two pages initialization phase calls.
In the created
process, it will be from the current page URL query string in room obtain information (Tips: URL chat room is http://webchats.test/#/chat?roomId=1
):
async created() {
const roomId = queryString(window.location.href, 'roomId');
this.roomid = roomId;
if (!roomId) {
this.$router.push({path: '/'});
}
if (!this.userid) {
// Prevent unlogged
this.$router.push({path: '/login'});
}
const res = await url.getNotice();
this.noticeList = res.data.noticeList;
if (res.data.version !== res.data.version) {
this.noticeBar = false;
}
this.noticeVersion = res.data.version;
},
If the room information is empty, it will jump to the homepage, if the user is not logged in, it will jump to the login interface.
Then call url.getNotice()
to obtain information bulletin, corresponding to the back-end interface call is located resources/js/api/server.js
:
// Request announcement
getNotice: () => Axios.get('https://s3.qiufengh.com/config/notice-config.js'
This piece does not belong to the core logic, and the specific details are ignored.
Next, look at mounted
logic function:
async mounted() {
// WeChat rebound bug
ios();
this.container = document.querySelector('.chat-inner');
// socket internal,this pointer to question
const that = this;
await this.$store.commit('setRoomDetailInfos');
await this.$store.commit('setTotal', 0);
const obj = {
name: this.userid,
src: this.src,
roomid: this.roomid
};
socket.emit('room', obj);
socket.on('room', function (obj) {
that.$store.commit('setUsers', obj);
});
socket.on('roomout', function (obj) {
that.$store.commit('setUsers', obj);
});
loading.show();
setTimeout(async () => {
const data = {
total: +this.getTotal,
current: +this.current,
roomid: this.roomid
};
this.isloading = true;
await this.$store.dispatch('getAllMessHistory', data);
this.isloading = false;
loading.hide();
this.$nextTick(() => {
this.container.scrollTop = 10000;
});
}, 500);
this.container.addEventListener('scroll', debounce(async (e) => {
if (e.target.scrollTop >= 0 && e.target.scrollTop < 50) {
this.$store.commit('setCurrent', +this.getCurrent + 1);
const data = {
total: +this.getTotal,
current: +this.getCurrent,
roomid: this.roomid
};
this.isloading = true;
await this.$store.dispatch('getAllMessHistory', data);
this.isloading = false;
}
}, 50));
this.$refs.emoji.addEventListener('click', function(e) {
var target = e.target || e.srcElement;
if (!!target && target.tagName.toLowerCase() === 'span') {
that.chatValue = that.chatValue + target.innerHTML;
}
e.stopPropagation();
});
},
Here is first initialized room total number of messages and information, and then Websocket channel routing server roominitiated the request, the server has to inform the user enters the room, and by listening to the client roomand roomoutreturns the server to receive the event message into the room and left the room:
socket.emit('room', obj);
socket.on('room', function (obj) {
that.$store.commit('setUsers', obj);
});
socket.on('roomout', function (obj) {
that.$store.commit('setUsers', obj);
});
In the callback function, we set the online user information of the room through Vuex.
In order to achieve this Laravel based authentication backend API interface, we are united in obj
the new api_token
field:
Of course, we need to calculate the property computed
settings auth_token
to make the above code to take effect:
computed: {
... // Other configurations
...mapState({
userid: state => state.userInfo.userid,
src: state => state.userInfo.src,
auth_token: state => state.userInfo.token,
})
},
Continue to look at mounted
the logic followed by setTimeout
the definition of a timer, mainly to get the chat room chat history from the server room, too, we have added in the Request field api_token
fields:
const data = {
total: +this.getTotal,
current: +this.current,
roomid: this.roomid,
api_token: this.auth_token
};
this.isloading = true;
await this.$store.dispatch('getAllMessHistory', data);
getAllMessHistory
The final request interface is defined in the rear end of resources/js/api/server.js
the:
// Get all historical chats in the current room
RoomHistoryAll: data => Axios.get('/history/message', {
params: data
}),
There is the request parameters of total
the total number indicates that the message, current
the current page (or the current screen news, because a large amount of information possible, here it is necessary to do the pagination process), roomid
represents a room ID, api_token
interface for authentication.
We will need to implement this historical chat history interface in the backend later, this is an HTTP request.
The last is the definition of event listening for two components: one is the processing of the chat window scroll operation, and the other is the processing after the Emoji icon is clicked. Note that when scrolling chat window also involves calling the chat history interfaces, which in fact we are very familiar pull-down refresh the phone App, we need here objparameter also joined api_token
the field:
const data = {
total: +this.getTotal,
current: +this.getCurrent,
roomid: this.roomid,
api_token: this.auth_token
};
It can be seen that during the initialization phase of the chat room page, the two most important things are to establish a connection with the WebSocket server, tell it that the user has entered a certain room, and then obtain the historical chat history of this room and render it to the chat interface.
Next, we implement the corresponding Websocket interaction logic and HTTP routing interface on the back end.
Let’s first implement the interface for obtaining historical chat records from the backend.
Create the controller first MessageController
:
php artisan make:controller MessageController
The controller then write app/Http/Controllers/MessageController.php
codes are as follows:
<?php
namespace App\Http\Controllers;
use App\Message;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Log;
class MessageController extends Controller
{
/**
* Get historical chat history
* @param Request $request
* @return \Illuminate\Http\JsonResponse
*/
public function history(Request $request)
{
$roomId = intval($request->get('roomid'));
$current = intval($request->get('current'));
$total = intval($request->get('total'));
if ($roomId <= 0 || $current <= 0) {
Log::error('Invalid room and page information');
return response()->json([
'data' => [
'errno' => 1
]
]);
}
// Get the total number of messages
$messageTotal = Message::where('room_id', $roomId)->count();
$limit = 20; // 20 messages per page
$skip = ($current - 1) * 20; // From which message
// Paging query messages
$messageData = Message::where('room_id', $roomId)->skip($skip)->take($limit)->orderBy('created_at', 'desc')->get();
// Return response
return response()->json([
'data' => [
'errno' => 0,
'data' => $messageData,
'total' => $messageTotal,
'current' => $current
]
]);
}
}
This controller currently provides only history
method that returns JSON formatted chat history.
Finally, we in the API route file routes/api.php
definitions this route, the route after authentication is required to access, and because of this request will include api_token
field, so certification will by auth:api
done automatically Middleware:
Route::middleware('auth:api')->group(function () {
...
Route::get('/history/message', 'MessageController@history');
});
Next, you can test the request on the front end. Since there is no message yet, the data returned is empty:
In the next tutorial, we will write the code for users to enter and exit the room on the back end of the Websocket server, and update the online user information after entering and exiting, and push it to all online users in the chat room.
#laravel #swoole #vue