Начнем

Учебное пособие

Концепции

Приложение

Запрос

Ответ

Routing

Обработка ошибок

Cook book

Дополнения

Contributing

Первое пошаговое руководство



Если вы ищете гид по всем компонентам для создания очень простого приложения Slim
(тут нет Twig, но есть Monolog и подключение к базе данных PDO), то вы в нужном месте. Пройдитесь через учебник, чтобы создать пример приложения, или адаптируйте каждый шаг для своих нужд.

Прежде чем вы начнете: существует также skeleton project который даст вам быстрый старт для примера приложения, поэтому используйте его, если вы предпочитаете просто что-то сделать, а не изучать, как работают все компоненты.

В этом учебном пособии рассматривается пример приложения. Код приложения, если вы хотите , чтобы обратиться к нему.

Настройка

Начните с создания папки для вашего проекта (у меня называется project, потому что именовать вещи сложно). Мне нравится резервировать верхний уровень для вещей, которые есть не-код, а затем есть папка для исходного кода и папка внутри того, что является моим webroot, поэтому моя первоначальная структура выглядит следующим образом:

.
├── project
│   └── src
│       └── public

Установка Slim Framework

Composer лучший способ установить Slim Framework. Если у вас его нет, вы можете воспользоваться инструкцией по установке, в моем проекте я только что загрузил composer.phar в свой src/ каталог, и я буду использовать его локально. Итак, моя первая команда выглядит так (Я в src/ каталоге):

    php composer.phar require slim/slim

Это сделает две вещи:

  • Добавьте зависимость Slim Framework в composer.json (в моем случае он создает файл для меня, поскольку у меня его еще нет, безопасно запускать его, если у вас уже есть composer.json файл )
  • Выполните composer install так, чтобы эти зависимости действительно были доступны для использования в вашем приложении

Если вы сейчас заглянете в каталог проекта, вы увидите, что у вас есть vendor/ папка со всем кодом библиотеки. Также есть два новых файла: composer.json и composer.lock. Это самое лучшее время, чтобы настроить системы управления версиями, а также: при работе с composer, всегда исключать vendor/ каталог, но два composer.json И composer.lock должны быть включены в систему контроля версиями. Поскольку я использую composer.phar в этом каталогк я собираюсь включить его также в свое репо; чтобы вы могли использовать composer команды на всех системай в которых надо.

Чтобы правильно настроить игнорирование в git , создайте файл src/.gitignore и добавте следующую стоку в файл.

