지난번에 만들어놓은 친구추가기능에서 조금 변경을 했다.
원래는 작성자의 아이디를 클릭하면 아코디언 패널이 나타나서 친구추가를 누르면 바로 친구추가가 되는 기능이었다.
이번에 변경한 점은 친구추가를 누르게되면 상대방에게 친구요청이 가게되고, 상대방이 친구요청 수락을 누르게되면 친구가되는 형식이다.
Migration 생성
Schema::create('request_friends', function (Blueprint $table) {
$table->id();
$table->foreignId('from');
$table->foreignId('to');
$table->foreign('from')->references('id')->on('users')->onDelete('cascade');
$table->foreign('to')->references('id')->on('users')->onDelete('cascade');
});
위의 기능을 실현하기 위해서는 우선, 친구요청에 관한 테이블이 필요하다.
필드로는 친구요청을 보낸(from)과 받는 사람(to)와 id값이 존재하고
from과 to는 user의 id키를 참조하는 외래키로 설정했다. users가 삭제되었을 경우에는 cascde옵션을 통해서 같이 삭제되도록 설정
친구요청 보내기
위의 사진처럼 친구추가를 누르면 친구요청이 보내지는데
public function request($id)
{
//내가 요청 보낸 목록이 있는지 없는지
$check_request_from = Request_friend::where('from', auth()->id())->where('to', $id)->first();
//상대방에서 나한테 보낸 요청은 없는지
$check_request_to = Request_friend::where('to', auth()->id())->where('from', $id)->first();
//이미 친추되어있지는 않은지
$check_friend = List_of_friend::where('user_id', auth()->id())->where('friend_id', $id)->first();
if($check_friend == null && $check_request_from == null && $check_request_to == null && auth()->id() != $id){
$data['from'] = auth()->id();
$data['to'] = $id;
Request_friend::create($data);
emotify('success', '친추성공!');
} else {
emotify('error', '이미 친구야 or 자기 자신은 친추 못해요!');
}
return redirect()->back();
}
보내지게되면, friendController의 request함수가 요청된다.
글을 쓴 유저의 id번호가 request로 날라가게 되어서 그 값을 통해서 검증을 한다.
검증은, 친구요청 테이블에 이미 요청이 있는지 없는지 친구창 목록에 존재하는지 없는지를 확인하다.
없을 경우에는 친구요청 테이블에 from값과 to값이 저장되어서 요청이 보내지게된다.
App.php
Route::get('/mypage', [MypageController::class, 'index']);
친구요청목록은 mypage를 만들어서 그곳에서 볼 수 있도록 했다.
MypageController.php
public function index()
{
$request_list = Request_friend::where('to', auth()->id())->get();
return view('mypage.index', [
'request_list' => $request_list
]);
}
request_friend 모델로부터, 요청 받은 사람(to)필드의 값이 현재 접속중인 사람의 id 값과 같은 데이터를 가져오도록
하고, mypage 디렉토리에있는 index.blade.php로 데이터와 함께 보내준다.
mypage/index.blade.php
@extends('layouts.app')
@section('content')
<div class="flex h-full">
<div class="w-1/5 border-r-2 border-solid border-gray-600">
친구요청
</div>
<div class="w-4/5 flex flex-col">
@foreach ($request_list as $request)
<div class="border p-3">
{{ $request->user->name }}님으로 부터 친구추가 요청이 있습니다.
<div class="float-right">
{{-- 버튼을 두개만들어서, 버튼에 따라서 action을 다르게 주기위함 --}}
<form method="POST" name="form">
@csrf
<input type="hidden" value="{{ $request->from }}" name="request_from">
<input type="hidden" value="{{ $request->id }}" name="request_id">
<input class="mb-10 bg-blue-700 hover:bg-gray-900 text-white font-bold py-2 px-4 border border-gray-900 rounded"
type="submit" value="수락" onclick="javascript: form.action='/friend/accept';"/>
<input class="mb-10 bg-red-700 hover:bg-gray-900 text-white font-bold py-2 px-4 border border-gray-900 rounded"
type="submit" value="거절" onclick="javascript: form.action='/friend/refusal';"/>
</form>
</div>
</div>
@endforeach
</div>
</div>
@endsection
foreach문을 사용해서 list 목록들을 각각 div형태로 보여지도록 했다.
실제화면을 보면
가 실제 mypage에서 보이는 view화면이다.
<form method="POST" name="form">
@csrf
<input type="hidden" value="{{ $request->from }}" name="request_from">
<input type="hidden" value="{{ $request->id }}" name="request_id">
<input class="mb-10 bg-blue-700 hover:bg-gray-900 text-white font-bold py-2 px-4 border border-gray-900 rounded"
type="submit" value="수락" onclick="javascript: form.action='/friend/accept';"/>
<input class="mb-10 bg-red-700 hover:bg-gray-900 text-white font-bold py-2 px-4 border border-gray-900 rounded"
type="submit" value="거절" onclick="javascript: form.action='/friend/refusal';"/>
</form>
view파일에서 form태그를 보면, 각 버튼마다 다른 주소로 보내주기 위해서 onclick 이벤트를 추가해줬다.
그리고 hidden을 통해서 친구요청의 id값과 from값을 post로 보내준다.
App.php
Route::POST('/friend/accept', [FriendController::class, 'accept']);
Route::POST('/friend/refusal', [FriendController::class, 'refusal']);
수락을 눌렀을 경우에는 FriendController의 accept 함수를 사용하도록
거절을 눌렀을 경우에는 FriendController의 refusal 함수를 사용하도록 설정
FriendController.php
public function accept(Request $request)
{
request()->validate([
'request_from' => 'required',
'request_id' => 'required'
]);
//접속유저의 친구목록에 요청온 상대방이 친추되어있는지 확인
$check_friend_current = List_of_friend::where('user_id', auth()->id())->where('friend_id', $request->request_from)->first();
//요청보낸 사람의 친구목록에 요청받은 사람이 있는지 확인
$check_friend_with = List_of_friend::where('user_id', $request->request_from)->where('friend_id', auth()->id())->first();
if($check_friend_current == null && $check_friend_with == null){
$values_current['friend_id'] = $request->request_from;
$values_current['user_id'] = auth()->id();
$values_with['friend_id'] = auth()->id();
$values_with['user_id'] = $request->request_from;
List_of_friend::create($values_current);
List_of_friend::create($values_with);
//친구등록이 완료되었으니, 친구요청에 있는 데이터는 삭제시킨다.
$request_friend = Request_friend::where('id', $request->request_id)->delete();
emotify('success', '친추성공!');
} else {
emotify('error', '이미 친구야 or 자기 자신은 친추 못해요!');
}
return redirect()->back();
}
수락을 눌렀을 때, accept 함수에서는 우선 request 값들을 validation을 한다.
그다음에는 친구목록에 이미 저장되어있는지 아닌지 검증을 위한 작업을 한다.
그리고 검증이 끝나면, 친구 테이블에 저장을 한다. from한 유저와 to받은 유저 두명을 각각 db에 저장시킨다. (서로서로 친구추가 되도록)
그리고, DB에 저장이 끝나고 나면 친구요청 테이블에 있는 값은 이제 필요없어졌으니 삭제를 한다.
public function refusal(Request $request)
{
Request_friend::where('from', $request->request_from)->delete();
return redirect()->back();
}
거절을 눌렀을 때, 바로 request_from 받아온 값을 통해서 친구요청 테이블에 있는 요청을 삭제시키고 리프레쉬
여기까지 구현을 끝냈지만, 한가지 수정해야할 점이 있다.
DB에서 데이터를 삭제하는 거에는 소프트삭제와 하드삭제가 있다고한다.
위에 경우처럼, 그냥 DB테이블에서 그 데이터를 소멸시켜버리는 것이 하드삭제고
소프트삭제는 테이블에 status를 나타낼 수 있는 속성을 하나 추가시켜서 status를 통해서 삭제, 존재 여부를 파악시킨다.
예를 들어 is_delete 속성을 추가해서 삭제외었으면 1 존재하면 0 값을 넣어서 운영하는 것이다.
그렇게 해야지만 데이터 보관 측면에서 훨씬 좋다고한다.
'IT 공부 > Laravel' 카테고리의 다른 글
[ Laravel ] 프로젝트 Jetstream 사용하기 (0) | 2021.08.08 |
---|---|
[ Laravel ] 유저 블라인드 기능 (0) | 2021.05.04 |
[ Laravel ] Vue.js로 실시간 채팅(메세지 저장/불러오기) (0) | 2021.04.01 |
[ Laravel ] Vue.js를 이용한 실시간 채팅 (유저목록) (0) | 2021.03.31 |
[ Laravel ] Vue.js를 이용한 실시간 채팅 (필요한 개념) (0) | 2021.03.31 |