Laravel 02. Routing & Controller

1. Route
1.1 why Route ?
PHP 프로젝트에서 우리는 /경로/php파일명을 URL 로 접근할 수 있습니다.
/aboutus/aboutus01.php
파일
/aboutus/aboutus01.php
브라우저 경로
http://url.com/aboutus/aboutus01.php
1) 복잡한 URL 을 간결하게 바꿀수 있다.
http://teddy.school.com/board/list.php?board_id=study&step=view&bid=23
=> http://teddy.school.com/board/study/23
2) 보안을 위해 직접 php 파일에 접근을 차단한다.
http://url.com/aboutus.blade.php ( x )
- php 프로젝트를 알수 있다. -> php 취약점 활용
- 경로를 알수 있다 -> 백도어등의 프로그램을 심어 자신이 심은 php 파일을 실행한다.
* Route 는 사용자의 URL 접근을 해석해서 Route 가 알고 있는 파일을 실행해준다.
1.2. Route 살펴보기
routes/web.php
use Illuminate\Support\Facades\Route;
Route::get('/', function () {
return view('welcome');
});
view() 함수는 우리가 1강에서 이야기한 view 페이지를 보여주는 명령입니다.
1) 바로 Text 를 보내줄수도 있습니다.
Route::get('/aboutus', function () {
return 'We are Hokma Teacher!';
});
2) 라우트에서 직접 로직을 만들고 결과를 리턴할 수도 있습니다.
Route::get('/addition', function () {
$result = 2 + 3;
return "The result of 2 + 3 is: " . $result;
});
3) Html 로 작성한 view 를 지정할 수 있습니다.
Route::get('/services', function () {
return view('services');
});
* 여기서 잠깐 존재하지 않는 경로를 호출하면
없는 경로에 접근해보겠습니다.
http://127.0.0.1:8000/school

