Для нашего любимого фреймворка существует с десяток различных админок и ещё больше генераторов, выбор может показаться настолько запутанным, что некоторые пишут исключительно свои решения. Я не работал со всеми и не могу утверждать, что какие то лучше/хуже, но могу рассказать об ORCHID и как с ней работать ~ за 10 минут. ## Всегда начинайте с данных Буду надеяться, что вы уже установили фреймворк и [платформу](https://orchid.software/ru/docs/installation), создали базу данных и даже запустили веб-сервер. Очевидным продолжением будет написание моделей и миграций для вашей базы данных. Создадим новую модель "Проекты": ```php php artisan make:model Project -m ``` > Используя флаг `-m`, будет создан файл нашей миграции Добавим ей поле имя (уникальный идентификатор и время создания/обновления уже должны стоять по умолчанию) ```php namespace App; use Illuminate\Database\Eloquent\Model; class Project extends Model { /** * @var array */ protected $fillable = [ 'name' ]; } ``` Не забудем изменить и файл миграции: ```php use Illuminate\Support\Facades\Schema; use Illuminate\Database\Schema\Blueprint; use Illuminate\Database\Migrations\Migration; class CreateProjectsTable extends Migration { /** * Run the migrations. * * @return void */ public function up() { Schema::create('projects', function (Blueprint $table) { $table->increments('id'); $table->string('name'); $table->timestamps(); }); } /** * Reverse the migrations. * * @return void */ public function down() { Schema::dropIfExists('projects'); } } ``` Отлично, осталось только применить наши изменения к базе данных используя команду: ```bash php artisan migrate ``` ## Добавим экран На текущем этапе нам нужно лишь добавить простое действия, вроде создания, и отображения таблицы наших "Проектов" . Большинство решений предлагает создать единственный класс, в котором был бы описан весь CRUD, но ORCHID предлагает иной механиз - Экраны, где разработчик описывает то, что должно отображаться на странице в браузере. Создадим свой собственный экран для отображения списка, для этого выполним команду: ```php php artisan orchid:screen ProjectListScreen ``` В директории `app/Orchid/Screens` будет создан новый класс `ProjectListScreen`, давай те разберём его: ```php namespace App\Orchid\Screens; use Orchid\Screen\Screen; class ProjectListScreen extends Screen { /** * Свойства имя и описание отвечают за то, * какое название будет отображаться * на экране пользователя и заголовках. */ public $name = 'ProjectListScreen'; public $description = 'ProjectListScreen'; /** * Метод определяющие все входные данные экрана, * именно в нём должны вызываться запросы к базе данных, * api или любые другие (не обязательно явно), * результатом которого должен быть массив, * обращение к которым будут использоваться его ключи. */ public function query(): array { return []; } /** * Определяет управляющие кнопки и события * которые должны будут произойти по нажатию */ public function commandBar(): array { return []; } /** * Набор отображений, * строк, таблицы, графиков, * модальных окон и их комбинация */ public function layout(): array { return []; } } ``` Главным отличием экрана от контроллера, является определённая заранее структура, которая обслуживает *только одну страницу* определяя данные и события. Как и контроллер, экран нужно регистрировать в файле маршрутов, определим его в файле для панели администрирования `routes/platform.php`: ```php use App\Orchid\Screens\ProjectListScreen; $this->screen('projects', ProjectListScreen::class)->name('platform.projects'); ``` Этим мы определим url адрес `/dashboard/projects` будет обрабатываться классом `ProjectListScreen` и иметь системное имя `platform.projects` Посмотрим на результат в браузере: ![1](https://user-images.githubusercontent.com/5102591/51277635-3ba11e80-19e9-11e9-9bfd-c958ed71feca.png) Видим только указанные свойства нашего класса, добавим возможность с создания "Проектов", для этого определим поле ввода и метод сохранения, основная визуальная составляющая описывается в виде классов `Layouts`, это могут быть таблицы, строки, метрики и т.п. Добавим вариант с отображением в виде строки, которая будет содержать простое поле для ввода: ```php namespace App\Orchid\Screens; use Orchid\Screen\Fields\InputField; use Orchid\Screen\Layouts; use Orchid\Screen\Screen; class ProjectListScreen extends Screen { /** * Свойста имя и описание отвечают за то, * какое название будет отображаться * на экране пользователя и заголовках. */ public $name = 'ProjectListScreen'; /** * @var string */ public $description = 'ProjectListScreen'; /** * Метод определяющие все входные данные экрана, * именно в нём должны вызываться запросы к базе данных, * api или любые другие (не обязательно явно), * результатом которого должен быть массив, * обращение к которым будут использоваться его ключи. */ public function query(): array { return []; } /** * Определяет управляющие кнопки и события * которые должны будут произойти по нажатию */ public function commandBar(): array { return []; } /** * Набор отображений, * строк, таблицы, графиков, * модальных окон и их комбинация */ public function layout(): array { return [ Layouts::rows([ InputField::make('project.name') ->type('text') ->title('Название проекта') ]), ]; } } ``` Обновим страницу и удостоверимся, что поле действительно отображается на экране. ![2](https://user-images.githubusercontent.com/5102591/51277644-478ce080-19e9-11e9-880d-f6cdbbed6c00.png) Хоть поле и отображается оно ещё не несёт ни какого смысла без дополнительной обработки, так сделаем же её! Для этого добавим кнопку на командную строку и определим её событие: ```php namespace App\Orchid\Screens; use App\Project; use Illuminate\Http\Request; use Orchid\Screen\Fields\InputField; use Orchid\Screen\Layouts; use Orchid\Screen\Link; use Orchid\Screen\Screen; use Orchid\Support\Facades\Alert; class ProjectListScreen extends Screen { /** * Свойства имя и описание отвечают за то, * какое название будет отображаться * на экране пользователя и заголовках. */ public $name = 'ProjectListScreen'; /** * @var string */ public $description = 'ProjectListScreen'; /** * Метод определяющие все входные данные экрана, * именно в нём должны вызываться запросы к базе данных, * api или любые другие (не обязательно явно), * результатом которого должен быть массив, * обращение к которым будут использоваться его ключи. */ public function query(): array { return []; } /** * Определяет управляющие кнопки и события * которые должны будут произойти по нажатию */ public function commandBar(): array { return [ Link::name('Добавить проект') ->method('createProject'), ]; } /** * Набор отображений, * строк, таблицы, графиков, * модальных окон и их комбинация */ public function layout(): array { return [ Layouts::rows([ InputField::make('project.name') ->type('text') ->title('Название проекта') ]), ]; } /** * @param Request $request * @return \Illuminate\Http\RedirectResponse */ public function createProject(Request $request) { Project::create($request->get('project')); Alert::success('Проект был успешно создан'); return back(); } } ``` На экране будет отображена новая кнопка "Добавить проект", по нажатию на которой будет выполнен метод `createProject`. ![3](https://user-images.githubusercontent.com/5102591/51277666-5378a280-19e9-11e9-994f-b187654a13ff.png) Отлично, но этого явно не достаточно для полноценной работы, так как мы невидим уже созданные проекты, добавим их список к экрану, для этого создадим новый `Layout` типа таблицы используя команду: ```bash php artisan orchid:table ProjectListTable ``` В директории `app/Orchid/Layouts` будет создан класс `ProjectListTable` со следующим содержанием: ```php namespace App\Orchid\Layouts; use Orchid\Screen\Layouts\Table; class ProjectListTable extends Table { /** * Источник данных * * @var string */ public $data = ''; /** * Поля которые будут отображаться ввиде колонок * * @return array */ public function fields(): array { return []; } } ``` Нам необходимо определить его в экране и передать ему данные, что бы максимально использовать возможности вернёмся к модели `Project` и дополним её трейтом `MultiLanguageTrait`: ```php namespace App; use Illuminate\Database\Eloquent\Model; use Orchid\Platform\Traits\MultiLanguageTrait; class Project extends Model { use MultiLanguageTrait; /** * @var array */ protected $fillable = [ 'name' ]; } ``` После этого вернемся к экрану и определим данные : ```php namespace App\Orchid\Screens; use App\Orchid\Layouts\ProjectListTable; use App\Project; use Illuminate\Http\Request; use Orchid\Screen\Fields\InputField; use Orchid\Screen\Layouts; use Orchid\Screen\Link; use Orchid\Screen\Screen; use Orchid\Support\Facades\Alert; class ProjectListScreen extends Screen { /** * Свойства имя и описание отвечают за то, * какое название будет отображаться * на экране пользователя и заголовках. */ public $name = 'ProjectListScreen'; /** * @var string */ public $description = 'ProjectListScreen'; /** * Метод определяющие все входные данные экрана, * именно в нём должны вызываться запросы к базе данных, * api или любые другие (не обязательно явно), * результатом которого должен быть массив, * обращение к которым будут использоваться его ключи. */ public function query(): array { $projects = Project::paginate(); return [ 'projects' => $projects ]; } /** * Определяет управляющие кнопки и события * которые должны будут произойти по нажатию */ public function commandBar(): array { return [ Link::name('Добавить проект') ->method('createProject'), ]; } /** * Набор отображений, * строк, таблицы, графиков, * модальных окон и их комбинация */ public function layout(): array { return [ Layouts::rows([ InputField::make('project.name') ->required() ->type('text') ->title('Название проекта') ]), ProjectListTable::class, ]; } /** * @param Request $request * @return \Illuminate\Http\RedirectResponse */ public function createProject(Request $request) { Project::create($request->get('project')); Alert::success('Проект был успешно создан'); return back(); } } ``` В методе `query` определил ключ `projects` содержащий список проектов, который будет доступен во всех шаблонах и автоматически подставляться в поля/колонки и т.п. Осталось только определить `ключ` и колонки в нашей таблице: ```php namespace App\Orchid\Layouts; use Orchid\Screen\Layouts\Table; use Orchid\Screen\TD; class ProjectListTable extends Table { /** * @var string */ public $data = 'projects'; /** * @return array */ public function fields(): array { return [ TD::set('name','Имя проекта'), TD::set('created_at','Дата создания'), TD::set('updated_at','Дата обновления') ]; } } ``` Обновим страницу и посмотрим на результат. ![4](https://user-images.githubusercontent.com/5102591/51277799-b702d000-19e9-11e9-9673-4fab6d5adb8c.png) Одинокое поле рядом с таблице смотрится не лучшим образом, уберём её в модальное окно, для этого обернём наше поля для ввода и изменением кнопку следующим образом: ```php namespace App\Orchid\Screens; use App\Orchid\Layouts\ProjectListTable; use App\Project; use Illuminate\Http\Request; use Orchid\Screen\Fields\InputField; use Orchid\Screen\Layouts; use Orchid\Screen\Link; use Orchid\Screen\Screen; use Orchid\Support\Facades\Alert; class ProjectListScreen extends Screen { /** * Свойста имя и описание отвечают за то, * какое название будет отображаться * на экране пользователя и заголовках. */ public $name = 'ProjectListScreen'; /** * @var string */ public $description = 'ProjectListScreen'; /** * Метод определяющие все входные данные экрана, * именно в нём должны вызываться запросы к базе данных, * api или любые другие (не обязательно явно), * результатом которого должен быть массив, * обращение к которым будут использоваться его ключи. */ public function query(): array { $projects = Project::paginate(); return [ 'projects' => $projects ]; } /** * Определяет управляющие кнопки и события * которые должны будут произойти по нажатию */ public function commandBar(): array { return [ Link::name('Добавить проект') ->title('Добавить проект') ->modal('createProjectModal') ->method('createProject'), ]; } /** * Набор отображений, * строк, таблицы, графиков, * модальных окон и их комбинация */ public function layout(): array { return [ Layouts::modals([ 'createProjectModal' => Layouts::rows([ InputField::make('project.name') ->required() ->type('text') ->title('Название проекта') ]), ]), ProjectListTable::class, ]; } /** * @param Request $request * @return \Illuminate\Http\RedirectResponse */ public function createProject(Request $request) { Project::create($request->get('project')); Alert::success('Проект был успешно создан'); return back(); } } ``` ![5](https://user-images.githubusercontent.com/5102591/51277811-c3872880-19e9-11e9-8620-c4f82316fb74.png) На этом наш экран почти готов, осталось позаботиться о выводе его в меню и хлебных крошках: Для указания хлебных крошек отредактируем файл `routes/breadcrumbs.php`, добавив в самый конец: ```php // Platform -> Projects Breadcrumbs::for('platform.projects', function ($trail) { $trail->parent('platform.index'); $trail->push('Проекты'); }); ``` ![6](https://user-images.githubusercontent.com/5102591/51277825-cf72ea80-19e9-11e9-8336-5031add01d35.png) А для указания в меню необходимо добавить добавить в класс композер `/app/Orchid/Composers/MainMenuComposer.php` ```php namespace App\Orchid\Composers; use Orchid\Platform\ItemMenu; use Orchid\Platform\Dashboard; class MainMenuComposer { /** * @var Dashboard */ private $dashboard; /** * MenuComposer constructor. * * @param Dashboard $dashboard */ public function __construct(Dashboard $dashboard) { $this->dashboard = $dashboard; } /** * Registering the main menu items. */ public function compose() { // Main $this->dashboard->menu ->add('Main', ItemMenu::setLabel('Проекты') ->setIcon('icon-folder') ->setRoute(route('platform.projects')) ->setGroupName('Управление') ); } } ``` Обновим страницу и посмотрим на результат. ![7](https://user-images.githubusercontent.com/5102591/51277829-d39f0800-19e9-11e9-8e0c-9bb68b783157.png) -------- Этот минимальный пример даёт понять написание кода с использованием пакета и если вам понравился материал, изложение, дайте обратную связь и мы рассмотрим эту тему более углубленно.