Салют, хабровчане. Следующая статья была написана одним из наших постоянных читателей и определенно не претендует на звание хардкорного материала, но при этом вполне может послужить туториалом для новичка. Ждем в комментариях ваше мнение по статье, а за более хардкорными знаниями приглашаем на наш курс «Framework Laravel».

Всем привет! Сегодня, в столь «удаленное» для всех время работы, я бы хотел разобрать создание несложной todo, в которой можно создавать свои задачи. Звучит как то, что написано в официальной документации Laravel, и так оно и есть — я использую их todo в качестве базовой основы, немного его трансформирую, а основная часть моего рассказа будет про то, как же создавать роль администратора, исоздать очередной нелепый клон Trello.

Как я уже сказал, за основу мы возьмем следующий гайд. Он очень простой и больше концентрируется на работе с миграциями и с роутингом, чем на программировании контроллеров и моделей. К большому сожалению, его не обновляли с версии 5.1 и, если вы только начинаете программировать в Laravel на последней 7 версии (только 3 марта вышла, свеженькая)), роутинг вам придется писать не в

Так же я поменял фреймворк для верстки с bootstrap на bulma. Во-первых, мне он больше нравится, а вот вторых у меня уже была кодовая база blade шаблонов регистраций (хотя, с другой стороны, нарастить страницы регистраций и авторизаций очень просто, я покажу дальше, как).
Эту версию проекта можно скачать здесь в ветке мастер (а в ветке new вы можете скачать готовое приложение). Активировать вы её сможете с помощью следующих команд, при условии, что у вас уже установлен composer и laravel:
Авторизации «из коробки» поменялись с 6 версии. Теперь для быстрого создания нужно поставить пакет, который может вам быстро сгенерировать контроллеры и blade — шаблоны:
В вашем проекте должно появиться несколько новых файлов:
в папке resourses появится подпапка auth, в которой будут файлы blade шаблонов, посвященные авторизации, паролям. Изначально blade-шаблоны сверстаны в bootstrap, однако я их немного трансформировал в bulma, чтобы соблюсти общность css-фрейворка в проекте. Однако, чтобы удобно было пользоваться веб-сайтом, нам потребуется панель навигации. В resources я создал папку includes, в которой разместил вспомогательные файлы — header и nav. Чтобы не занимать много места, скажу, что в header у меня была только head с подключением bulma, а в
Пора уже и обсудить структуру нашего проекта. Потом читатель сможет трансформировать приложение под свои нужды, но сейчас, допустим, я хочу, чтобы в приложении был один администратор (допустим, проджект-менеджер), который может ставить и удалять задачи, и какая-то команда, которая может эти команды видеть. Конечно, было бы уже совсем неплохо, если бы кто-то мог брать задачи и обозначать, что именно он их выполняет, но об этом как-нибудь потом.
Окей, значит у нас будет две группы юзеров и условимся, что увидеть нашу доску задач смогут только авторизованные юзеры, которым дали доступ, а добавлять задачи — некоторые суперадмины. Давайте приступим.
Для небольшого упрощения я решил разбить приложение на две страницы: одну, на которой у нас будет только задачи без возможности редактирования, и вторую, которая будет доступна только суперадмину. Доступную команде страницу я решил назвать
Эта страница выводит только список задач. Для ее отображения я добавлю новый путь в web.php:
Шаблон, в котором у нас тот же список, но с возможностью редактирования и добавления, называется
И этот шаблон, как и оригинальном туториале, расширяется в
Отлично! С внешним видом мы определились, теперь можно переходить к роутингу и созданию наших
Для начала зайдем в модель Users и добавим новые типы пользователей:
Далее заходим в последнюю миграцию таблицы users (папка database/migrations) и добавляем колонку с нашим новым типом данных:
Дальше проходим в
Окей, дальше нам нужно создать нашу middleware для админа. Проще всего это осуществить с помощью следующей команды:
Надеюсь, у вас все получилось. В папке
Дальше нам нужно зарегистрировать наш middleware в
Трансформируем путь dash в
Осталось создать кастомный контролер для нашего администратора:
Редактируем:
Чтобы у вас все с регистрацией заработало конкретно, нужно не забыть поправить редирект в
Теперь администратор у нас может появится только с помощью нашего помощника в терминале tinker:
На этом все. Если вы хотите попробовать готовое приложение, повторю ссылку Конечно, наше приложение прямо сейчас нельзя использовать в продакшене, потому что ваши задачи сможет увидеть каждый, кто зарегистрировался на ресурсе. Но как вы будете ограничивать доступ?
Возможно, у вас есть корпоративная почта, и тогда вы сможете ограничивать доступ в команду с помощью регулярок в валидизации почты. Или вы сможете добавить проверку на членство в команде точно так же, как админа, проделав схожие манипуляции. По традиции, приведу несколько полезный ссылок, для тех, кто только собирается начать осваивать Laravel:
→ Чуть более подробная статья, чем в документации, о миграциях в Laravel
→ Неплохая статья на Medium про роли в Laravel
→ Что у нас свеженького в Laravel 7
Разворот приложений и непрерывный деплой «без боли» с помощью Forge/Envoyer.

