본문 바로가기

PHP/Laravel

[Laravel 7.x] '0'부터 시작하는 Laravel 계층형 게시판

완성된 모습

PHP의 프레임워크인 Laravel Framework를 사용하여 첫 결과물로 계층형 게시판을 만들어 보았습니다.
버전은  7.21.0  이고, https://laravel.kr/docs/7.x 라라벨 코리아 한글 메뉴얼을 참고하였습니다.
필자가 만든 코드를 다시 짚어가면서 정확히 이해하기 위해 작성하였는데요. 아직 개발 왕초보이기 때문에 내용이 부실할 수도 있고 틀린 부분이 있을 수도 있습니다. 피드백해주시면 매우 감사하겠습니다.
첫 포스팅 시작! 편의상 반말로 작성한 점 양해 부탁드립니다. (_ _ ) 감사합니다.



1. 게시판 컨트롤러, 모델, 마이그레이션 생성
2. 마이그레이션 정의
3. 경로지정(라우팅)
4. 컨트롤러 메소드 정의
       - index, create, store 메소드
5. 뷰 생성하기

       -  layout, index, create 뷰


1. 컨트롤러, 모델, 마이그레이션 생성

생성하기 전에 .env 파일의 DB설정을 본인의 정보로 DB로 수정해주자. 수정을 완료했다면.
콘솔 창에 php artisan make:model Task -c -m 를 입력해줍니다. 모델 생성 명령어인데, Task는 필자가 정의한 모델 이름.

-c는 컨트롤러를 생성해주는 옵션, -m는 마이그레이션 생성 옵션이다.
컨트롤러는 MVC 패턴의 구성 요소로 사용자의 요청을 처리하고 응답을 되돌려주는 전체 과정을 관장한다.
이 명령어를 실행하면 Task 모델의 컨트롤러와 마이그레이션이 생성되는데 이번 시간에 정의할 것은.
database/migaration 폴더 안에 Task모델에 대한 마이그레이션 파일.
app/Task.php 모델 파일.
app/Http/Controllers 폴더 안에는 TaskController.php 컨트롤러 파일 세 가지이다.

 

 

2. 마이그레이션 정의

database/migration 폴더 안의 생성날짜_create_tasks_table.php 파일입니다.

use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;

class CreateTasksTable extends Migration
{
    public function up()
    {
        Schema::create('Task', function (Blueprint $table) {
            $table->increments('id');
            $table->text('memo');
            $table->text('creator_name');
            $table->integer('grp')->nullable();
            $table->integer('sort')->nullable();
            $table->integer('depth')->nullable();
            $table->timestamps();
        });
    }

    public function down()
    {
        Schema::dropIfExists('Task');
    }
}​

database/migration/(생성날짜)_create_tasks_table.php

마이그레이션 클래스는up 과 down, 두 개의 메소드를 가지고 있습니다. up메소드는 데이터베이스에 테이블, 컬럼, 인덱스를 추가하는데 사용되고, 이와 반대로 down메소드는 up메소드의 동작을 취소합니다. 
이 두 메소드 안에서 모두 라라벨 스키마 빌더를 사용하여 테이블을 다양한 방법을 통해서 생성하고 변경할 수 있다.  -라라벨 메뉴얼-

필요한 컬럼들을 정의해 줍니다. memo와 craetor_name 은 문자열이라 text 속성을 나머지 컬럼은 integer 속성을 주었고. $table->속성('컬럼명'); 의 형식으로 정의해줍니다. nullable()은 null을 허용해준다.
각 컬럼에 저장될 데이터를 설명하자면

id : 글 번호, 기본키입니다. increment 속성이므로 데이터가 생성되면 1씩 증가합니다.
memo : 사용자가 작성한 글.
creator_name : 사용자가 입력한 사용자의 이름입니다.
grp : 같은 주제를 갖는 게시물의 고유번호. 부모 글과 부모 글로부터 파생된 모든 자식 글은 같은 번호를 갖습니다.
sort : 같은 그룹 내 댓글의 순서.
depth : 같은 그룹 내 댓글의 계층.