vendor/*

Теперь git не предложит вам добавить файлы vendor/ в репозиторий - потому что мы позволяем composer управлять этими зависимостями, а не включать их в наш репозиторий управления версиями.

Создание Приложения

На project homepage есть отличный и минимальный пример, поэтому мы будем использовать этот пример как отправную точку index.php для Slim Framework. Поместите следующий код в src/public/index.php:

<?php
use \Psr\Http\Message\ServerRequestInterface as Request;
use \Psr\Http\Message\ResponseInterface as Response;

require '../vendor/autoload.php';

$app = new \Slim\App;
$app->get('/hello/{name}', function (Request $request, Response $response) {
    $name = $request->getAttribute('name');
    $response->getBody()->write("Hello, $name");

    return $response;
});
$app->run();

Мы просто вставили загрузку кода ... давайте посмотрим, что он делает.

В use объявление в верхней части скрипта только подключения Request и Response в наш скрипт, и мы не должны обращаться к ним по их многословным именам. Slim framework поддерживает PSR-7, который является стандартом PHP для обмена сообщениями HTTP, поэтому вы заметите, что при создании своего приложения вы часто и часто видите Request и Response объекты. Это современный и отличный подход к написанию веб-приложений.

Затем мы подключаем vendor/autoload.php файл - файл созданый Composer. Он позволит ссылаться на Slim
и другие связанные зависимости которые мы установили ранее. Обратите внимание: если вы используете ту же структуру файлов, что и я, то vendor/ каталог находится в родительском уровне от вашего, index.php и вам, возможно, придется настроить путь, как я сделал выше.

Наконец, мы создаем $app бъект, который является началом Slim goodness. $app->get() Вызов наш первый "route" - когда мы делаем запрос GET на /hello/someone то это код , который ответит на него. Не забывайте вам нужна эта заключительная $app->run() строка, чтобы рассказать Slim, что мы закончили настройку, и пришло время заняться основным событием.

Теперь у нас есть приложение, нам нужно его запустить. Я расскажу о двух вариантах: встроенном веб-сервере PHP и настройке виртуального хоста Apache.

Запуск приложения с веб-сервером PHP

Это мой предпочтительный вариант «быстрого старта», потому что он не полагается ни на что другое! Из src/public каталого запустите команду:

php -S localhost:8080

Это сделает ваше приложение доступным по адресу http://localhost:8080 (если вы уже используете порт 8080 на своем компьютере, вы получите предупреждение. Просто выберите другой номер порта).

Обратите внимание вы получите сообщение об ошибке "Page Not Found" по этому URL-адресу - но это сообщение об ошибке от Slim, так что это ожидается. Попробуйте http://localhost:8080/hello/joebloggs вместо этого :)

Запустите приложение с помощью Apache или nginx

Чтобы получить эту настройку в стандартном стеке LAMP, нам понадобится пара дополнительных компонентов: некоторая конфигурация виртуального хоста и одно правило перезаписи.

Конфигурация vhost должна быть довольно простой; нам здесь ничего не нужно. Скопируйте существующую конфигурацию vhost по умолчанию и укажите, ServerName как вы хотите ссылаться на свой проект. Например, вы можете установить:

ServerName slimproject.dev

or for nginx:

server_name slimproject.dev;

Затем вы также захотите установить DocumentRoot чтобы указать public/ каталог вашего проекта, что-то вроде этого (отредактируйте существующую строку):

DocumentRoot    /home/lorna/projects/slim/project/src/public/

or for nginx:

root    /home/lorna/projects/slim/project/src/public/

Не забудьте перезапустить сервер, ведь вы изменили конфигурацию!

У меня также есть .htaccess файл в моем src/public каталоге; это зависит от того, включен ли модуль перезаписи Apache и просто делает все веб-запросы доступными к index.php, чтобы Slim мог обрабатывать всю маршрутизацию для нас. Вот мой .htaccess файл:

RewriteEngine on
RewriteCond %{REQUEST_FILENAME} !-d
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule . index.php [L]

nginx не использует .htaccess файлы, поэтому вам нужно добавить следующее в конфигурацию вашего сервера в location блоке:

if (!-e $request_filename){
    rewrite ^(.*)$ /index.php break;
}

ПРИМЕЧАНИЕ: Если вы хотите, чтобы ваша точка входа была чем-то иным, чем index.php, вам также понадобится изменить вашу конфигурацию. api.php также обычно используется в качестве точки входа, поэтому ваша настройка должна соответствовать соответствующим образом. В этом примере предполагается, что вы используете index.php.

С помощью этой настройки просто не забудьте использовать http://slimproject.dev вместо http: // localhost: 8080 в других примерах этого урока. Такое же предупреждение о работоспособности, как указано выше: вы увидите страницу с ошибкой на странице http://slimproject.dev, но на самом деле это страница с ошибкой Slim's . Если вы перейдете к http://slimproject.dev/hello/joebloggs, тогда должно произойти что-то лучше.

Конфигурация и автозагрузчики

Теперь мы создали платформу, мы можем начать получать все, что нам нужно, в самом приложении.

Добавить параметры конфигурации в приложение

В первом примере используются все значения по умолчанию Slim, но мы можем легко добавить конфигурацию в наше приложение, когда мы его создадим. Есть несколько вариантов, но здесь я только что создал массив опций конфигурации, а затем сказал Slim, чтобы использовать его настройки здесь, когда я его создаю.

Сначала сама конфигурация:

$config['displayErrorDetails'] = true;
$config['addContentLengthHeader'] = false;

$config['db']['host']   = "localhost";
$config['db']['user']   = "user";
$config['db']['pass']   = "password";
$config['db']['dbname'] = "exampleapp";

Первая строка - самая важная! Включите это в режиме разработки, чтобы получить информацию об ошибках (без этого, Slim будет, по крайней мере, регистрировать ошибки, поэтому, если вы используете встроенный веб-сервер PHP, тогда вы увидите их на консольном выходе, который будет полезен). Вторая строка позволяет веб-серверу устанавливать заголовок Content-Length, который делает Slim более предсказуемым.

Другие настройки здесь не являются конкретными ключами/значениями, это всего лишь некоторые данные, которые я хочу получить позже.

Теперь, чтобы передать это в Slim, нам нужно изменить, где мы создаемSlim/App объект, чтобы он теперь выглядел следующим образом:

$app = new \Slim\App(["settings" => $config]);

Теперь мы сможем получить доступ к любым настройкам, которые мы помещаем в этот $config массив из нашего приложения.

Настройка автозагрузки для собственных классов

Composer может обрабатывать автозагрузку ваших собственных классов так же хорошо, как и имеющиеся. Для углубленного руководства взгляните на использование Composer для управления правилами автозагрузки.

Моя настройка довольно проста, так как у меня есть только несколько дополнительных классов, они просто находятся в глобальном пространстве имен, а файлы находятся в
src/classes/ каталоге. Поэтому, чтобы загрузить их, я добавлю этот autoload раздел в свой composer.json файл:

{
    "require": {
        "slim/slim": "^3.1",
        "slim/php-view": "^2.0",
        "monolog/monolog": "^1.17",
        "robmorgan/phinx": "^0.5.1"
    },
    "autoload": {
        "psr-4": {
            "": "classes/"
        }
    }
}

Добавление зависимостей

Большинство приложений будут иметь некоторые зависимости, а Slim прекрасно их имитирует, используя DIC (Container Injection Container), построенный на Pimple. В этом примере будут использоваться как Monolog так и PDO соединение с MySQL.

Идея контейнера для инъекций зависимостей заключается в том, что вы настраиваете контейнер для загрузки зависимостей, которые необходимы вашему приложению, когда они им нужны. После того, как DIC создал / собрал зависимости, он сохраняет их и может предоставить их позже, если это необходимо.

Чтобы получить контейнер, мы можем добавить следующее после строки, в которой мы создаем, $app и до того, как мы начнем регистрировать маршруты в нашем приложении:

$container = $app->getContainer();

Теперь у нас есть Slim\Container объект, мы можем добавить к нему наши сервисы.

использование Monolog в вашем приложении

Если вы еще не знакомы с Monolog, это отличный framework логирования для PHP-приложений, поэтому собираюсь использовать его здесь. Во-первых, подключите библиотеку Monolog через composer:

php composer.phar require monolog/monolog

Зависимость называется logger, а код для добавления выглядит следующим образом:

$container['logger'] = function($c) {
    $logger = new \Monolog\Logger('my_logger');
    $file_handler = new \Monolog\Handler\StreamHandler("../logs/app.log");
    $logger->pushHandler($file_handler);
    return $logger;
};

Мы добавляем элемент в контейнер, который сам является анонимной функцией ($c параметр передается в самом контейнере, поэтому вы можете использовать другие зависимости, если это вам нужно).
Это будет вызвано, когда мы попытаемся получить доступ к этой зависимости в первый раз; здесь код устанавливает настройку зависимости. В следующий раз, когда мы попытаемся получить доступ к той же зависимости, тот же самый объект, который был создан в первый раз, будет использоваться в следующий раз.

Мой Monolog конфиг здесь довольно прозрачен, только настройки приложения для регистрации всех ошибок в файл logs/app.log (помните, это путь с точки зрения того, где работает скрипт, в нашем случае это index.php).

С помощью logger на месте я могу использовать его изнутри кода роута с помощью строки, подобной этой:

 $this->logger->addInfo("Something interesting happened");

Хорошее логирование приложения - действительно важная основа для любого приложения, поэтому я всегда рекомендую поместить что-то подобное на место. Это позволяет вам добавить столько или меньше отладки, сколько захотите, и с помощью соответствующих уровней журнала с каждым сообщением вы можете иметь столько же или немного деталей, сколько подходит для того, что вы делаете в любой момент.

Добавить соединение с базой данных

Существует множество библиотек баз данных, доступных для PHP, но в этом примере используется PDO - это доступно в PHP в качестве стандарта, поэтому оно, вероятно, полезно в каждом проекте или вы можете использовать свои собственные библиотеки, адаптировав приведенные ниже примеры.

Точно так же, как мы сделали для добавления Monolog to the DIC, мы добавим анонимную функцию, которая устанавливает зависимость, в этом случае называется db:

$container['db'] = function ($c) {
    $db = $c['settings']['db'];
    $pdo = new PDO("mysql:host=" . $db['host'] . ";dbname=" . $db['dbname'],
        $db['user'], $db['pass']);
    $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
    $pdo->setAttribute(PDO::ATTR_DEFAULT_FETCH_MODE, PDO::FETCH_ASSOC);
    return $pdo;
};

Помните конфиг, который мы добавили в наше приложение раньше? Ну, вот где мы его используем - контейнер знает, как получить доступ к нашим настройкам, и поэтому мы можем легко получить нашу конфигурацию отсюда. С помощью config мы создаем PDO объект (помните, что это приведет к отказу, PDOException если он сработает, и вы можете обработать это здесь) чтобы мы могли подключиться к базе данных. Я включил два setAttribute() вызова, которые действительно не нужны, но я нахожу, что эти два параметра делают PDO более удобным для использования в качестве библиотеки, поэтому я оставил настройки в этом примере, чтобы вы могли их использовать! Наконец, мы возвращаем наш объект соединения.

Опять, мы можем получить доступ к нашим зависимостям с помощью только, $this-> и затем имя требуемой зависимости, которая в этом случае есть $this->db, по этому в моем случае приложении есть код, который выглядит примерно так:

 $mapper = new TicketMapper($this->db);

Это приведет к db dependency ависимости от DIC, создав его, если это необходимо, и в этом примере просто позволяет мне передать PDO объект прямо в мой класс сопоставления.

Создание роутеров

"Роутеры" - это шаблоны URL, которые мы будем описывать и прикреплять к ним функциональность. Slim не использует автоматическое сопоставление или формулы URL-адресов, поэтому вы можете сделать любой шаблон маршрута, который вам нравится, на любую понравившуюся вам функцию, она очень гибкая. Маршруты могут быть связаны с определенным HTTP-глаголом (например, GET или POST) или более чем одним глаголом.

В качестве первого примера, вот код для создания запроса GET, /tickets в котором перечислен список в мой багтрекер пример приложения. Он просто выплевывает переменные, так как мы еще не добавили никаких представлений в наше приложение:

$app->get('/tickets', function (Request $request, Response $response) {
    $this->logger->addInfo("Ticket list");
    $mapper = new TicketMapper($this->db);
    $tickets = $mapper->getTickets();

    $response->getBody()->write(var_export($tickets, true));
    return $response;
});

Использование $app->get() означает, что этот маршрут доступен только для запросов GET; есть эквивалентный $app->post() вызов, который также принимает шаблон роутера и обратный вызов для запросов POST. Существуют также методы для других глаголов - а также map() функция для ситуаций, когда более одного глагола должен использовать один и тот же код для определенного роута.

Slim роуты работают в том порядке, в котором они объявлены, поэтому, если у вас есть роут, который может пересекать другой роут, вам нужно сначала поставить наиболее конкретный роут. Slim будет генерировать исключение, если есть проблема, например, в этом приложении у меня есть оба /ticket/new и /ticket/{id} они должны быть объявлены в этом порядке, иначе маршрутизация будет считать, что «новый» - это идентификатор!

В этом примере приложения все роуторы находятся в index.php но напрактике это может сделать довольно длинный и громоздкий файл! Это хороших повод прорефакторить ваше приложени, чтобы поместить набор маршрутов с обратными вызовами, которые фактически объявлены в другом месте.

Все обратные вызовы роута принимают три параметра (третий необязателен):

Request
запрос в нем содержится вся информация о входящем запросе, заголовках, переменных и т. д.
Response
ответ мы можем добавить к нему выходные данные и заголовки, и после его завершения он будет превращен в HTTP-ответ, который получает клиент
Arguments
аргументы именованные заполнители из URL-адреса (больше всего за один момент), это необязательно и обычно опускается, если нет

Этот акцент на Request and Response иллюстрирует, что Slim 3 основан на стандарте PSR-7 для HTTP-сообщений. Использование объекта запроса и ответа также делает приложение более тестируемым, так как нам не нужно делать реальные запросы и ответы, мы можем просто настроить объекты по желанию.

Роуторы с помощью именных заполнителей

Иногда наши URL-адреса имеют в них переменные, которые мы хотим использовать в нашем приложении. В моем примере отслеживания ошибок я хочу, чтобы URL-адреса хотели /ticket/42 ссылаться на ticket - и Slim имеет простой способ разбора секции "42" и сделать его доступным для удобства использования в коде. Вот маршрут, который делает именно это:

$app->get('/ticket/{id}', function (Request $request, Response $response, $args) {
    $ticket_id = (int)$args['id'];
    $mapper = new TicketMapper($this->db);
    $ticket = $mapper->getTicketById($ticket_id);

    $response->getBody()->write(var_export($ticket, true));
    return $response;
});

Посмотрите, где определен маршрут: мы пишем его как /ticket/{id}.
Когда мы это сделаем, маршрут займет часть URL-адреса, где {id} объявлен, и становиться доступным внутри обратного вызова как $args['id'].

Использование параметров GET

Поскольку GET и POST отправляют данные по-разному, то способ, которым мы получаем эти данные из объекта Request, сильно отличается в Slim.

Можно получить все параметры запроса из запроса, выполнив $request->getQueryParams()команду, которая вернет ассоциативный массив. Поэтому для URL-адреса /tickets?sort=date&order=desc мы получим ассоциативный массив, например:

    ["sort" => "date", "order" => "desc"]

Затем они могут использоваться (после проверки, конечно) внутри вашего обратного вызова.

Работа с данными POST

При работе с входящими данными мы можем найти это в теле. Мы уже видели, как мы можем анализировать данные из URL-адреса и как получать переменные GET, $request->getQueryParams() но как насчет данных POST? Данные запроса POST можно найти в теле запроса, а Slim имеет хорошие встроенные помощники, чтобы упростить получение информации в полезном формате.

Для данных, которые поступают из веб-формы, Slim превратит это в массив. В моем приложении-примере для tickets есть форма для создания новых tickets которые просто отправляют два поля: «title» и «description». Вот первая часть маршрута, который получает эти данные, обратите внимание, что для использования маршрута POST, $app->post() а не $app->get():

$app->post('/ticket/new', function (Request $request, Response $response) {
    $data = $request->getParsedBody();
    $ticket_data = [];
    $ticket_data['title'] = filter_var($data['title'], FILTER_SANITIZE_STRING);
    $ticket_data['description'] = filter_var($data['description'], FILTER_SANITIZE_STRING);
    // ...

Запрос $request->getParsedBody() просит Slim посмотреть запрос и Content-Type заголовки этого запроса, затем сделать что-то умное и полезное с телом. В этом примере это просто сообщение формы, поэтому результирующий $data массив выглядит очень похоже на то, от чего мы ожидаем, $_POST - и мы можем продолжать использовать расширение filter чтобы проверить, что значение приемлемо, прежде чем мы его используем.
Огромное преимущество использования встроенных методов Slim заключается в том, что мы можем тестировать вещи, введя разные объекты запроса - если мы будем использовать $_POST напрямую, мы не сможем это сделать.

Что здесь действительно хорошо, так это то, что если вы создаете API или записываете конечные точки AJAX, например, очень легко работать с форматами данных, которые поступают через POST, но не являются веб-формой. Пока Content-Type заголовок установлен правильно, Slim будет анализировать полезную нагрузку JSON в массив, и вы можете получить к ней доступ точно так же: используя $request->getParsedBody().

Views и Шаблоны

У Slim нет мнения о мнениях, которые вы должны использовать, хотя есть некоторые варианты, которые готовы подключить. Ваш лучший выбор - это Twig или простой старый PHP. У обоих вариантов есть плюсы и минусы: если вы уже знакомы с Twig, тогда он предлагает множество отличных фичи и функциональность, таких как разметка, но если вы еще не используете Twig, это может быть большой накладной кривой обучения, чтобы добавить в проект микрофрейворка. Если вы ищете простое, то PHP-представления могут быть для вас! Я выбрал PHP для этого примера проекта, но если вы знакомы с Twig, тогда не стесняйтесь использовать это; основы в основном одинаковые.

Поскольку мы будем использовать представления PHP, нам нужно будет добавить эту зависимость в наш проект через Composer. Команда выглядит так (аналогично тому, что вы уже видели):

    php composer.phar require slim/php-view

Чтобы иметь возможность отображать представление, нам сначала нужно создать представление и сделать его доступным для нашего приложения; мы делаем это, добавляя его в DIC. Код, который нам нужен, связан с другими дополнениями DIC в верхней части src/public/index.php и выглядит следующим образом:

$container['view'] = new \Slim\Views\PhpRenderer("../templates/");

Теперь у нас есть view элемент в DIC, и по умолчанию он будет искать его шаблоны в src/templates/ каталоге. Мы можем использовать его для визуализации шаблонов в наших действиях - вот маршрут списка билетов снова, на этот раз включая вызов для передачи данных в шаблон и его рендеринга:

$app->get('/tickets', function (Request $request, Response $response) {
    $this->logger->addInfo("Ticket list");
    $mapper = new TicketMapper($this->db);
    $tickets = $mapper->getTickets();

    $response = $this->view->render($response, "tickets.phtml", ["tickets" => $tickets]);
    return $response;
});

Единственная новая часть здесь - предпоследняя линия, где мы устанавливаем $response переменную. Теперь, когда view находится в DIC, мы можем ссылаться на него как $this->view. Вызов render() требует, чтобы мы предоставили три аргумента: $response, файл шаблона (внутри каталога шаблонов по умолчанию), и любые данные, которые мы хотим передать. Объекты ответа (неизменяемы) immutable что означает, что вызов render() не будет обновлять объект ответа; вместо этого он вернет нам новый объект, поэтому он должен быть захвачен таким образом. Это всегда верно, когда вы работаете с объектом ответа.

При передаче данных в шаблоны вы можете добавить столько элементов в массив, сколько хотите сделать доступными в шаблоне. Ключи массива - это переменные, которые будут существовать в момент, когда мы перейдем к самому шаблону.

Например, вот фрагмент из шаблона, который отображает список билетов (т.е. код из src/templates/tickets.phtml - который использует Pure.css чтобы помочь покрыть мои недостатки навыков фронтенда):

<h1>All Tickets</h1>

<p><a href="/ticket/new">Add new ticket</a></p>

<table class="pure-table">
    <tr>
        <th>Title</th>
        <th>Component</th>
        <th>Description</th>
        <th>Actions</th>
    </tr>

<?php foreach ($tickets as $ticket): ?>

    <tr>
        <td><?=$ticket->getTitle() ?></td>
        <td><?=$ticket->getComponent() ?></td>
        <td><?=$ticket->getShortDescription() ?> ...</td>
        <td>
            <a href="<?=$router->pathFor('ticket-detail', ['id' => $ticket->getId()])?>">view</a>
        </td>
    </tr>

<?php endforeach; ?>
</table>

В этом случае $tickets на самом деле это TicketEntity класс с геттерами и сеттерами, но если вы пройдете в массиве, вы сможете получить к нему доступ, используя здесь массив, а не объектную нотацию.

Вы заметили, что что-то интересное происходит $router->pathFor() в конце примера? Давайте поговорим о названных роутерах далее :)

Простое создание URL с именованными роутерами

Когда мы создаем маршрут, мы можем присвоить ему имя, вызвав ->setName() объект маршрута. В этом случае я добавляю имя на маршрут, который позволяет мне просматривать отдельный ticket, чтобы я мог быстро создать правильный URL-адрес для ticket, просто указав имя маршрута, поэтому мой код теперь выглядит примерно так (просто изменен кусок кода, показаннный здесь):

$app->get('/ticket/{id}', function (Request $request, Response $response, $args) {
    // ...
})->setName("ticket-detail");

Чтобы использовать это в своем шаблоне, мне нужно сделать маршрутизатор доступным в шаблоне, который захочет создать этот URL-адрес, поэтому я изменил tickets/ маршрут, чтобы передать маршрутизатор в шаблон, изменив строку визуализации, чтобы выглядеть так:

    $response = $this->view->render($response, "tickets.phtml", ["tickets" => $tickets, "router" => $this->router]);

Поскольку /tickets/{id} маршрут имеет дружественное имя и маршрутизатор, который теперь доступен в нашем шаблоне, э то то, что делает pathFor() вызов в нашем шаблоне. Поставляя id, он используется как именованный заполнитель в шаблоне URL-адреса, и создается правильный URL-адрес для привязки к этому маршруту с этими значениями. Эта функция блестящая для читаемых URL-адресов шаблонов и даже лучше, если вам когда-либо понадобится изменить формат URL по любой причине - не нужно grep шаблонов, чтобы увидеть, где они используются. Этот подход определенно рекомендуется, особенно для ссылок, которые вы будете использовать много.

Что дальше?

В этой статье дается пошаговое руководство по настройке с помощью простого приложения, которое, я надеюсь, позволит вам быстро начать работу, увидеть некоторые рабочие примеры и создать что-то потрясающее.

Отсюда я рекомендую вам взглянуть на другие части проектной документации на все, что вам нужно, которое еще не было охвачено, или что вы хотите увидеть альтернативный пример. Следующим шагом было бы взглянуть на раздел Middleware этот метод заключается в том, как мы размещаем наше приложение и добавляем такие функции, как аутентификация, которая может применяться к нескольким маршрутам.