Всем привет! Сегодня, в столь «удаленное» для всех время работы, я бы хотел разобрать создание несложной todo, в которой можно создавать свои задачи. Звучит как то, что написано в официальной документации Laravel, и так оно и есть — я использую их todo в качестве базовой основы, немного его трансформирую, а основная часть моего рассказа будет про то, как же создавать роль администратора, и
Создаем основание

Как я уже сказал, за основу мы возьмем следующий гайд. Он очень простой и больше концентрируется на работе с миграциями и с роутингом, чем на программировании контроллеров и моделей. К большому сожалению, его не обновляли с версии 5.1 и, если вы только начинаете программировать в Laravel на последней 7 версии (только 3 марта вышла, свеженькая)), роутинг вам придется писать не в
app/Http/routes.php, а в routes/web.php (это правда уже с 6 версии поменялось), и в общем на этом вся разница заканчивается. В итоге, у вас должно получится что-то такое:
Так же я поменял фреймворк для верстки с bootstrap на bulma. Во-первых, мне он больше нравится, а вот вторых у меня уже была кодовая база blade шаблонов регистраций (хотя, с другой стороны, нарастить страницы регистраций и авторизаций очень просто, я покажу дальше, как).
Эту версию проекта можно скачать здесь в ветке мастер (а в ветке new вы можете скачать готовое приложение). Активировать вы её сможете с помощью следующих команд, при условии, что у вас уже установлен composer и laravel:
composer install // создаете файл .env, копируете в него .env example, настраиваетесь под вашу базу данных php artisan key:generate //устанавливаете ключ безопасности php artisan serve //запускаете приложение
Создаем авторизацию и регистрацию
Авторизации «из коробки» поменялись с 6 версии. Теперь для быстрого создания нужно поставить пакет, который может вам быстро сгенерировать контроллеры и blade — шаблоны:
composer install laravel/ui php artisan ui vue --auth
В вашем проекте должно появиться несколько новых файлов:
в папке resourses появится подпапка auth, в которой будут файлы blade шаблонов, посвященные авторизации, паролям. Изначально blade-шаблоны сверстаны в bootstrap, однако я их немного трансформировал в bulma, чтобы соблюсти общность css-фрейворка в проекте. Однако, чтобы удобно было пользоваться веб-сайтом, нам потребуется панель навигации. В resources я создал папку includes, в которой разместил вспомогательные файлы — header и nav. Чтобы не занимать много места, скажу, что в header у меня была только head с подключением bulma, а в
nav.blade.php было следующее:<nav class="navbar has-background-black-ter" role="navigation" aria-label="main navigation"> <div class="navbar-brand"> <a class="navbar-item has-text-white is-size-4" href="/"> TODO </a> <a role="button" class="navbar-burger" aria-label="menu" aria-expanded="false"> <span aria-hidden="true"></span> <span aria-hidden="true"></span> <span aria-hidden="true"></span> </a> </div> <div class="navbar-menu"> <div class="navbar-start"> @if (Auth::check()) <button type="button" class="button is-primary"> <!-- если пользователь зарегистрирован, тогда ->отобразить его ник --> {{{ Auth::user()->name}}} </button> @else <!-- в другом случае --> <a class="navbar-item has-text-danger" href="{{route('register')}}">Регистрация</a> <a class="navbar-item has-text-danger" href="{{route('login')}}">Войти</a> @endif @if (Auth::check()) <!-- если зарегистрирован, тогда нам нужно показать как выйти --> <!-- это можно сделать через форму --> <a class="navbar-item has-text-danger" href="{{url('/logout') }}" onclick="event.preventDefault(); document.getElementById('logout-form').submit();"> Выйти </a> <form id="logout-form" action="{{ url('/logout') }}" method="POST" style="display: none;"> {{ csrf_field() }} </form> @endif </ul> </div> <div class="navbar-end"> <!-- navbar items --> </div> </div> </nav>
Начинаем создавать нашу архитектуру
Пора уже и обсудить структуру нашего проекта. Потом читатель сможет трансформировать приложение под свои нужды, но сейчас, допустим, я хочу, чтобы в приложении был один администратор (допустим, проджект-менеджер), который может ставить и удалять задачи, и какая-то команда, которая может эти команды видеть. Конечно, было бы уже совсем неплохо, если бы кто-то мог брать задачи и обозначать, что именно он их выполняет, но об этом как-нибудь потом.
Окей, значит у нас будет две группы юзеров и условимся, что увидеть нашу доску задач смогут только авторизованные юзеры, которым дали доступ, а добавлять задачи — некоторые суперадмины. Давайте приступим.
Для небольшого упрощения я решил разбить приложение на две страницы: одну, на которой у нас будет только задачи без возможности редактирования, и вторую, которая будет доступна только суперадмину. Доступную команде страницу я решил назвать
welcome.blade.php:@include('includes.header') <body> @include('includes.nav') <div class="columns is-centered"> <div class="column is-half"> <div class="panel"> <div class="panel-heading"> Текущие задачи </div> <div class="panel-body"> @foreach ($tasks as $task) <a class="panel-block"> <button class="button is-rounded"> <span>{{ $task->name }}</span> </button> @endforeach </div> </div> </div> </div> <body> </html>
Эта страница выводит только список задач. Для ее отображения я добавлю новый путь в web.php:
Route::get('/', function () { return view('welcome', [ 'tasks' => Task::orderBy('created_at', 'asc')->get(), ]); });
Шаблон, в котором у нас тот же список, но с возможностью редактирования и добавления, называется
task.blade.php. Он слишком велик, поэтому я размещу его под спойлером:task.blade.php
@extends('layouts.app') @section('content') <div class="columns is-centered"> <div class="column is-half"> <div class="panel"> <div class="panel-heading"> Новое дело </div> <div class="panel-block"> @include('common.errors') <!-- Форма для создания тасков --> <form action="{{ url('task')}}" method="POST"> {{ csrf_field() }} <div class="field"> <label for="task-name" class="label is-medium">Дело</label> <input type=" text" name="name" id="task-name" class="input is-medium" value="{{ old('task') }}"> </div> <div class="field"> <button type="submit" class="button is-success"> <span class="icon"> <i class="fa fa-btn fa-plus"> </span></i> <span>Добавить дело</span> </button> </div> </form> </div> </div> <!-- Current Tasks --> @if (count($tasks) > 0) <div class="panel"> <div class="panel-heading"> Текущие задачи </div> <div class="panel-body"> {{-- <table class="table table-striped task-table"> <thead> <th>Дело</th> <th> </th> </thead> <tbody> --}} @foreach ($tasks as $task) <a class="panel-block"> <button class="button is-rounded"> <span>{{ $task->name }}</span> </button> <form action="{{ url('task/'.$task->id) }}" method="POST"> {{ csrf_field() }} {{ method_field('DELETE') }} <button type="submit" class="button is-danger"> <span class="icon is-small"> <i class="fa fa-btn fa-trash"></i></span> <span> Удалить </span> </button> </form> </a> @endforeach </div> </div> @endif </div> </div> @endsection
И этот шаблон, как и оригинальном туториале, расширяется в
app/layouts.blade.php:@include('includes.header') <body> @include('includes.nav') @yield('content') </body> </html>
Отлично! С внешним видом мы определились, теперь можно переходить к роутингу и созданию наших
middlewares.Для начала зайдем в модель Users и добавим новые типы пользователей:
const ADMIN_TYPE = 'admin'; const TEAM_TYPE = 'team'; #и добавляем в самый конец класса функцию проверки: public function isAdmin(){ return $this->type === self::ADMIN_TYPE; // требуем доложить тип пользователя }
Далее заходим в последнюю миграцию таблицы users (папка database/migrations) и добавляем колонку с нашим новым типом данных:
$table->string('type')->default('team'); // пока предполагаем, что кроме команды у нас сервисе больше никого нету
Дальше проходим в
app/Http/Controllers/Auth/RegisterController.php и немного редактируем функцию create (она тоже в версии 5 выглядела немного по другому):protected function create(array $data) { return User::create([ 'name' => $data['name'], 'email' => $data['email'], 'password' => Hash::make($data['password']), 'type' => User::TEAM_TYPE, ]); }
Окей, дальше нам нужно создать нашу middleware для админа. Проще всего это осуществить с помощью следующей команды:
php artisan make:middleware IsAdmin
Надеюсь, у вас все получилось. В папке
HTTP/middleware у вас должен был появится isAdmin.php, в которой функцию handle нужно отредактировать следующим образом:public function handle($request, Closure $next) { if(auth()->user()->isAdmin()) { return $next($request); // если пользовать админа, пропускаем. Если нет - тогда отправляем домой } return redirect('/'); }
Дальше нам нужно зарегистрировать наш middleware в
app/HTTP/Kernel, чтобы им можно было воспользоваться:protected $routeMiddleware = [ #множество других мидлевеиров, не так важных для этой истории is_admin' => \App\Http\Middleware\IsAdmin::class, ];
Трансформируем путь dash в
web.php, который должен иметь возможность видеть только суперадмин:Route::get('/dash', function () { return view('tasks', [ 'tasks' => Task::orderBy('created_at', 'asc')->get(), ]); }) ->middleware('is_admin') ->name('admin'); # не забываем добавить авторизацию и возможность разлогироваться Auth::routes(); Route::post('/logout', 'Auth\LoginController@logout')->name('logout');
Осталось создать кастомный контролер для нашего администратора:
php artisan make:controller AdminController
Редактируем:
public function __construct() { $this->middleware('auth'); } public function admin() { return view('admin'); }
Чтобы у вас все с регистрацией заработало конкретно, нужно не забыть поправить редирект в
RouteServiceProvider.php в app/HTTP/Providers, потому он изначально рассчитан на шаблон home:public const HOME = '/';
Теперь администратор у нас может появится только с помощью нашего помощника в терминале tinker:
php artisan tinker use App\User; User::where('email', 'admin@mail.com')->update(['type' => 'admin']); //даем нашем пользователю права админа
На этом все. Если вы хотите попробовать готовое приложение, повторю ссылку Конечно, наше приложение прямо сейчас нельзя использовать в продакшене, потому что ваши задачи сможет увидеть каждый, кто зарегистрировался на ресурсе. Но как вы будете ограничивать доступ?
Возможно, у вас есть корпоративная почта, и тогда вы сможете ограничивать доступ в команду с помощью регулярок в валидизации почты. Или вы сможете добавить проверку на членство в команде точно так же, как админа, проделав схожие манипуляции. По традиции, приведу несколько полезный ссылок, для тех, кто только собирается начать осваивать Laravel:
→ Чуть более подробная статья, чем в документации, о миграциях в Laravel
→ Неплохая статья на Medium про роли в Laravel
→ Что у нас свеженького в Laravel 7
Разворот приложений и непрерывный деплой «без боли» с помощью Forge/Envoyer.