down()메소드에 해당하는 리버스 마이그레이션은 생략하여도 된다.

정의를 완료하였다면 콘솔창에 php artisan migrate 를 입력해준다. DB안에 테이블이 생성된다. 
마이그레이트 된 파일을 수정한 뒤에 :fresh 를 붙이면 모든 마이그레이션 파일의 데이터를 지우고 새로고침.
:rollback 을 붙이면 마지막 데이터베이스 상태로 되돌리기가 된다.

생성된 Tasks 테이블 ( HeidiSQL 프로그램 )

 

 

 

3.경로 지정 (라우팅)

routes/web.php 파일에 라우팅을 해줍니다.

use Illuminate\Support\Facades\Route;

Route::get('/tasks/', 'TaskController@index'); 

Route::get('/tasks/create', 'TaskController@create'); 

Route::post('/tasks/', 'TaskController@store'); 

routes/web.php

라라벨코리아 https://laravel.kr/docs/7.x/controllers


라라벨 메뉴얼 사이트를 참고하여
Route::메소드('URL경로', '컨트롤러의 클래스명@메소드명'); 을 지정해준다.
예를 들어 사진대로 경로를 지정한다면 create 액션의 경로는 localhost8000:photos/create 가 된다.
Route::get('/tasks/', 'Pagecontroller@index');
경로가 맞다면 TaskController 클래스의 index 메소드가 실행된다.

index는 메인페이지, create는 말 그대로 글, 댓글을 작성하기 위해 필요하고, store는 create에서 받은 데이터를
처리하여 데이터베이스에 저장하기 위해 필요하다.

 

 

 

4. 컨트롤러 메소드 정의

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Task; //테이블명 지정

class TaskController extends Controller
{
    public function index() //메인페이지 메소드
    {
        return view('tasks.index');
    }

    public function create() //생성페이지 메소드
    {
        return view('tasks.create');
    }

    public function store() //저장 메소드
    {
        return redirect("/tasks");
    }
}

App/Http/Controllers/TaskController.php

먼저 필요한 각 메소드들을 정의해 둔다. use App\Task를 하면 모델인 Task 클래스를 상속받는다.

namespace App;

use Illuminate\Database\Eloquent\Model;

class Task extends Model
{
    protected $table = 'tasks';
}

App/Task.php

모델을 담당하는 Task 모델은 컨트롤러에 의해 호출되어 DB에 데이터를 저장하거나, DB에서 데이터를 가져와서 뷰가 사용할 수 있는 형태로 컨트롤러에 반환한다. 클래스 안에 protected $table = '테이블명';
선언을 해주면 생성한 Task 모델에서 어떤 테이블을 사용해야 할지 Model 에게 알려준다.

 

- index 메소드                                          

    public function index(Request $request) //Request 클래스의 변수 매개변수로 사용
    {
      
        $pageNum     = $request->input('page');
        // view에서 넘어온 현재페이지의 파라미터 값.
        $pageNum     = (isset($pageNum)?$pageNum:1);
        // 페이지 번호가 없으면 1, 있다면 그대로 사용
        $startNum    = ($pageNum-1)*10;
        // 페이지 내 첫 게시글 번호
        $writeList   = 10;
        // 한 페이지당 표시될 글 갯수
        $pageNumList = 10;
        // 전체 페이지 중 표시될 페이지 갯수
        $pageGroup   = ceil($pageNum/$pageNumList);
        // 페이지 그룹 번호
        $startPage   = (($pageGroup-1)*$pageNumList)+1;
        // 페이지 그룹 내 첫 페이지 번호
        $endPage     = $startPage + $pageNumList-1;
        // 페이지 그룹 내 마지막 페이지 번호
        $totalCount  = Task::count();
        // 전체 게시글 갯수
        $totalPage   = ceil($totalCount/$writeList);
        // 전체 페이지 갯수
        if($endPage >= $totalPage) {
        $endPage = $totalPage;
        } // 페이지 그룹이 마지막일 때 마지막 페이지 번호

        if($request->input('del')==1) {
            Task::where('id', $request->input('delId'))
            ->update(['memo'=>'삭제된글입니다.']);
        } // 삭제요청

        $comments = Task::orderby('grp', 'DESC')
        ->orderby('sort')->skip($startNum)->take($writeList)->get();
        // 테이블에서 가져온 DB 뷰에서 사용 할 수 있는 변수에 저장.

        return view('tasks.index', [
            'totalCount'=>$totalCount,
            'comments'=>$comments,
            'pageNum'=>$pageNum,
            'startPage'=>$startPage,
            'endPage'=>$endPage,
            'totalPage'=>$totalPage
            ]);
            // 요청된 정보 처리 후 결과 되돌려줌
    }

