git 0e29f42d953c6ad1f0c06968a9b043f808f3ed87
- Основы
- Защита от CSRF
- Подмена HTTP-метода
- Именованные роуты
- Группы роутов
- Доменная маршрутизация
- Префикс пути
- Привязка моделей
- Ошибки 404
- Маршрутизация в контроллер
Большинство роутов (маршруты, routes) вашего приложения будут определены в файле app/Http/routes.php
, который загружается сервис-провайдером App\Providers\RouteServiceProvider
. В Laravel простейший роут состоит из URI (пути) и функции-замыкания.
Route::get('/', function()
{
return 'Hello World';
});
Route::post('foo/bar', function()
{
return 'Hello World';
});
Route::put('foo/bar', function()
{
//
});
Route::delete('foo/bar', function()
{
//
});
Route::match(['get', 'post'], '/', function()
{
return 'Hello World';
});
Route::any('foo', function()
{
return 'Hello World';
});
Route::get('foo', array('https', function()
{
return 'Must be over HTTPS';
}));
Вам часто может понадобиться сгенерировать URL к какому-либо роуту - для этого используется метод URL::to
:
$url = url('foo');
Здесь 'foo' - это URI.
Laravel предоставляет простой способ защиты от межсайтовых подделок запросов (cross-site request forgeries). CSRF - это вид вредоносной атаки, в результате которой несанкционированные команды выполняются от имени зарегистрированного пользователя
Фреймворк автоматически генерит так называемый CSRF-токен для каждой активной сессии. Этот токен можно проверять при обработке запроса - действительно ли запрос послан с вашего сайта, а не с сайта-злоумышленника. Как правило проверяют только POST, PUT и DELETE запросы, так как они могут изменить состояние приложения (внести изменения в БД).
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
То же самое, но с использованием шаблонизатора Blade:
<input type="hidden" name="_token" value="{{ csrf_token() }}">
Вам не нужно проверять вручную соответствие CSRF-токена сессионному в POST, PUT и DELETE запросах, HTTP middleware (посредник) VerifyCsrfToken
делает это автоматически. Вдобавок к полю _token
, проверяется еще и HTTP-заголовок X-CSRF-TOKEN
, который часто используется в Javascript-фреймворках.
HTML-формы не поддерживают методы HTTP-запроса PUT
или DELETE
. Для того, чтобы отправить на сервер HTTP-запрос с этими методами, вам нужно добавить в форму скрытый input с именем _method
.
Значение этого поля будет восприниматься фреймворком как тип HTTP-запроса. Например:
<form action="/foo/bar" method="POST">
<input type="hidden" name="_method" value="PUT">
<input type="hidden" name="_token" value="<?php echo csrf_token(); ?>">
</form>
В роутах можно указывать параметры, которые можно получить в виде аргументов функции-замыкания:
Route::get('user/{id}', function($id)
{
return 'User '.$id;
});
Route::get('user/{name?}', function($name = null)
{
return $name;
});
Route::get('user/{name?}', function($name = 'John')
{
return $name;
});
Route::get('user/{name}', function($name)
{
//
})
->where('name', '[A-Za-z]+');
Route::get('user/{id}', function($id)
{
//
})
->where('id', '[0-9]+');
Конечно, при необходимости вы можете передать массив ограничений (constraints):
Route::get('user/{id}/{name}', function($id, $name)
{
//
})
->where(['id' => '[0-9]+', 'name' => '[a-z]+'])
Вы можете определить соответствие параметра пути регулярному выражению глобально для всех роутов. Паттерны задаются в методе boot
сервис-провайдера RouteServiceProvider
. Например, если у вас {id}
в URL-ах это всегда числовое значение:
$router->pattern('id', '[0-9]+');
После того как паттерн определён, он применяется ко все роутам.
Route::get('user/{id}', function($id)
{
// Здесь $id будет только числом
});
Если вам нужно получить значение параметра вне роута, вы можете использовать метод input()
:
if ($route->input('id') == 1)
{
//
}
Вы можете обратиться к текущему роуту через объект Illuminate\Http\Request
. Получить этот объект вы можете при помощи фасада Request::
или подав его (type-hint) в аргументы конструктора нужного класса или в аргументы функции-замыкания:
use Illuminate\Http\Request;
Route::get('user/{id}', function(Request $request, $id)
{
if ($request->route('id'))
{
//
}
});
Присваивая имена роутам вы можете сделать обращение к ним (при генерации URL в шаблонах (views) или редиректах) более удобным. Вы можете задать имя роуту таким образом:
Route::get('user/profile', ['as' => 'profile', function()
{
//
}]);
Также можно указать контроллер и его метод:
Route::get('user/profile', [
'as' => 'profile', 'uses' => 'UserController@showProfile'
]);
Теперь вы можете использовать имя маршрута при генерации URL или переадресации:
$url = route('profile');
$redirect = redirect()->route('profile');
Получить имя текущего выполняемого роута можно методом currentRouteName
:
$name = Route::currentRouteName();
Иногда вам может быть нужно применить фильтры к набору маршрутов. Вместо того, чтобы указывать их для каждого маршрута в отдельности вы можете сгруппировать маршруты:
Route::group(['middleware' => 'auth'], function()
{
Route::get('/', function()
{
// К этому маршруту будет привязан фильтр auth.
});
Route::get('user/profile', function()
{
// К этому маршруту также будет привязан фильтр auth.
});
});
Чтобы не писать полный неймспейс к каждому контроллеру, вы можете использовать параметр namespace
в группе:
Route::group(['namespace' => 'Admin'], function()
{
//
});
Примечание: По умолчанию
RouteServiceProvider
включает все роуты внутрь неймспейса, определенного в его свойстве$namespace
.
Роуты Laravel способны работать и с поддоменами:
Route::group(['domain' => '{account}.myapp.com'], function()
{
Route::get('user/{id}', function($account, $id)
{
//
});
});
Группа роутов может быть зарегистрирована с одним префиксом без его явного указания с помощью ключа prefix
в параметрах группы.
Route::group(['prefix' => 'admin'], function()
{
Route::get('user', function()
{
//
});
});
Привязка моделей - удобный способ передачи экземпляров классов в ваш роут. Например, вместо передачи ID пользователя вы можете передать модель User, которая соответствует данному ID, целиком. Для начала используйте метод route
в RouteServiceProvider::boot
для указания класса, который должен быть внедрён.
public function boot(Router $router)
{
parent::boot($router);
$router->model('user', 'App\User');
}
Затем зарегистрируйте роут, который принимает параметр {user}
:
Route::get('profile/{user}', function(App\User $user)
{
//
});
Из-за того, что мы ранее привязали параметр {user}
к модели App\User
, то её экземпляр будет передан в маршрут. Таким образом, к примеру, запрос profile/1
передаст объект User
, который соответствует ID 1, полученному из БД.
Внимание: если переданный ID не соответствует строке в БД, будет брошено исключение (Exception) 404.
Если вы хотите задать свой собственный обработчик для события "не найдено", вы можете передать функцию-замыкание в метод model
:
Route::model('user', 'User', function()
{
throw new NotFoundHttpException;
});
Иногда вам может быть нужно использовать собственный метод для получения модели перед её передачей в маршрут. В этом случае просто используйте метод Route::bind
. Функция-замыкание принимает в качестве аргумента параметр из URL и должна возвратить экземпляр класса, который должен быть встроен в роут.
Route::bind('user', function($value)
{
return User::where('name', $value)->first();
});
Есть два способа вызвать исключение 404 (Not Found) из маршрута. Первый - при помощи хэлпера abort
:
abort(404);
Этот хэлпер бросает исключение Symfony\Component\HttpFoundation\Exception\HttpException
с кодом ответа 404.
Второй - вы можете сами бросить исключение Symfony\Component\HttpKernel\Exception\NotFoundHttpException
.
Смотрите также секцию errors документации.