Logotipo WebingPro.
Menu
Background Image
Voltar para a página anterior

Bem vindo ao Magic!
Parte 1 – Introdução

Postado por Gabriel Felipe em 05/11/2014 às 01:11

Background Image

Já imaginou um framework que pensasse no desenvolvimento web como um todo? Levando em consideração o front e o backend? Esse é o Magic! Hoje vou lhes apresentar essa ferramenta desenvolvida e mantida pela WebingPro.

Magic, um projeto desenvolvido no labs da WebingPro

Algumas coisas que precisamos entender sobre o framework:

MVC

Model-view-controller ou model-visão-controlador é um padrão de projetos. Nele, separamos o projeto em 3 partes principais.

  1. O modelo é responsável por todos os dados e regras de negócio, sendo, por exemplo, responsável pelas interações com bancos de dados.
  2. As visões são as saídas de dados, podendo  por exemplo ser os templates que o usuário vê, ou os json’s de saída de uma api.
  3. O controlador é o que controla, ou seja ele recebe a requisição executa alguma lógica baseada nela, consulta os dados ou regras de negócios nos modelos envolvidos nessa requisição e escolhe uma visão para usar como retorno para a requisição.

Para tentar ficar mais claro vamos fazer uma comparação com o café nosso de cada dia.

  1. O modelo seria a plantação, onde o café nasce, afinal o café seria como um registro no nosso banco de dados, é a base do negócio.
  2. A visão seria embalagem onde compramos, ela pode variar entre saco ou caixa mas o conteúdo é o mesmo.
  3. O controlador seria a fábrica onde o café, colhido na plantação, é tratado para ser enviado para a caixa. Diferentes controladores podem obter diferentes resultados a partir do mesmo modelo e visão, por exemplo: Considere o modelo café e a visão saco. Enquanto um controlador pode preparar esse café para ser enviado para o saco como café instantâneo, outro pode preparar diferente e enviar como café convencional.

Mas não vou me estender muito no conceito de MVC, caso você queira saber mais a respeito pode clicar aqui e aqui, são ótimos artigos a respeito. =)

Escopos

Magic considera que um mesmo projeto pode conter vários “subprojetos”  ou “partes”. Cada uma dessas “partes” do projeto é um escopo, por exemplo:  o site é o escopo público, enquanto o CMS é o escopo administrativo.

Quando você baixa ele pela primeira vez, ele vem com um escopo pré-configurado, o “manager”. Nele você encontrará alguns geradores de código e outros facilitadores, mas isso veremos mais para frente.  Por hora basta entender que um escopo é um subprojeto do projeto e que cada um desses subprojetos possui uma estrutura MVC.

A requisição

Toda requisição ao Magic é feita ao index.php acompanhada de dois parametros: route e scope. O primeiro indica qual método de qual controller irá ser responsável por essa requisição, enquanto o segundo indica em qual escopo o sistema deve procurar esse controller. Abaixo podemos ver uma imagem que ilustra o modo como as rotas são definidas.

Exemplode rotas

Agora que sabemos o básico sobre o funcionamento do Magic, vamos ao que interessa:

Os diferenciais no Frontend

Apesar do Magic ser escrito em PHP, as minhas funcionalidades preferidas dele estão no frontend, principalmente no css.

Ta mas o que muda no css?

Velocidade

O Magic vem com um framework básico css, que fornece um grid responsivo e classes auxiliares. Assim ele lhe  ajuda a escrever css mais rápido, mas sem carregar um monte de estilos desnecessários ao projeto.

Poder

Less CSS: Todo o css que você escrever será automaticamente compilado por um pré-processador Less. Já falamos nesse post sobre o motivo pelo qual recomendamos o uso de pré-processadores css, porém volto a ressaltar que meu fluxo de trabalho foi muito otimizado com eles.

Browser Sniffing dentro do CSS: Além de todo o poder gerado pelo Less, ainda temos a possibilidade de exibir regras especiais de acordo com o navegador direto do css. Felizmente essa funcionalidade é cada vez menos necessária, porém ajuda e muito quando precisamos dela.

 

PHP dentro do CSS: Sim, você pode utilizar PHP dentro do css, se isso não é poder suficiente para você, não sei o que vai ser. Você pode se perguntar por que faria isso, bem aqui vão alguns exemplos:

  • Gerar um grid de acordo com variáveis sem precisar escrever linha a linha.

     
  • Mudar o tamanho dos itens do menu de acordo com a quantidade de itens registrados no banco de dados, tornando desnecessária a verificação em JS.