app/Http/Contorllers/TaskController/.php

컨트롤러의 인덱스 메소드 부분이다. 한줄한줄 천천히 알아보자.
먼저 컨트롤러로 넘어오는 Request값을 받기 위해 메소드의 매개변수로 Request 클래스의 변수를 사용해주자. 맨위에 있는
use Illuminate\Http\Request 클래스의 변수다. 이게 있으면 GET값이나 POST값을 받을 수 있다.

주석에 설명이 있지만 추가로 설명이 필요한 변수를 설명하겠음.
                             
$pageGroup   = ceil($pageNum/$pageNumList);
ceil 함수는 올림 함수다. 소수점 아래 값이 있으면 무조건 올린다. 현재 페이지그룹이 1~ 10페이지인지 11~ 20페이지인지를 알려줌.

if($endPage >= $totalPage) { $endPage = $totalPage; }
마지막 페이지 번호가 전체 페이지 개수랑 같아지면 더 이상 표시 안 함. (사진참고)

    if($request->input('del')==1) {
            Task::where('id', $request->input('delId'))->update(['memo'=>'삭제된글입니다.']);
        }


뷰에서 [ 삭제하기 ] 버튼을 클릭하면 del 파라미터에 1의 값이 들어오게 되는데 1이 들어온다면, 게시물의 ID가 있는 컬럼의 memo컬럼을 "삭제된글입니다." 로 수정한다.

라라벨은 DB를 다룰 때 쿼리빌더를 사용한다. where('컬럼이름','데이터') 는 SQL문에서 where '컬럼이름' = '데이터' 와 같음. 쿼리빌더문에 대한 모든 정보들은 라라벨 홈페이지에 있다.  쿼리빌더(Link) .    Update문도 SQL문을 안다면 쉽게 이해가 갈 것이다.  where 명령어를 실행한 뒤 그 위치의 'memo' 컬럼의 내용을 "삭제된글입니다." 로 바꾼다.

$comments = Task::orderby('grp', 'DESC')->orderby('sort')->skip($startNum)->take($writeList)->get();


comments 를 선언하고 변수 안에 쿼리빌더의 결과를 넣는다. 테이블은 Task 테이블이고 grp와 sort를 정렬한다.

skip은 offset과 같고, take는 limit와 같은 의미이다. 마지막으로 get() 메소드를 사용하여 결과를 가져올 수 있다.
정렬 알고리즘은 따로 포스팅을 할 예정이다.

       return view('tasks.index', [    //경로를 작성할 때 \대신 . 을 사용
            'totalCount'=>$totalCount,
            'comments'=>$comments,
            'pageNum'=>$pageNum,
            'startPage'=>$startPage,
            'endPage'=>$endPage,
            'totalPage'=>$totalPage
            ]);


곧 생성할 뷰의 파일명인 resources/views/tasks/index.blade.php 에 변수들을 넘겨준다. 저 변수들은 이제 뷰 에서도 사용이 가능하다.

 

- create 메소드                                        

    public function create()
    {
        return view('tasks.create');
    }

craete 메소드는 뷰만 보여주면된다... 값을 저장하는 것은 store 에서 처리하기 때문이다.

 

