Erros do painel do administrador ou experiência em desenvolvimento do Laravel Orchid


No passado, o artigo "Orchid CMS - outro CMS no Laravel" foi publicado na Habré, e agora, após dois anos e mais de 100 lançamentos, tentaremos analisar os erros e problemas que estavam no caminho do desenvolvimento.


1. Posicionamento


O título do artigo anterior e muitos outros indicaram a abreviatura CMS, que em sonhos úmidos era para atrair mais interesse no desenvolvimento. Ao mesmo tempo, o pacote não ofereceu soluções prontas na replicação de sites, mas apenas gerenciamento na administração.


No final, foi apenas pior ... Essa combinação em si repelia usuários experientes a instalar, e os iniciantes esperavam ver suas habilidades habituais, em vez de alguma liberdade.


2. Formulários


Quando se trata de painéis de administração, a primeira coisa que importa é a forma e como trabalhar com eles. Por exemplo, consideraremos um formulário construído em modelos de blade , que exibe e permite editar os dados de algum objeto:


 <form action="..."> <input type="text" name="title"> <input type="text" name="price"> <input type="submit" value=""> </form> 

Gerentes, editores e usuários como um todo desejam ver o máximo possível sobre o objeto de edição e não há problema se todas as informações puderem ser obtidas de uma tabela, mas quando as informações são muito ampliadas?


A solução mais popular que vi foi simplesmente dividir o formulário em várias classes e arquivos de apresentação. Eles foram exibidos como guias no formulário, informações nas quais seriam agrupadas por relacionamento:


 <form action="..." id="main"> <input type="text" name="title"> <input type="text" name="price"> <input type="submit" value=""> </form> <form action="..." id="editors"> <!--    --> <input type="submit" value=""> </form> <form action="..." id="history"> <!--   --> <input type="submit" value=""> </form> 

Foi exatamente isso que foi reproduzido ... É claro que com pequenas mudanças e características, mas o significado permaneceu o mesmo. Ao criar uma classe separada, agrupe todo o processamento na forma de outras formas:



Sobrepondo os exemplos anteriores, no código, cada formulário parecia aproximadamente da seguinte maneira:


 class Example extends Form { public $name = 'General'; public function rules(): array { return [ 'title' => 'required|max:160' ]; } public function display(): View { return view('main'); } public function persist(Model $model) { //.. return $model->save(); } } 

E a formação no controlador de todo o grupo:


 class ExampleController extends Controller { public function index(Model $model) { $form = new FormGroup([ Example::class // editors.. // history.. ]); return $form->render($model); } } 

Além de separar o formulário em si e a pequena organização do código, isso não trouxe outros resultados. Em resumo:


  • Este método não ajudou em nada a resolver a duplicação de vários elementos, por exemplo, o campo "Título" de um objeto pode ocorrer várias vezes, mas nunca uma cópia completa do formulário.
  • Com ações diferentes das "padrão", foi necessário criar um método controlador separado, que estragou completamente todo o ponto de dividir a forma.
  • Tampouco há vantagens em automatizar a construção de uma exibição; você ainda precisa especificá-la manualmente.

3. CRUD


A opção mais controversa, que muitas vezes aparece em feeds de notícias e desenvolvedores de blogs. Essa abordagem é usada por quase todos os pacotes alternativos e foi feita. Seguindo o exemplo de um sistema conhecido em que tudo é armazenado em uma tabela, um modelo foi criado com um campo JSON dinâmico:



Em uma classe separada, foram descritos os campos necessários para criação e edição, além de ações básicas:


 class Example extends Behavior { public $name = 'Main'; public function rules(): array { return [ 'title' => 'required|max:160' ]; } public function fields(): array { return [ Input::make('title') ->type('text') ->max(160) ->required(), ]; } } 

Graças a essa abordagem, escrever o código mais simples foi rápido devido à completa falta de trabalho com a apresentação, mas trouxe alguns problemas:


  • Operações personalizadas não estão disponíveis dentro da instalação.
  • Uma exibição dinâmica, como janelas modais com informações de carregamento, não está disponível.
  • No menor desvio, por exemplo, gráficos, voltamos a escrever modelos de blade com estilos e scripts.
  • Incapacidade de usar dados de outras fontes que não o banco de dados.
  • Trabalhar apenas dentro da estrutura de uma tabela, isso poderia ser corrigido, mas na primeira e na última implementação foi.

Correção


A versão CRUD foi baseada na apresentação totalmente automatizada, o que levou a uma nova implementação. Dessa vez, um produto do Visual Studio LightSwitch foi adotado como padrão, o que permitiu às pessoas usá-lo sem um profundo conhecimento de desenvolvimento.


Naturalmente, não precisamos desse efeito e esse nem é o objetivo, enquanto quase todas as capacidades técnicas estavam presentes no Laravel ou nas implementações de usuários.
Decidiu-se focar em apenas um único aspecto - Telas.



A tela é tudo o que o usuário vê na página e quais ações ele pode executar.
Tudo isso é descrito em uma classe, ele não sabe de onde vêm os dados, pode ser: um banco de dados, API ou qualquer outra fonte externa. O design da aparência é baseado em camadas e tudo o que era necessário era determinar quais dados serão mostrados em um modelo específico.


Uma camada pode ter um determinado layout, que pode ser uma tabela, linha, gráfico etc. Além disso, cada layout pode incluir um layout diferente, ou seja, aninhamento. Por exemplo, a tela é dividida em duas colunas, no campo esquerdo para preencher, à direita, uma tabela e gráfico de pesquisa, etc.


Para controlar os dados exibidos na tela, são fornecidos comandos que cuidam do processamento.


 class ExampleScreen extends Screen { public $name = 'Example Screen'; public function query(Model $model): array { return [ 'model' => $model ]; } public function commandBar(): array { return [ Link::make('-') ->link('http://orchid.software/ru') ->icon('icon-globe-alt'), ]; } public function layout(): array { return [ Layout::rows([ Input::make('model.title') ->type('text') ->max(160) ->required(), ]) ]; } } 

A parada ocorreu nesta opção, pois mantém um equilíbrio saudável entre gravação completa e geração automática, mantendo-se compreensível.

Source: https://habr.com/ru/post/pt460471/


All Articles