Может войдёшь?
Черновики Написать статью Профиль

Знакомимся с Laravel Orchid

laravel5 orchid

Для нашего любимого фреймворка существует с десяток различных админок и ещё больше генераторов, выбор может показаться настолько запутанным, что некоторые пишут исключительно свои решения. Я не работал со всеми и не могу утверждать, что какие то лучше/хуже, но могу рассказать об ORCHID и как с ней работать ~ за 10 минут.

Всегда начинайте с данных

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

Создадим новую модель "Проекты":

php artisan make:model Project -m

Используя флаг -m, будет создан файл нашей миграции

Добавим ей поле имя (уникальный идентификатор и время создания/обновления уже должны стоять по умолчанию)

namespace App;

use Illuminate\Database\Eloquent\Model;

class Project extends Model
{
    /**
     * @var array
     */
    protected $fillable = [
        'name'
    ];
}

Не забудем изменить и файл миграции:

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');
    }
}

Отлично, осталось только применить наши изменения к базе данных используя команду:

php artisan migrate

Добавим экран

На текущем этапе нам нужно лишь добавить простое действия, вроде создания, и отображения таблицы наших "Проектов" . Большинство решений предлагает создать единственный класс, в котором был бы описан весь CRUD, но ORCHID предлагает иной механиз - Экраны, где разработчик описывает то, что должно отображаться на странице в браузере.

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

php artisan orchid:screen ProjectListScreen

В директории app/Orchid/Screens будет создан новый класс ProjectListScreen, давай те разберём его:

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:


use App\Orchid\Screens\ProjectListScreen; $this->screen('projects', ProjectListScreen::class)->name('platform.projects');

Этим мы определим url адрес /dashboard/projects будет обрабатываться классом ProjectListScreen и иметь системное имя platform.projects

Посмотрим на результат в браузере:

1

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

Добавим вариант с отображением в виде строки, которая будет содержать простое поле для ввода:

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

Хоть поле и отображается оно ещё не несёт ни какого смысла без дополнительной обработки, так сделаем же её! Для этого добавим кнопку на командную строку и определим её событие:

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

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

php artisan orchid:table ProjectListTable

В директории app/Orchid/Layouts будет создан класс ProjectListTable со следующим содержанием:

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:

namespace App;

use Illuminate\Database\Eloquent\Model;
use Orchid\Platform\Traits\MultiLanguageTrait;

class Project extends Model
{
    use MultiLanguageTrait;
    /**
     * @var array
     */
    protected $fillable = [
        'name'
    ];
}

После этого вернемся к экрану и определим данные :

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 содержащий список проектов, который будет доступен во всех шаблонах и автоматически подставляться в поля/колонки и т.п.

Осталось только определить ключ и колонки в нашей таблице:

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

Одинокое поле рядом с таблице смотрится не лучшим образом, уберём её в модальное окно, для этого обернём наше поля для ввода и изменением кнопку следующим образом:

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

На этом наш экран почти готов, осталось позаботиться о выводе его в меню и хлебных крошках:

Для указания хлебных крошек отредактируем файл routes/breadcrumbs.php, добавив в самый конец:

// Platform -> Projects
Breadcrumbs::for('platform.projects', function ($trail) {
    $trail->parent('platform.index');
    $trail->push('Проекты');
});

6

А для указания в меню необходимо добавить добавить в класс композер /app/Orchid/Composers/MainMenuComposer.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


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

Как вы считаете, полезен ли этот материал? Да Нет

Комментарии (5)

Aleks777

Можно полный пример блога например )

Aleks777

Очень интересная система

leopoldus

материал полезный. рассмотрите тему ещё :)

Arams

в файле ProjectListScreen вместо

// use Orchid\Screen\Input;
// use Orchid\Screen\Layouts;
// use Orchid\Screen\Screen;

нужно использовать

use Orchid\Screen\Fields\Input;
use Orchid\Screen\Layouts;
use Orchid\Screen\Screen;

а в функции layout вместо

 InputField::make('project.name')
   ->type('text')
   ->title('Название проекта')

вот это

Input::make('project.name')
   ->type('text')
   ->title('Название проекта')

в рутах вместо

$this->screen('projects', ProjectListScreen::class)->name('platform.projects');

нужно использовать

$this->router->screen('projects', ProjectListScreen::class)->name('platform.projects');
Gamelot

для чего использовался в модели трейт MultiLanguageTrait для меня осталось загадкой!

Написать комментарий

Разметка: ? ?

Авторизуйся, чтобы прокомментировать.