- store 메소드                                         

    public function store(request $request)
    {
        $pageNum = $request->input('page'); //댓글을 작성한 페이지로 돌아가기 위해 필요
        $mode =  $request->input('mode'); // 댓글작성인지 글작성인지 구분하기 위한 변수
        $memo = $request->input('memo');
        $creatorName = $request->input('creator_name');
        $creatorName = (isset($creatorName)?$creatorName:"익명");
        $id = $request->input('id');
        $grp = $request->input('grp');
        $sort = $request->input('sort');
        $depth =  $request->input('depth');

        if($mode==0) {
            Task::where([
                ['grp',$grp],
                ['sort','>',$sort],
            ])->increment('sort', 1);
            
            $commentPage = new Task;
            $commentPage->memo = $memo;
            $commentPage->creator_name  = $creatorName;
            $commentPage->grp = $grp; 
            $commentPage->sort = $sort+1; 
            $commentPage->depth = $depth+1;
            $commentPage->save();
        }
        else {
            $commentPage = new Task;
            $commentPage->memo = $memo;
            $commentPage->creator_name  = $creatorName;
            $commentPage->sort = 0;
            $commentPage->depth = 0;
            $commentPage->save();
            $commentPage->grp = $commentPage->id;
            $commentPage->save();
        }
        return redirect("/tasks?page=$pageNum");
    }


store 메소드는 라우팅을 작성할 때 POST방식으로 작성하였기 store에 들어올 파라미터들은 POST방식으로 들어온다.
store 메소드에서는 데이터베이스에 값을 저장하는 일만 한다.

 if($mode==0) {
            Task::where([
                ['grp',$grp],
                ['sort','>',$sort],
            ])->increment('sort', 1);
            
            $commentPage = new Task;
            $commentPage->memo = $memo;
            $commentPage->creator_name  = $creatorName;
            $commentPage->grp = $grp; 
            $commentPage->sort = $sort+1; 
            $commentPage->depth = $depth+1;
            $commentPage->save();
        }


만약 $mode변수에 파라미터 값이 '0' 이 들어오는 건 게시물에 댓글을 작성하는 경우이다. 쿼리빌더를 사용해 댓글의 grp값이 있는 컬럼을 찾고 댓글의 sort 값보다 큰 sort 값들에게 1을 더해준다. 
값을 저장할 때는 라라벨의 ORM인 Eloquent를 사용한다. 새 모델의 인스턴스를 생성하고 모델의 속성을 설정한 뒤 저장한다. 엘로퀸트(Link)

else {
            $commentPage = new Task;
            $commentPage->memo = $memo;
            $commentPage->creator_name  = $creatorName;
            $commentPage->sort = 0;
            $commentPage->depth = 0;
            $commentPage->save();
            $commentPage->grp = $commentPage->id;
            $commentPage->save();
        }
        return redirect("/tasks?page=$pageNum");


이 문단은 댓글이 아닌 게시물을 작성하는 경우 실행되는 엘로퀀트다. 그리고 return redirect 를 사용하여 create 페이지에서 값을 저장하고 난 뒤 create 페이지가 아닌 메인페이지에 페이지 파라미터 값을 넘겨주어서 글쓰기 or 댓글쓰기 버튼을 눌렀던 페이지로 돌아간다.

 

 

5. 뷰 생성하기

뷰는 애플리케이션에서 제공하는 HTML 로 구성되어 있으며, 컨트롤러 / 애플리케이션 로직을 프리젠테이션 로직에서 분리하는 역할을 수행합니다. 뷰 파일들은 resources/views 디렉토리에 위치합니다.
-라라벨 메뉴얼-

페이지를 만들기 위해서 라라벨에서 제공하는 blade 라는 템플릿 엔진을 사용함.
블레이드 뷰 파일은 .blade.php 형식의 파일 확장자를 사용하고 주로 resources/views 에 저장된다.
먼저 resources/views 안에 tasks 폴더와 layouts 폴더를 만들어 줍니다.
레이아웃을 정의하기위해 layouts 폴더안에 task_layout.blade.php 를 만들어 준다.
레이아웃을 정의하는 이유는 다양한 페이지가 동일한 레이아웃을 유지해야 될 때 이 레이아웃을
하나의 블레이드 뷰로 정의하면 편리하기 때문이다. 또한 일일이 HTML 마크업을 적을 필요도 없어진다.

 