Element Querys Existe uma ideia de que media queries não são a resposta para design responsivo e sim um hack, pois ao condicionar suas regras CSS de acordo com o tamanho da tela você impossibilita a modularização. A solução seria condicionar as regras de acordo com os tamanhos de um determinado elemento ou outro, ai surgem as elements-queries, permitindo por exemplo diminuir a fonte de todos os parágrafos que tiverem menos de 400 pixels de largura, independentemente de onde a página estiver sendo visualizada. Isso é o resumo do resumo do conceito, que pode ser melhor compreendido nesse post genial.

Praticidade, Agilidade ou Felicidade

Para servir o usuário com um único arquivo css pequeno, o Magic vai agrupar todos os seus CSS’s em um só e minificar ele automaticamente, mantendo-o em um arquivo de cache até que um dos arquivos que geraram ele sejam modificados novamente, evitando assim o processo de agrupar e minificar ele a cada requisição.

Por exemplo, se você possui 3 folhas de estilo: “Styleguide.css”,”Home.css”,”Slider.css”, o Magic vai automaticamente criar um arquivo de cache que é composto pela união do conteúdo de todos eles, após criar esse arquivo ele vai remover todos os comentários e minificar o arquivo para servir ao usuário.

Mas isso tudo sem tocar nos seus arquivos de desenvolvimento. Essa é uma das minhas partes favoritas em todo o framework, pois faz com que uma tarefa muitas vezes ignorada por ser chata, repetitiva e atrapalhar muito a manutenção do projeto, passe a ser invisível e transparente ao desenvolvimento.

E quanto ao Javascript?

No que se refere ao Javascript, o Magic foca mais nas requisições ajax, criando um ambiente comum no javascript e no php. Segue abaixo o exemplo de uma requisição ajax:

  Javascript

  PHP:

Como podemos perceber nos códigos acima, as requisições podem ter o status de sucesso ou falha, lembrando que esses são status lógicos e não o status da requisição. Por exemplo, se o ajax tem a função de encontrar um item no banco de dados, o sucesso seria ele encontrar esse item e a falha seria ele não encontrar.

No lado do javascript, o framework vai definir se utiliza o callback onSuccess ou onFail de acordo com o que foi utilizado no PHP, isto é se o php retornou $this->json->fail, será utilizado o  callback onFail, já se o php retornou o $this->json->success será utilizado o callback onSuccess.

Podemos também perceber que tanto no Javascript, quanto no PHP os parâmetros são os mesmos, a “msg” que o php enviar vai ser a “msg” que o javascript vai receber e o array associativo que o php enviar no “dataArray” será convertido em um objeto similar no parâmetro data do javascript.

Quanto a parte de executar a requisição ajax de fato, o método post no Javascript é responsável por isto. O primeiro parâmetro é a rota, que mostrei para vocês na imagem do início do post e o segundo é um objeto associativo com os parâmetros a serem passados.

Além da abstração do ajax, o Magic já vem com o jQuery 1.9.1 e disponibiliza algumas variáveis que você pode utilizar no projeto, são elas:

  • path_base: Contém o caminho até a url base do seu projeto, por exemplo: http://www.seudominio.com, com isso você pode usar essa variável sempre que precisar referenciar seu caminho. Dessa forma na hora de trocar o projeto de servidor, como por exemplo para colocá-lo em produção todos os caminhos serão atualizados automaticamente.
  • magic_scope: Contém o escopo dessa requisição.
  • magic_language: Contém a linguagem dessa requisição.

E por último os templates (HTML’S)

Quanto aos HTML’s, o Magic possui um componente que gerencia o html da página chamado MagicHTML. Esse componente vai gerar para você o html base da página, incluindo as seções do Doctype e do Head. Para customizar essas seções, como por exemplo as metatags, o componente possui vários métodos.  É um pouco complicado explicar, mas você vai entender melhor na hora que montar seu primeiro aplicativo com ele.

No mais, os templates geralmente são blocos de html simples e um template pode chamar outro template, o que permite reaproveitamento e modularização.  Por exemplo, podemos ter um template chamado “produto.tpl” que é utilizado em outros templates como: home.tpl, categoria.tpl, busca.tpl entre outras seções que contenham listas de produtos.

E as vantagens no Backend?

Caminhos

O Magic automaticamente identifica onde o frameword está sendo executado e define uma série de constantes de acordo com esse caminho. Na prática o que isso significa é que você não precisa mudar nenhuma configuração na hora de trocar o projeto de servidor, novamente uso o exemplo de quando publicar ele. Basta colocar os arquivos na pasta que você quer que o framework seja executado e todos as referências a arquivos permanecerão intactas.

Rotas

No Magic URL’s amigáveis são definidas através de um arquivo de configuração chamado routes.json, ele é extremamente simples de se configurar e fazer url’s amigáveis nunca foi tão fácil. Abaixo um exemplo desse arquivo de configuração, comentado.

