Первое приложение на Laravel. Пошаговое руководство (Часть 1)

Cо дня своего релиза в 2011 популярность фреймворка Laravel выросла на порядок. В 2015 году он стал самым популярным (starred) PHP фреймворком на GitHub. Сегодня Laravel выбирают в качестве основного инструмента разработчики по всему миру.
Laravel сфокусирован на вас, конечных пользователях, что в первую очередь означает нацеленность на простоту, ясность и результат. Крупные компании и разработчики-одиночки используют его для проектов любого рода: от хобби до корпоративных порталов крупнейших компаний мира.
Цель этой статьи - создать руководство для тех, кто только начал изучать Laravel. Начать с идеи и построить реальное приложение.
Это не полное руководство по фреймворку, мы не охватим все детали Laravel и для начала необходимо выполнить ряд условий. Вот, что потребуется:
- Локальная PHP среда (Homestead, Vagrant, MAMP и т.д.)
- База данных. Я буду использовать MySQL.
- PHPUnit
- Node.js
Я попытаюсь пройти через процесс создания нового приложения так же, как я бы сделал это в реальных условиях. На самом деле, код и идея взяты из реально созданного мной проекта
Планирование
Каждый проект где-то берет свое начало, это либо рабочее задание, либо просто идея в вашей голове. Независимо от источника происхождения, функционал проекта необходимо тщательно спланировать прежде чем писать код. Это очень важно.
Как вы планируете зависит от того, как работает ваш ум. Будучи визуалистом, я люблю строить план на бумаге: рисую как будет выглядеть экран, а затем переношу картинку в код. Другие предпочитают написать план проекта в текстовом файле, вики, или любой другой форме. Не имеет значения, как вы планируете, важен сам процесс.
В качестве проекта для этого руководства мы будем делать каталог ссылок. Вот список основных целей для этого приложения:
- Показать простой список ссылок
- Создать форму для добавления новых ссылок
- Проверить данные формы
- Вставить данные в базу данных.
Давайте начнем.
Первые шаги
Пришло время ринуться в бой и развернуть пустой проект. Я люблю хранить все свои рабочие проекты в директории ~ /Code и везде далее буду использовать этот путь. Вы можете изменить его на более привычный вам.
Откройте терминал и создайте новый каталог для кода проекта.
cd ~/Code
mkdir links
cd links
Затем установите программу установки Laravel :
composer global require "laravel/installer"
После завершения процесса , можно создать новый проект, выполнив:
laravel new links
Эта команда создаст новый каталог и установит пустой проект Laravel.
Теперь нужно создать виртуальный хост, ссылающийся на ~/Code/links/public, чтобы можно было загрузить сайт в браузере. В качестве домена я использовал links.dev.
Если все работает, вы должны увидеть страницу-заглушку Laravel:
Теперь сгенерируем систему аутентификации использую следующую команду:
php artisan make:auth
Хотя в этом уроке мы не будем вдаваться в систему аутентификации, стоит упомянуть, что эта команда создаст шаблоны и изменит роутинг. Сделаем это сразу, чтобы потом не переживать за вмешательство в наш код. Теперь когда все установлено и работает, приступим к коду.
Создаем список ссылок
Если держать в голове весь проект можно сойти с ума. Лучше разбить все на более мелкие задачи. Так что давайте начнем со списка ссылок.
Несмотря на то, что список ссылок кажется небольшой задачей она требует базу данных, таблицу в базе данных, данные в этой таблице, запрос к базе данных, и файл представления.
Первым шагом будет создание миграции. В этом нам поможет консольный инструмент artisan.
php artisan make:migration create_links_table --create=links
Теперь откройте файл, который создала команда. Он находится по следующему пути database/migrations/{{ДатаВремя}}_create_links_table.php
Внутри метода up добавьте столбцы таблицы
Schema::create('links', function (Blueprint $table) {
$table->increments('id');
$table->string('title');
$table->string('url’)->unique();
$table->text('description');
$table->timestamps();
});
Сохраните файл и запустите миграцию
php artisan migrate
Теперь надо добавить данные. В Laravel для этой цели есть две функции: заполнение начальными данными (seeding) и фабрики моделей.
Перед тем как продолжить процесс, самое время написать первый юнит-тест. Я предпочитаю делить тесты на две категории: функционал (features) и юниты (unit). Этот тест будет юнит-тестом, поэтому создаем файл ./tests/unit/SeederTest.php и добавляем тестирующий метод :
public function testLinksTable()
{
$this->seeInDatabase('links', ['title' => 'dotdev.co']);
}
Этот метод должен выдать ошибку. Запускаем - так и есть
… matches PCRE pattern "/dotdev.co/i" …
Стоп, мы не это вообще-то тестируем. При установке в Laravel уже есть один тестовый файл ExampleTest.php . Удалите его и запустите phpunit снова.
Теперь мы видим нашу настоящую ошибку
There was 1 failure:
1) SeederTest::testLinksTable Unable to find row in database table [links] that matched attributes [{"ti-tle":"dotdev.co"}]. Failed asserting that 0 is greater than 0.
Для того, чтобы этот тест прошел удачно, необходимо создать файл, заполняющий базу данных.
php artisan make:seeder LinksTableSeeder
Откройте DatabaseSeeder.php и добавьте следующее в метод run:
$this->call(LinksTableSeeder::class);
Чтобы тест прошел удачно мы могли бы просто добавить новую запись в LinksTableSeeder. Но, мы создадим фабрику модели сейчас, чтобы сэкономить время будущем, тк наши будущие тесты будут на нее завязаны. До того как создать фабрику, необходимо добавить саму модель.
php artisan make:model Link
Отредактируем созданную модель app/Link.php добавив имя таблицы в бд:
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Link extends Model
{
protected $table = 'links';
}
Теперь вернемся к ModelFactory.php и добавим наши ссылки:
$factory->define(App\Link::class, function (Faker\Generator $faker) {
return [
'title' => $faker->name,
'url' => $faker->url,
'description' => $faker->paragraph,
];
});
Если мы снова запустим сейчас phpunit, ошибка все еще будет, т.к. ссылки с названием “dotdev.co” в базе еще нет. В нашем SeederTest мы можем создать эту запись в бд с помощью той же фабрики моделей:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class SeederTest extends TestCase
{
public function testLinksTable()
{
factory(App\Link::class)->create([
'title' => 'dotdev.co',
]);
$this->seeInDatabase('links', ['title' => 'dotdev.co']);
}
}
Теперь, если выполнить phpunit все должно завершиться успешно.
Следующий шаг – собственно вывод самого списка ссылок. И само время написать новый тест.
Создаем новый файл ./tests/features/LinkTest.php. Спросим себя: что мы ожидаем увидеть? На странице списка ссылок мы можем найти известную нам ссылку, как мы делали выше, и подтвердить, что мы реально ее видим. Вот код такой проверки:
<?php
use Illuminate\Foundation\Testing\WithoutMiddleware;
use Illuminate\Foundation\Testing\DatabaseMigrations;
use Illuminate\Foundation\Testing\DatabaseTransactions;
class LinkTest extends TestCase
{
public function testWeSeeAListOfLinks()
{
factory(App\Link::class)->create([
'title' => 'dotdev.co',
]);
$this->visit('/')
->see('dotdev.co');
}
}
Phpunit снова выдает ошибку, что искомая строка не найдена. Откроем карту машрутов ./app/Http/routes.php и посмотрим куда указывает маршрут «/» .
Route::get('/', function () {
return view('welcome');
});
Давайте сделаем выборку наших ссылок и отправим их в представление.
Route::get('/', function () {
$links = \App\Link::all();
return view('welcome', compact('links'));
});
Отредактируем welcome.blade.php добавив простой цикл foreach:
@foreach ($links as $link)
<li>{{ $link->title }}</li>
@endforeach
Теперь phpunit позеленел. Тесты прошли успешно.
Мои поздравления! Первая функция реализована и покрыта тестами. Ничего не ломайте ;)