- 페이지 레이아웃                                    

<!DOCTYPE html>
<html lang="ko">
	<head>
    		<meta charset="UTF-8">
    		<meta name="viewport" content="width=device-width, initial-scale=1.0">
    		@yield('metatag') <!-- 헤드 부분. -->
    		<title>@yield('title')</title> <!-- 타이틀 제목 -->
    		@yield('style') <!-- 스타일 컨텐츠가 들어갈 부분 -->
	</head>
	<body>
		@yield('content') <!-- body 컨텐츠가 들어갈 부분 -->
		<script src="https://code.jquery.com/jquery-3.5.1.min.js"></script>
		@yield('script') <!-- script가 들어갈 부분 -->
	</body>
</html>

resources/view/layouts/tasks_layout.blade.php

여기서 @yield 는 어떤 섹션의 컨텐츠을 나타내는 데에 사용되는 지시어다.
blade파일에서 @section('yield 이름') 으로 yield 부분에 넣을 컨텐츠를 작성할 수 있고 @endsection으로 닫아줘야한다. 블레이드 템플릿에서 지시어를 사용할 때는 지시어 앞에 @를 붙여주고 데이터를 표시할 땐 {{ $data }} 이런 식으로 쓴다. 블레이드 템플릿 (link) 애플리케이션의 레이아웃을 정의하였으니, 이 레이아웃을 상속하는 자식 페이지를 즉 index 페이지와 create 페이지를  정의해보자. resource/views 안에 tasks 폴더를 만들고 안에 뷰가 될 블레이드 템플릿인
index.blade.php 와 create.blade.php를 만들어 준다.

 

- index 뷰                                             

@extends('layouts.tasks_layout') // 레이아웃을 사용함.

@section('title')
게시판
@endsection

@section('style')
<style>
    table,th,td {
        border : 1px solid black;
        border-collapse: collapse;
        margin : 20px 20px -15px 20px;
    }

    th,td {
        padding: 5px;
    }

    th {
        background-color: honeydew;
    }
</style>
@endsection

@section('content')
<h1>게시판</h1>
<small><?= $totalCount ?>개의 글이 있습니다.
<?= $pageNum ?>페이지 입니다.</small>
<table>
    <tr>
    	<th>ID</th>
    	<th>MEMO</th>
    	<th>NAME</th>
    	<th>DATE</th>
    	<th></th>
    </tr>
    @foreach($comments as $comment)
    <tr>
    	<td>
    	{{ $comment->id }}
    	</td>
    	<td>
    	@if ($comment->depth==0)
      		{{ $comment->memo }}
   		@else
    	@for ($i=0; $i<$comment->depth; $i++)
        	&nbsp&nbsp
        @endfor
        └{{ $comment->memo }}
    	@endif
    </td>
    <td>
    	{{ $comment->creator_name }}
    </td>
    <td>
    	{{ $comment->created_at }}
    </td>
    <td>
    	<form  style="float:left; margin-right:10px;" action="tasks/create" method="GET">
        	<button onClick="commentInfo({{ $comment->id }},{{ $comment->grp }}
        	,{{ $comment->sort }},{{ $comment->depth }})">댓글달기</button>
        	<input type="hidden" name = "mode" value="0">
        	<input type="hidden" class = "id" name = "id" value="">
        	<input type="hidden" class = "grp" name = "grp" value="">
        	<input type="hidden" class = "sort" name = "sort" value="">
        	<input type="hidden" class = "depth" name = "depth" value="">
        	<input type="hidden" name="page" value="<?= $pageNum ?>">
    	</form>
    	<form action="/tasks" method="GET" style="float:left;">
       		<input type="submit" value="삭제하기">
       		<input type="hidden" name = "del" value="1">
        	<input type="hidden" name = "delId" value="{{ $comment->id }}">
        	<input type="hidden" name="page" value="{{$pageNum}}">
    	</form>
    </td>