Os comentários devem ser auto-explicativos, a única observação não presente nos comentários é com relação aos parâmetros variáveis. Essa situação pode ser visualizada no caso dos produtos e galerias do exemplo acima.

Os parâmetros variáveis são definidos através de expressões regulares e são passados como no exemplo da linha 9. Naquele caso, a variável $_GET[‘slug’] seria = 1. Porém, se a url fosse http://www.seudominio.com.br/produto/teste, $_GET[‘slug’] seria igual a “teste”.

Banco de Dados

Essa é a minha parte preferida do Magic, fica muito mais prático trabalhar com bancos de dados utilizando as três classes disponibilizadas para a tarefa. Abaixo, uma breve apresentação de cada uma delas.

DbModel

A classe DbModel é responsável pela manipulação de um registro de uma determinada tabela, sendo por exemplo responsável por todas operações relacionadas a um único registro. Abaixo alguns exemplos:

Procurar na tabela carros o registro cujo id é “5”:

Exibir o título do carro agora ue já achamos ele:

Retornar todas as informações do carro num array associativo

DbModelPlural

Enquanto a classe DbModel serve para manipular um único registro da tabela, a DbModelPlural tem o objetivo de manipular vários registros simultaneamente. Vamos aos exemplos:

Deletar todos os carros produzidos antes de “2000”

Nas funções de pesquisa os parâmetros são nomeados e passados num array associativo, dessa forma o Magic, utilizando PDO, prepara as queries de maneira segura.

DbModel e DbModelPlural a utilização real

Apesar de já ser bem legal utilizar o banco de dados conforme mostrado acima, o poder real dessas classes começa quando estendemos elas.

Ao estendê-las podemos utilizar uma série de funcionalidades para agilizar e muito a manipulação do banco de dados. São algumas dessas funcionalidades:

Métodos Gatilhos:

A classe DbModel possui uma série de métodos que você pode declarar na classe filha que serão executados em alguns momentos cruciais. Alguns desses gatilhos são:

  1. before_destroy e after_destroy: Executados respectivamente antes e depois do método destroy(), responsável por deletar o registro do banco.
  2. before_new e after_new: Executados respectivamente antes e depois da criação de um novo registro no banco.
  3. before_update e after_update: Executados respectivamente antes e depois da atualização de um registro no banco.

Abaixo alguns exemplos de situações onde esses gatilhos são extremamente úteis:

Imagine a seguinte situação, você possui uma tabela produtos e cada produto possui uma ou mais fotos. Você poderia utilizar foreign keys para deletar essas fotos automaticamente do banco de dados quando um produto fosse deletado, porém ficaria com um monte de arquivos “mortos” das fotos no disco.

Contudo, essa situação poderia ser resolvida com o gatilho after_destroy da seguinte maneira:

Outro caso de uso comum dos gatilhos é quando temos uma coluna responsável pela ordenação dos registros. Nesse caso precisamos de três gatilhos, o before_new,after_destroy e before_update.

No before_new, procuramos a última posição atual no banco, para registrar o registro com a posição correta.

No after_destroy alteramos a posição de todos os registros com posição superior a do registro deletado, diminuindo elas e mantendo a consistência dos dados.

Já no before_update verificamos se a posição foi trocada, se sim, alteramos os outros registros de acordo.

Condições Globais

Reconhecidas no código como global wheres são condições que são adicionadas em todas as queries. Por exemplo, se você tem um campo na tabela para dizer se uma noticía está ou não ativa, você não vai precisar checar esse campo em cada query, basta que você defina uma condição global e ela será aplicada a todos as queries. Veja abaixo um exemplo de como funciona:

Agora se usarmos produto::find(5), a query resultante seria algo como:

Joins

Outra funcionalidade importante é abstração dos joins, uma vez definido os joins, todas as vezes que você fizer uma query ao banco ele irá retornar as informações solicitadas no join junto. E esses dados também estão disponíveis no formato de objeto, fica mais claro vendo:

Novamente,  se utilizarmos o método produto::find(5) resulta numa query semelhante a:

E teríamos a propriedade tituloGaleria no objeto produto, portanto algo como assim:

Se torna possível.

Campos Adicionais

Sabe quando você precisa tratar uma data antes de retornar ela na query, ou quem sabe fazer alguma fórmula? Os campos adicionais são isso, você passa uma operação sql e um apelido, e todas as queries seguintes irão ter esse campo junto. Como antes, fica mais claro vendo:

E a query resultante de produto::find(5) seria:

Semelhante ao que acontece com os campos do join, podemos acessar o campo adicional no formato $produto->hora_insercao, após executar um método de busca como o find.

Paginação

