IT 공부/Laravel

[ Laravel ] Vue.js로 실시간 채팅(메세지 저장/불러오기)

JONGI-N CHOI 2021. 4. 1. 23:58

이제 input text를 이용해서 메세지를 입력했을 때, DB에 저장하는 기능을 만듦

 

메세지 DB에 저장하기!

Chat.vue

data() {
            return {
                chatWith: null,
                text: '',
                messages: []
            }
        },

data() 에 DB에 저장될 메세지인 text를 지정해준다. 

 

<input 
                    class="border-2 border-solid rounded border-gray-600 w-full p-2" 
                    type="text"
                    v-model="text"
                    @keyup.enter="submit"
                >

input 태그에 v-model="text"가 의미하는 것은, input의 text와 vue data()의 text를 연동시켜준다

input에서 값이 입력되면 실시간으로 vue data의 text값도 동일하게 바인딩이 된다. 

 

@keyup.enter="submit"

그리고 keyup.enter 엔터를 누르고 땟을 때, submit 메소드를 실행

 

submit() {
                if(this.text){
                    axios.post('/api/messages', {
                        text: this.text,
                        to :this.chatWith,
                        from: this.currentUser
                    }).then(res => {
                        //submit을 하고 난 뒤에, 자동적으로 messages에 추가됨으로 써 refresh가 된다. 
                        this.messages.push(res.data.message); 
                    });
                }
                //메세지 보낸 다음에 iunput창 초기화
                this.text= '';
            }

텍스트가 존재할 경우에만 저장하도록 한다. 

 

메세지(text)와 보내는사람(from) 받는사람 (to)을 request 보낸다. 

 

그리고 다 끝나면, text를 초기화한다. 

 

MessageController.php

public function store()
    {   
        // 아래 모든 값이 안왔을땐 에러값이 나오도록
        $validated = request()->validate([
            'text' => 'required',
            'to' => 'required',
            'from' => 'required'
        ]);        
        

        //MessageSent 이벤트를 발생시켜라
        $message = Message::create($validated);
        
        //message를 생성했을 때, messageSent 이벤트를 실행시켜라
        MessageSent::dispatch($message);

        return response()->json([
            'message' =>$message->load('from')
        ], 201);
    }

request 받아온 값들을 validate를 통해 검증을 하고

 

Messages 테이블에 저장을 한다. 

 

그리고 다시 response를 통해서 json 데이터형식으로  message 객체를 보내는데, load('from')을 이용해서 

 

user의 정보도 같이 넘긴다. 

 

Models/Message.php

public function from()
    {
        return $this->belongsTo(User::class, 'from');
    }

Message모델과 User모델의 관계를 정의해놨기 때문에, load('from')을 통해서 user의 정보까지 사용가능해진다. 

 

 

메세지 불러오기!

 

유저 목록에서 아이디를 클릭했을 때, 해당유저와 했던 메세지 내용을 불러오기 

getMessages() {
                axios.get('/api/messages', {
                    params:{
                        to:this.chatWith,
                        from:this.currentUser
                    }
                }).then(res => {
                    console.log(res);
                    this.messages = res.data.messages;
                })
            },

그러기 위해서는 클릭한 유저의 아이디, 현재 로그인중인 유저 아이디를 파라미터로 보낸다. 

 

 

MessageController.php

public function index()
    {
        $messages = Message::where(function($query) {
            $query->where('from', request('from'));
            $query->where('to', request('to'));
        })->orWhere(function($query) {
            $query->where('from', request('to'));
            $query->where('to', request('from'));
        })->get();
        
        //json형식으로 return을 한다. 
        return response()->json([
            //load를 통해서 from과 to의 이름을 가져올 수 있다.
            //Model Message를 보면 from, to가 user와 연결되어있기 때문에 User정보까지 같이 가져올 수 있다. 
            'messages' => $messages->load('from', 'to')
        ], 200);
    }

그리고 messages 테이블에서 message를 불러오는데 쿼리문 조건을 준다. 

 

내가 보낸 메세지 or 상대방이 보낸 메세지를 가져와라 ! 라는 쿼리문을 사용했다. 

 

 

updateChatWith(value){
                this.chatWith = value;
                this.getMessages();
            },

getMessages함수는 유저의 글을 클릭할 때 동작하는 함수인 updateChatWith 함수의 정의를 해놓고

 

data() {
            return {
                chatWith: null,
                text: '',
                messages: []
            }
        },

컴포넌트에서 messages값을 쓰기위해서 정의를 해준다. 

 

<ChatArea 
                :chat-id="chatWith"
                :messages="messages"
            />

가져온 messages는 CtatArea에서 보여지는 값이므로 ChatArea 컴포넌트로 보낸다.

 

 

ChatArea.vue

messages:{
                type: Array,
                required:true
            }

상위 컴포넌트에서 보낸 messages를 props로 정의해주고 사용한다. 

 

<ChatMessage 
            v-for="message in messages"
            :key="message.id"
            :message="message"
        />  

메세지를 보여주는 부분은 ChatMessage에 표시하기로 해서 다시한번 자식 컴포넌트로 message값을 보내는데

for문을 사용해서 보내준다. 

 

ChatMessage.vue

props:{
        message: {
            type: Object,
            required: true
        }
    }

상위 컴포넌트에서 보내온 message (객체)를 props에서 정의해주고 

 

<div>
            <strong>{{ message.from.name }} {{ message.created_at}}</strong>
        </div>
        <div>
            {{ message.text}}
        </div>

메세지 보낸 사람의 이름, 보낸 시간 그리고 내용을 보여주게되는데 

 

message테이블에는 text와 보낸사람 받는 사람의 id값 필드밖에 없지만, name을 가져올 수 있는 것은 

 

아까 models에서 user와의 관계를 정의했기 때문의 user의 필드 값을 가져와서 사용할 수 있는 것이다.