</tr>
@endforeach
</table>
	<form action="tasks/create" method="GET">
    	<button style="margin-top:20px;">글쓰기</button>
    	<input type="hidden" name = "mode" value="1">
    	<input type="hidden" name="page" value="{{ $pageNum }}">
	</form>

<a href = "/tasks?pageNum={{ $startPage }}"><<</a>
    <?php if($pageNum == 1)
    {
    echo "";
    }
    else
    { ?>
    <a href = "/tasks?page={{ $pageNum-1 }}"><</a>
<?php } ?>
    <?php for($i=$startPage; $i<=$endPage; $i++)
    { ?>
    <a href = "/tasks?page=<?= $i ?>"><?= $i ?></a>
<?php } ?>
    <?php if($pageNum == $totalPage)
    { 
    echo "";
    }
    else 
    { ?>
    <a href = "/tasks?page={{ $pageNum+1 }}">></a>
<?php } ?>
    <a href = "/tasks?page={{ $endPage }}">>></a><br>
    
@section('script')
<script>
function commentInfo(id,grp,sort,depth)
{
    $('.id').val(id);
    $('.grp').val(grp);
    $('.sort').val(sort);
    $('.depth').val(depth);
};
</script>
@endsection
@endsection

resource/views/tasks/index.blade.php (뭔가 오류가 있는지 들여쓰기 수정이 안된다.)

정신없을 수 있지만 천천히 살펴보자. 스타일과 레이아웃은 생략하고 데이터를 표시해주는 부분을 보겠다.

 @foreach($comments as $comment) // 블레이드 템플릿에서 제공하는 반복문을 위한 지시어.
    <tr>                         // foreach와 기능은 똑같다.
    	<td>
    	{{ $comment->id }}       // 데이터를 표시 할 땐 {{ }}로 감싸준다.
    	</td>
    	<td>
    	@if ($comment->depth==0)
      		{{ $comment->memo }}
   		@else
    	@for ($i=0; $i<$comment->depth; $i++) // 대댓글을 구분하기 위해 깊이만큼 띄어쓰기.
        	&nbsp&nbsp
        @endfor
        └{{ $comment->memo }}
    	@endif
    </td>
    <td>
    	{{ $comment->creator_name }}
    </td>
    <td>
    	{{ $comment->created_at }}
    </td>
    <td>
    	<form  style="float:left; margin-right:10px;" action="tasks/create" method="GET">
        	<button onClick="commentInfo({{ $comment->id }},{{ $comment->grp }}
        	,{{ $comment->sort }},{{ $comment->depth }})">댓글달기</button>
        	<input type="hidden" name = "mode" value="0">
        	<input type="hidden" class = "id" name = "id" value="">
        	<input type="hidden" class = "grp" name = "grp" value="">
        	<input type="hidden" class = "sort" name = "sort" value="">
        	<input type="hidden" class = "depth" name = "depth" value="">
        	<input type="hidden" name="page" value="<?= $pageNum ?>">
    	</form>
    	<form action="/tasks" method="GET" style="float:left;">
       		<input type="submit" value="삭제하기">
       		<input type="hidden" name = "del" value="1">
        	<input type="hidden" name = "delId" value="{{ $comment->id }}">
        	<input type="hidden" name="page" value="{{$pageNum}}">
    	</form>
    </td>
</tr>
@endforeach


데이터와 댓글버튼, 삭제버튼이 있는 부분이다. 포스팅 최상단의 이미지를 보면 더 이해가 잘 될 것이다.
삭제하기 버튼을 누르면 삭제를 구분해줄 파라미터와 삭제할 코멘트의 아이디를 보낸다.
create뷰로 파라미터를 보내주는 댓글달기 폼 부분을 보면 버튼을 클릭하면 commentInfo 함수가 실행되는데,

function commentInfo(id,grp,sort,depth)
{
    $('.id').val(id);
    $('.grp').val(grp);
    $('.sort').val(sort);
    $('.depth').val(depth);
};


함수의 생김새는 이렇다. 버튼을 클릭하면 그 버튼이 위치한 행의 id, grp, sort, depth 값이 create에 파라미터 값으로 보내질 value 값에 들어가는 자바스크립트 함수이다.

