forum
                                
                                
                                
                                    forum copied to clipboard
                            
                            
                            
                        Pode Objeto Request em Repositórios?
Olá pessoal, sou novo com a parte de repositórios e gostaria de um opinião de vocês, sobre algumas funções que gostaria de utilizar num possível repositório, usando o objeto Request!
Problema Encontrado
Limpar Controller, Isolar Camada de persistência de Dados
Abordagem
Imaginem estas funções no seu Controller
public function index(Request $request, RepositoryUser $repository){
      $repository->save($request);
      $repository->get($request);
      $repository->delete($request);
      $repository->update($request);
}
Vamos pegar o exemplo do método "save". Imaginem uma implementação base Padrão para esta função.
class RepositoryBase {
    pubic function save(Request $request){
        $model->fill($request->all());
        $model->save();
    }
}
Poderiamos ter duas funções save, uma usando request e outra por parametros. Além disto, na função request, podemos colocar parametros adicionais, para configurações com relação ao objeto request se em alguns casos os inpputs não coincidirem com as propriedades da Entidade.
Enfim, acho que isto poderia limpar enormemente o controller e poupar tempo se bem implementado O que vcs acham?
Eu acho que você está movendo a responsabilidade do Controller pra dentro do Repository. Particularmente, eu não faria. A única utilidade do Controller deveria ser decifrar o Request de uma forma que o Repository entenda. Assim, você pode ter vários Controllers e vários tipos de Requests capazes de conversar com um Repository.
Imagine que no futuro você queira um comando artisan utilizando o Repository, mas console não gera REQUEST, o que impediria o processo. O Repository deveria ser agnóstico em relação à forma como a informação chega.
A única utilidade do Controller deveria ser decifrar o Request
Alguém mais concorda com isso? Não digo única mas que isso seria uma responsabilidade do controller.
Sei que vou ter muito chão pela frente, ver muitos videos tutoriais até chegar a uma conclusão de como melhor utilizar este padrão de desenvolvimento, que para mim ainda é muito implícito, cada um pode fazer o que quiser e falar que é um repositório. A única sensação que não quero ter é perceber que estou implementando funcionalidades que o Eloquent já me traz, se for para fazer um repositório que seja para avançar com o projeto!
CONCORDO - _A única utilidade do Controller deveria ser decifrar o Request _ O controler é burro, mas só ele sabe a quem delegar as informações que ele recebeu. Os repos são serviços, e não devem saber de onde vem os dados, só precisam saber oq fazer com o dado Em seguida o controler sabe como ou oq responder.
Com isso em mente, pense em um caso onde você ter que usar o repo em um comando artisan ou em um cron... nesses ambientes não possuem $request, pois não estão sub o http.
Concordo com o @vinicius73 Acho que seria válida uma fina camada de validação na própria camada Controller, ela processaria qualquer validação e sanitização (antes mesmo de passar para o controller concreto, por assim dizer "antes de entrar no sistema"). Mesmo o objeto controller concreto requisitado não saberia nada sobre a validação e sanitização do input. Geralmente faço essa fina camada em APIs para evitar input de dados indesejados, "sujos" ou mal formatados.
Eu sigo o mesmo pensamento do @vinicius73. É possível seguir os conceitos que @Maykonn comentou utilizando Form Requests, eles vão garantir que seu controller não vai nem chegar a ser executado se os dados não são válidos (mas as vezes a validação é muito simples e em alguns poucos casos não tem problema validar dentro do controller).
A única sensação que não quero ter é perceber que estou implementando funcionalidades que o Eloquent já me traz, se for para fazer um repositório que seja para avançar com o projeto!
É por isso que eu desisti de usar Repository e decidi usar apenas Services. Se a operação é incrivelmente simples como simplesmente chamar save() no Eloquent, eu simplesmente injeto o Eloquent direto no Controller e chamo Save. "Ah, mas se vc quiser sair do Eloquent no futuro, tá fudido". Sim, eu não vou sair do Eloquent. Re-inventar o Eloquent no Repository me parece bem trabalhoso e pouco vantajoso para todos os projetos que já trabalhei até hoje.
As vezes as operações são mais complexas. Salvar 2 models diferentes e disparar um email, por exemplo. São 3 ações referentes a uma regra de negócio que vai estar em um Service e o Controller vai simplesmente delegar a requisição decifrada ao Service.
@deleugpn Utilizo bastante Repository nos meus projetos porque preciso abstrair a manutenção dos dados entre Redis, NoSQL e MySQL. Como você disse, usar Repository em casos que há necessidade.
Ótimo caso concreto que defende o uso de Repository. Eu não tive um ainda, mas com certeza lembrarei do seu comentário se um dia eu precisar.
Sei que vou ter muito chão pela frente, ver muitos videos tutoriais até chegar a uma conclusão de como melhor utilizar este padrão de desenvolvimento, que para mim ainda é muito implícito, cada um pode fazer o que quiser e falar que é um repositório.
Muitos já fazem isso e violam o Repository Pattern como bem entendem, mas isso não é repositório. 👍
É por isso que eu desisti de usar Repository e decidi usar apenas Services.
Isso em geral também é ruim e ignora completamente que repositórios vão muito além de simplesmente trocar o mecanismo de acesso aos dados. Repositórios existem principalmente para centralizar as consultas ao mecanismo de acesso aos dados e reduzir a duplicidade de código que existe quando você não tem essa camada.
Este artigo do MSDN tem ótimos argumentos sobre a contextualização e os objetivos do Repository Pattern. É preciso ter em mente que um repositório não é apenas sobre desacoplamento da camada de acesso aos dados, seu propósito central é abstrair os detalhes específicos de implementação da camada de acesso aos dados e servir como uma camada de acesso aos dados voltada para o domínio em vez da infraestrutura, centralizando as regras e lógicas de acesso aos dados - não por acaso o conceito de repositório surgiu no DDD. Muita gente confunde repositório com DAO e ORM, mas repositório não é nada disso. O artigo The Repository Pattern do Shawn McCool é outra excelente leitura sobre o assunto.
Você pode muito bem implementar repositórios apenas usando o Eloquent e ainda ter ganhos significativos nas métricas de sua base de código, porque você terá uma API declarativa e orientada ao domínio para obter os dados, podendo até mesmo fazer uso do Criteria pattern (variação do Specification Pattern) para construir consultas complexas. Outro ponto importante a ser esclarecido é que quando se fala em troca do mecanismo de acesso aos dados, isso não necessariamente precisa ser outro banco de dados. Pode ser simplesmente uma camada de caching por cima do Eloquent, e este é um perfeito caso de uso do Decorator Pattern para ser usado no Repository Pattern, demonstrado na aula Decorating Repositories do Laracasts - o package CacheDecorator demonstra uma técnica diferente de como esse pattern pode ser aplicado.
A menos que um projeto seja muito simples (e eu não consigo imaginar um) ele não irá tirar proveito do Repository Pattern, mas em qualquer outro caso haverá claras vantagens em empregar o seu uso levando em consideração que a camada de repositórios é voltada ao domínio e não à infraestrutura. 👍
Re-inventar o Eloquent no Repository me parece bem trabalhoso e pouco vantajoso para todos os projetos que já trabalhei até hoje.
E de fato não há vantagem alguma em considerar um repositório como um DAO/ORM. Este é o principal problema do Repository Pattern: ele é difundido de maneira completamente equivocada e packages como o l5-repository só servem para difundir ainda mais esse equívoco, já que é o perfeito exemplo do que não deve ser feito. 🙁
^ Tudo que você comentou descreve porquê eu não uso Repository.
Na verdade descreve o porquê alguém deveria usar o referido padrão. 🤣
@everyone.
concordo com as colocações atuais.
Então vamos lá:
Pode Illuminate\Http\Request no Repository?
Sim pode.
Eu recomendo fortemente você não o fazer.
Repositórios no Laravel já são uma flexibilização máxima que pouco se assemelha ao Pattern Repository
Passar uma Request pra ele é violar fortemente varias letras do SOLID e o até mesmo o senso comum.
Pode == É Possível, então a resposta é sim.
---- Continuo em outro post em sequencia.
@paulofreitas eu não tinha lido sua resposta, tu colocou lindamente sobre os Repositorios no Laravel não serem o Repository Pattern do Laravel.
--- continuo em outro post em sequencia.
@LeonardoBAV seguinte, o repository, como eu uso e acho que deveria ser usado, serve como camada para abstração de consultas e lógicas que podem ser usadas em vários locais,
então, um exemplo comum que pode ser feito usando o seu exemplo ali.
// UserRepository
public function delete( $model )
{
    if ($model->posts) {
       throw new \Exception("Usuário tem posts e não pode ser removido");
    }
    return $model->delete();
}
outro caso comum.
public function activeUsers()
{
     $query = $this->newQuery()->where('active', true);
     return $this->doQuery($query)->get();
}
Veja que estamos encapsulando algumas coisas que poderão ser necessárias em varios locais do app, assim você tem a possibilidade de editar e ajustar as regras em um único local.
MAS não saimos do foco que é consultar / editar / salvar / deletar dados.
Agora, no caso que você disse, como inputs.
Você pode fazer algo da seguinte maneira.
// company controller
/**
 * request: [ name, email ]
 */
public function store(Request $request, CompanyRepository $repository, SubscriptionService $subscriptionService)
{
     $preApproved = $subscriptionService->isPreApproved($request->get('email'));
     if ($preApproved) {
         $repository->create($request->all());
     } else {
         $repository->createPending($request->all());
     }
}
esse exemplo foi só pra ilustrar que toda lógica externa a abstração e reaproveitamento das consultas pode e deve ser feita FORA dos repositórios.
De preferencia, em serviços a parte.