404 에러, 페이지가 존재하지 않다고 알려줍니다.
3) 리다이렉트
Route::get('/school', function () {
return redirect('/service');
});
4) Controller 에게 처리를 지시하기
<?php
use Illuminate\Support\Facades\Route;
use App\Http\Controllers\LectureController;
# 컨트롤어와 function 을 지정해준다.
Route::get('/lectures', [LectureController::class, 'lectureIndex']);
# 컨트롤러를 사용할때는 web.php 상단에 LectureController 를 use 해 주어야 한다
# 컨트롤러의 자세한 내용은 다음시간에 공부하고 모양만 확인해보겠습니다.
app/Http/Controller/LectureController.php
<?php
namespace App\Http\Controllers;
class LectureController extends Controller
{
public function lectureIndex()
{
return 'This is the lecture page.';
}
}
5) 매개변수사용하기
Route::get('/article/{id}', function ($id) {
return 'Article '.$id;
});
* 만약 id 없이 url 을 호출하면
404 를 보내줍니다.
* 선택적 매개변수
#id 가 있을수도, 없을수도 있습니다.
Route::get('/article/{id?}', function ($id=null) {
return 'Article '.$id;
});
둘 이상의 매개변수를 사용할 수 있습니다.
Route::get('/article/{id}/comments/{commentId}', function ($id=null, $commentId=null) {
return 'Article '.($id). ' - Comment '.($commentId);
});
5) 정규식 제약조건
Route::get('/program/{name}', function ($name) {
return "Program's name " . $name;
})->where('name', '[A-Za-z]+');
http://127.0.0.1:8000/program/php
http://127.0.0.1:8000/program/php8
* 숫자도 허용하려면
Route::get('/program/{name}', function ($name) {
return "Program's name " . $name;
})->where('name', '[A-Za-z0-9]+');
* 기타
Route::get('/user/{id}', function ($id) {
//
})->where('id', '[0-9]+');
Route::get('/user/{id}/{name}', function ($id, $name) {
//
})->where(['id' => '[0-9]+', 'name' => '[a-z]+']);
Route::get('/user/{id}/{name}', function ($id, $name) {
//
})->whereNumber('id')->whereAlpha('name');
Route::get('/user/{name}', function ($name) {
//
})->whereAlphaNumeric('name');
Route::get('/user/{id}', function ($id) {
//
})->whereUuid('id');
6) naming
Route::get('/user/profile', function () {
//
})->name('profile');
## 컨트롤러등에서 URL 등을 대체해준다.
$url = route('profile');
return "User Index Page. Profile URL: " . $url;
## 매개변수를 사용할때
$url = route('profile',['id'=>1, 'name'=>'Teddy']);
우리는 Controller 를 통해 처리하는 방식을 주로 사용하게 될겁니다.
6) method
Route::get('/aboutus', function () {
return 'We are Hokma Teacher!';
});
Route 에서 사용한 get 은 어떤 의미일까요?
Route::get('/signup', [UserController::class, 'signupForm'])->name("signup");
Route::post('/signup', [UserController::class, 'signup'])->name("signupok");
Route::post('/signupByOTP', [UserController::class, 'signupByOTP']);
Route::get('/register', [LoginController::class, 'registerForm'])->name('register');
Route::post('/register/confirm', [LoginController::class, 'registerConfirm'])->name('register.confirm');
네. route 에서는 get 방식으로 접근하는 경로, post 로만 접근하는 경로를 지정할 수있습니다.
* /signup get, post 접근 가능여부를 직접 진행해볼것.
7) prepix
공통된 경로를 하나로 묶어 그룹화하여 간결하고 체계적으로 관리할수 있게 해줍니다.
// homepy 라우트
Route::get('/homepy/{homepyID}', [HomepyController::class, 'home'])->name('homepy.home');
Route::get('/homepy/{homepyID}/guestbook', [HomepyController::class, 'guestbook'])->name('homepy.guestbook');
Route::post('/homepy/{homepyID}/guestbook/update', [HomepyController::class, 'guestbook_update'])->name('homepy.guestbook_update');
Route::get('/homepy/{homepyID}/guestbook/delete/{no}', [HomepyController::class, 'guestbook_delete'])->name('homepy.guestbook_delete');
Route::get('/homepy/{homepyID}/lordplayer', [HomepyController::class, 'lordplayer'])->name('homepy.lordplayer');
Route::get('/homepy/{homepyID}/lordplayer/form', [HomepyController::class, 'lordplayer_form'])->name('homepy.lordplayer_form');
Route::post('/homepy/{homepyID}/lordplayer/update', [HomepyController::class, 'lordplayer_update'])->name('homepy.lordplayer_update');
Route::get('/homepy/{homepyID}/lordplayer/delete/{no}', [HomepyController::class, 'lordplayer_delete'])->name('homepy.lordplayer_delete');
Route::get('/homepy/{homepyID}/diary', [HomepyController::class, 'diary'])->name('homepy.diary');
Route::post('/homepy/{homepyID}/diary/update', [HomepyController::class, 'diary_update'])->name('homepy.diary_update');
Route::get('/homepy/{homepyID}/diary/delete/{no}', [HomepyController::class, 'diary_delete'])->name('homepy.diary_delete');
Route::get('/homepy/{homepyID}/picture', [HomepyController::class, 'picture'])->name('homepy.picture');
Route::get('/homepy/{homepyID}/picture/form', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
Route::post('/homepy/{homepyID}/picture/update', [HomepyController::class, 'picture_update'])->name('homepy.picture_update');
Route::get('/homepy/{homepyID}/picture/delete/{no}', [HomepyController::class, 'picture_delete'])->name('homepy.picture_delete');
Route::get('/homepy/{homepyID}/picture/form/{no}', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
Route::get('/homepy/{homepyID}/setting', [HomepyController::class, 'setting'])->name('homepy.setting');
Route::post('/homepy/{homepyID}/setting/update', [HomepyController::class, 'setting_update'])->name('homepy.setting_update');
Route::get('/homepy/{homepyID}/friend', [HomepyController::class, 'friend'])->name('homepy.friend');
Route::post('/homepy/{homepyID}/friend/request', [HomepyController::class, 'friend_request'])->name('homepy.friend_request');
Route::post('/homepy/{homepyID}/friend/cancel', [HomepyController::class, 'friend_cancel'])->name('homepy.friend_cancel');
Route::get('/homepy/{homepyID}/friend/{friendID}/accept', [HomepyController::class, 'friend_accept'])->name('homepy.friend_accept');
Route::get('/homepy/{homepyID}/friend/{friendID}/reject', [HomepyController::class, 'friend_reject'])->name('homepy.friend_reject');
Route::get('/homepy/{homepyID}/friend/request_list', [HomepyController::class, 'friend_request_list'])->name('homepy.friend_request_list');
Route::get('/homepy/{homepyID}/friend/{friendID}/delete', [HomepyController::class, 'friend_delete'])->name('homepy.friend_delete');
Route::get('/homepy/my/friend/list', [HomepyController::class, 'my_friend_list'])->name('homepy.my_friend_list');
// Prefix 를 이용함
Route::prefix('homepy')->name('homepy.')->group(function () {
Route::get('/{homepyID}', [HomepyController::class, 'home'])->name('homepy.home');
Route::get('/{homepyID}/guestbook', [HomepyController::class, 'guestbook'])->name('homepy.guestbook');
Route::post('/{homepyID}/guestbook/update', [HomepyController::class, 'guestbook_update'])->name('homepy.guestbook_update');
Route::get('/{homepyID}/guestbook/delete/{no}', [HomepyController::class, 'guestbook_delete'])->name('homepy.guestbook_delete');
Route::get('/{homepyID}/lordplayer', [HomepyController::class, 'lordplayer'])->name('homepy.lordplayer');
Route::get('/{homepyID}/lordplayer/form', [HomepyController::class, 'lordplayer_form'])->name('homepy.lordplayer_form');
Route::post('/{homepyID}/lordplayer/update', [HomepyController::class, 'lordplayer_update'])->name('homepy.lordplayer_update');
Route::get('/{homepyID}/lordplayer/delete/{no}', [HomepyController::class, 'lordplayer_delete'])->name('homepy.lordplayer_delete');
Route::get('/{homepyID}/diary', [HomepyController::class, 'diary'])->name('homepy.diary');
Route::post('/{homepyID}/diary/update', [HomepyController::class, 'diary_update'])->name('homepy.diary_update');
Route::get('/{homepyID}/diary/delete/{no}', [HomepyController::class, 'diary_delete'])->name('homepy.diary_delete');
Route::get('/{homepyID}/picture', [HomepyController::class, 'picture'])->name('homepy.picture');
Route::get('/{homepyID}/picture/form', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
Route::post('{homepyID}/picture/update', [HomepyController::class, 'picture_update'])->name('homepy.picture_update');
Route::get('/{homepyID}/picture/delete/{no}', [HomepyController::class, 'picture_delete'])->name('homepy.picture_delete');
Route::get('/{homepyID}/picture/form/{no}', [HomepyController::class, 'picture_form'])->name('homepy.picture_form');
Route::get('/{homepyID}/setting', [HomepyController::class, 'setting'])->name('homepy.setting');
Route::post('/{homepyID}/setting/update', [HomepyController::class, 'setting_update'])->name('homepy.setting_update');
Route::get('/{homepyID}/friend', [HomepyController::class, 'friend'])->name('homepy.friend');
Route::post('/{homepyID}/friend/request', [HomepyController::class, 'friend_request'])->name('homepy.friend_request');
Route::post('/{homepyID}/friend/cancel', [HomepyController::class, 'friend_cancel'])->name('homepy.friend_cancel');
Route::get('/{homepyID}/friend/{friendID}/accept', [HomepyController::class, 'friend_accept'])->name('homepy.friend_accept');
Route::get('/{homepyID}/friend/{friendID}/reject', [HomepyController::class, 'friend_reject'])->name('homepy.friend_reject');
Route::get('/{homepyID}/friend/request_list', [HomepyController::class, 'friend_request_list'])->name('homepy.friend_request_list');
Route::get('/{homepyID}/friend/{friendID}/delete', [HomepyController::class, 'friend_delete'])->name('homepy.friend_delete');
Route::get('/my/friend/list', [HomepyController::class, 'my_friend_list'])->name('homepy.my_friend_list');
});
컨트롤러를 그룹화할 수도 있습니다. ( 저는 실무에서 사용해본적이 없는데 이런것도 있네요 )
# Route::post('shop/items', [ShopController::class, 'index']);
Route::prefix('shop')->controller(ShopController::class)->group(function () {
Route::get('/items', 'index'); // /shop/items
Route::get('/item/{id}', 'show'); // /shop/item/{id}
});
** 라우트에 대한 질문이 있으신가요?
2. Controller
"로직을 처리하는 부분"
"사용자 요청을 받아 모델(Model)과 상호작용하고, 결과를 뷰(View)나 JSON으로 반환하는 '중간 관리자' 역할을 수행"
2.1 컨트롤러 생성
php artisan make:controller PostController
# INFO Controller [app/Http/Controllers/PostController.php] created successfully.
생성위치 app/Http/Controllers/PostController.php
2.2 컨트롤러 구조
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
//
}
2.3 Route 와 Controller
Route::get('/posts', [PostController::class, 'index']); // 목록
Route::get('/posts/create', [PostController::class, 'create']); // 작성폼
Route::post('/posts', [PostController::class, 'store']); // 저장
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class PostController extends Controller
{
public function index(Request $request)
{
return 'Posts List'
}
public function create(Request $request)
{
return 'Post Form'
}
public function store(Request $request)
{
return 'Post Save'
}
}
** 연습을 한번 해보겠습니다.
여러분은 hokma 학원의 홈페이지를 만들고 있습니다. - program list
사용자가 Program 목록을 보고 - program view
그중 Program 하나를 선택하면 상세페이지를 볼수 있습니다. - program apply
신청버튼을 누르면 신청서를 작성하는 페이지가 나옵니다. - program pply save
저장 버튼을 누르면 저장됩니다.
위에 예시를 만든것처럼 컨트롤러를 만들고 페이지를 안내하는 문자열을 출력하도록 해주세요.
2.4 __invoke 단일 작업 컨트롤러 (Single Action Controller)
특정 컨트롤러가 하나의 기능(예: 대시보드 표시, 결제 처리 등)만 수행한다면 여러 메서드를 만들 필요가 없습니다.
이때 __invoke 메서드를 사용합니다.
// 단일작업 컨트롤러 생성
php artisan make:controller IndexController --invokable
생성된 모양
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
class IndexController extends Controller
{
/**
* Handle the incoming request.
*/
public function __invoke(Request $request)
{
//
}
}
사용시 function 을 지정하지 않고 사용합니다.
Route::get('/', IndexController::class);
"Laravel is an object-oriented (OOP) based framework, and all functions are composed of classes."
“Laravel은 객체지향(OOP) 기반 프레임워크이며, 모든 기능은 Class로 구성되어 있다”
<?php
class PostController extends Controller
<?php
class User extends Model
그외에도 서비스, 미들웨어 등도 모두 class 로 되어있습니다.
클래스는
1. 재사용 가능
→ 같은 코드를 여러 곳에서 사용
2. 구조화
→ 역할별로 나누기 쉬움
3. 확장성
→ 기능을 추가하기 쉬움
클래스 vs 객체
클래스는 설계도이고, 객체는 그 설계도대로 사용되는것
중요한 이야기는 나중에 모델을 공부할때 하도록 하겠습니다.
RESTful