<a href = "/tasks?pageNum={{ $startPage }}"><<</a>
    <?php if($pageNum == 1)
    {
    echo "";
    }
    else
    { ?>
    <a href = "/tasks?page={{ $pageNum-1 }}"><</a>
<?php } ?>
    <?php for($i=$startPage; $i<=$endPage; $i++)
    { ?>
    <a href = "/tasks?page=<?= $i ?>"><?= $i ?></a>
<?php } ?>
    <?php if($pageNum == $totalPage)
    { 
    echo "";
    }
    else 
    { ?>
    <a href = "/tasks?page={{ $pageNum+1 }}">></a>
<?php } ?>
    <a href = "/tasks?page={{ $endPage }}">>></a><br>


이 부분은 페이징 부분이다.  php와 블레이드 지시어가 혼용되어있어 꼼꼼히 봐야 된다.
<<, <, 페이지번호, >, >> 가 순서대로 있다. 각 변수에 대한 설명은 위에서 했으니 참고하고 보면 좋을 것이다.

 

- create 뷰                                             

@extends('layouts.tasks_layout')

@section('title')
글 작성
@endsection

@section('content')
@if (app('request')->input('mode') ==0)
<h1>댓글작성</h1> //index에서 보낸 mode의 파라미터에 따라 타이틀이 바뀐다.
@else
<h1>글 작성</h1>
@endif

<form action="/tasks" method="POST">
@csrf
<p><label for="creator_name">NAME :</label>
<input type="text" id="creator_name" name="creator_name" placeholder="이름 입력"></p><br>
<p><textarea name="memo" id="memo" placeholder="글 작성" cols="20" rows="10" ></textarea></p>

<input type="hidden" id = "mode" name = "mode" value="{{ app('request')->input('mode') }}">
<input type="hidden" id = "id" name = "id" value="{{ app('request')->input('id') }}">
<input type="hidden" id = "grp" name = "grp" value="{{ app('request')->input('grp') }}">
<input type="hidden" id = "sort" name = "sort" value="{{ app('request')->input('sort') }}">
<input type="hidden" id = "depth" name = "depth" value="{{ app('request')->input('depth') }}">
<input type="hidden" id = "page" name = "page" value=" {{ app('request')->input('page') }}">
<input type="submit">
</form>
@endsection

resource/views/tasks/create.blade.php

 

NAME 부분에 작성자명을 입력하고 글 작성 부분에 텍스트를 입력하면 된다. 
제출을 누르면 데이터 베이스에 입력한 값들이 저장이 된다. POST로 보낸 파라미터는 컨트롤러의 store 메소드에서 처리가 된다.

폼 태그 바로 밑에 있는 @csrf는  크로스-사이트 요청 위조 공격(CSRF) 으로 부터 애플리케이션을 보호하기 위해 쓰는 지시어인데, 사용하면 토큰 필드를 생성해준다. 자세한 내용은 CSRF보호(link)에서 확인할 수 있다. POST메소드를 사용할 때 꼭 선언해주어야 한다.

만약에 DB에 한글을 저장했는데 한글이 깨져서 저장되어있는 경우
config/database.php 에 본인이 사용하는 관계형 데이터베이스 (RDB) 의 설정을 찾아

'charset' => 'utf8mb4',
'collation' => 'utf8mb4_unicode_ci',

charset 과 collation 부분을 변경해주면 된다.

 

지금까지 잘 따라왔다면. 콘솔의 프로젝트 디렉터리 위치에서 php artisan serve 명령어를 실행한 후 주소창에 localhost:8000/tasks 를 검색하면 정상적으로 작동이 되는 것을 볼 수 있다.

 

 

틀린 부분이 있다면 알려주시면 감사하겠습니다. 읽어주셔서 감사합니다.

 

다음 포스팅은 여기에 Ajax를 활용한 비동기 방식 페이지 검색 기능을 추가할 것이다.

'PHP > Laravel' 카테고리의 다른 글

[Laravel 7.x] Ajax 를 이용한 계층형 게시판 조회  (0) 2020.08.13