A classe DbModelPlural também tem suporte nativo a paginação, podemos ver abaixo como isso funciona na prática:

E agora podemos ver um exemplo completo de como seria estender as classes dbModel e dbModelPlural:

DbManager:

A terceira classe para manipulação de bancos de dados você provavelmente não vai utilizar tão frequentemente. Diferentemente das anteriores, essa serve para manipular a estrutura do banco de dados e não seus registros. Algumas possibilidades são:

  1. Pegar todas as colunas de uma tabela em um array, contendo nome, tipo da coluna e se é um indíce ou não.
  2. Adicionar uma coluna em uma tabela.
  3. Verificar se existe uma tabela no banco.
  4. Duplicar uma tabela
  5. Verificar a existência de uma coluna em uma tabela

Além dessas, outras funcionalidades estão disponíveis caso você precise.

Principais auxiliares

Apesar de existirem diversas classes auxiliares no Magic para ajudar no desenvolvimento, não falarei de todas essas classes hoje, porém abaixo comentarei sobre as principais.

  • Login: Existe uma classe para autenticação pronta no Magic, ela é bem simples, mas segura e contempla a maioria das situações. Você apenas precisará de algumas modificações para sistemas com permissões complexas.  Ela precisa de pelos menos 3 campos na tabela de usuários: Nome de usuário, senha e salt. A senha deve ser salva utilizando método crypt do php, concatenada a um salt único para cada usuário. Suporte a grupos de usuários também está pronto.
  • Date: Caso você precise de uma classe para lidar com dias úteis no Brasil, essa é uma boa classe. Ela tem a possibilidade de adicionar x dias úteis a uma determinada data, checar a quantidade de dias úteis entre duas datas distintas e outras funcionalidades.
  • Paginacao: A classe DbModelPlural já tem suporte nativo a paginação como vimos acima, porém a funcionalidade apenas prevê a parte relacionada as queries, e não a exibição da paginação. Essa classe supre essa demanda, ela pede um template para exibir a paginação, um objeto DbModelPlural e uma Url base para gerar as urls das outras páginas. Com isso ela identifica automaticamente em qual página está, quantas páginas temos e quais os links de cada uma. Abaixo um exemplo para facilitar o entendimento:
  • Upload: Serve de abstração para upload de um arquivo ou de múltiplos arquivos simultaneamente. Além de cuidar de todos os procedimentos de mover os arquivos para os diretórios finais e criar esses diretórios quando necessário a classe ainda permite que você valide os uploads por extensão.

Compatibilidade

É importante lembrar que o Magic é testado em ambiente Linux rodando com Apache e MySQL. Apesar de não ser difícil adaptar ele para funcionar em um Servidor Windows com IIS, a versão original dele não vai funcionar sem alterações, se esse for o seu caso, você pode me mandar um e-mail ou comentar aqui que eu lhe ajudo a configurar. Quanto ao banco de dados nunca tentei utilizar as classes de abstração do banco com outros bancos, porém como é utilizado PDO a adaptação não deve ser extremamente complicada.

Conclusão

Esse foi o primeiro artigo sobre o Magic aqui no blog da WebingPro, em breve vamos mostrar para vocês um tutorial de como fazer seu primeiro aplicativo com ele e depois vamos aprofundar cada um dos seus principais componentes em posts exclusivos, pois se fosse para falar de tudo aqui, esse post não ia acabar nunca.

Espero ter conseguido lhe apresentar os principais conceitos do framework e despertar seu interesse nele. Se consegui, você pode acompanhar o projeto e fazer download dele no Github, gostaria de pedir também que caso tenha gostado do projeto entre em contato para contribuir com ele, atualmente é difícil fazer o projeto crescer na velocidade desejada sem a ajuda da comunidade.

Caso você tenha ficado com dúvidas, o que é natural nesse tipo de apresentação, pode ficar a vontade para comentar que eu responderei com o maior prazer! E se tiver alguma sugestão, a mesma coisa 😉

——————————————-

Editado:

Outros posts referente ao Magic:

Conheça o autor do post

Gabriel Felipe:
Notice: the_author_description está obsoleto desde a versão 2.8.0! Use the_author_meta('description') em seu lugar. in /home/webingpro/www/blog/wp-includes/functions.php on line 3830
Tenho foco em PHP, mas gosto de ficar de olho no que ta acontecendo no mercado. Já brinquei com: Python, Node.JS e Ruby on Rails. PHP ainda é minha paixão no entanto. Na formação, sou autodidata desde 2004. Aprendi o que eu sei com a internet e esse blog é uma tentativa de devolver um pouco disso. Eu gosto de opensource, e a maioria das coisas que você encontrar aqui vão estar licenciadas sobre beerware, ou licença da cerveja.