Acessar config.yml e Regras de Negocio

83 views
Skip to first unread message

Carlos Wherbet

unread,
May 16, 2013, 9:18:36 AM5/16/13
to symfo...@googlegroups.com
Galera bom dia, estou continuando eu projeto e varias duvidas vão surgindo, algumas delas consigo resolver sozinho e outras tenho que procurar a ajuda de vcs. Espero que entendam que quando chego aqui pra perturbar vcs é que a coisa ta seria rsrsr
 
Vou enumerar as dúvidas pra facilitar as respostas.

1 - onde coloco minha regra de negocio, em entity? (estou criando um model que extend da minha entity, é correto?)

2 - Quero acessar as configurações definidas em config.yml no meu Model. (no controller cosegui por meio de $this->container->getParameter('service_pentaho'))

3 - Nao estou usando injeção de dependencia, sera que o  caminho é esse? (Estou no processo de entender a injeção no symfony)

Agradeço desde já!


__________________________
Carlos Wherbet


Rafael Goulart

unread,
May 16, 2013, 9:54:07 AM5/16/13
to symfo...@googlegroups.com
Carlos,

Este tipo de regra de negócio funciona realmente com DI. 

Explicando: você "NÃO TEM" como ter acesso ao container no Model. Se quiser encontrar um meio de fazer isto, estará fazendo do modo "errado".

O caminho "certo" é: crie uma classe que receba no construtor o Container, o Doctrine ou qualquer outro serviço que precisar, e como parâmetro opcional (setter) o objeto que você quer validar na regra de negócio.

Algo assim no seu Resources/config/services.yml:

services:

    minha.regra.negocio:
        class: MeuNamespace\MeuBundle\Regras\MinhaRegra
        arguments: ["@service_container", "@request"] 

Isto chamaria a classse:

<?php

namespace MeuNamespace\MeuBundle\Regras;

use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpFoundation\Request;
use Doctrine\ORM\EntityManager;

use MeuNamespace\MeuBundle\Entity\Cadastro;

class MinhaRegra
{
    /** @var ContainerInterface $container */
    private $container;

    /** @var EntityManager $dm */
    private $dm;

    /** @var Request $request */
    private $request;

    /** @var Cadastro $cadastro */
    private $cadastro;

    /**
     * @param ContainerInterface $container
     */
    public function __construct(ContainerInterface $container, Request $request)
    {
        $this->container = $container;
        $this->request   = $request;
        $this->dm        = $this->container->get('doctrine.orm.entity_manager');
    }

    public function setCadastro(Cadastro $cadastro)
    {
        $this->cadastro = $cadastro;
        return $this;
    }

    public function valida()
    {
        // seu código
        return true; // ou false
    }

}

E você pode usar o código assim no seu controler (ou em qualquer lugar que tenha acesso ao Container):

$regra = $this->container->get('minha.regra.negocio');

// (...) aqui qualquer código para pegar Cadastro = $cadastro

if ($regra->($cadastro)->valida()) {
    // Passou na regra
} else {
    // Opa, não passou!
}

Obviamente que está muito genérico. Passar o container é interessante porque tens acesso a QUALQUER serviço, mas o IDEAL é passar o serviço que realmente necessitas para deixar mais consistente. E fiz o exemplo genérico, mas o ideal é usar @doctrine, @mailer, etc.

É o caminho adequado para transformar uma Entity baseada em dados de outra com a qual ela não tem relacionamento (onde você precisaria fazer uma consulta na classe da Entity, coisa possível no SF 1.x mas inadequada e "impossível" no SF2).arguments

Use o app/console container:debug para saber que classe precisa colocar no "use" e o nome do serviço para colocar em "arguments".

[]'s
Rafael



--
Você está recebendo esta mensagem porque se inscreveu no grupo "Symfony Brasil" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para symfony-pt+...@googlegroups.com.
Para postar neste grupo, envie um e-mail para symfo...@googlegroups.com.
Visite este grupo em http://groups.google.com/group/symfony-pt?hl=pt-BR.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.
 
 

Rafael Goulart

unread,
May 16, 2013, 9:56:51 AM5/16/13
to symfo...@googlegroups.com
Em tempo:

Uma forma pouco explorada é usar o validator CallBack. Ele permite direcionar a validação para um método da própria classe. 


[]'s
Rafael Goulart


Em 16 de maio de 2013 10:18, Carlos Wherbet <carlos...@gmail.com> escreveu:

Carlos Wherbet

unread,
May 16, 2013, 10:07:44 AM5/16/13
to symfo...@googlegroups.com
Valeu Rafael, estudarei aqui e postarei os resultados mais tarde. Abs

__________________________
Carlos Wherbet


Marcelo Rodrigues

unread,
May 16, 2013, 10:10:48 AM5/16/13
to symfo...@googlegroups.com
Dentro do contexto da regra de negócio em si, o Model vai além da Entity. É comum o conceito de ambos serem direcionados apenas a abstração de banco, quando na verdade, é bem mais complexo. Principalmente com o Doctrine, que abstrai  um pouco do conceito de DDD, onde o Model engloba Serviços, Repositórios, Objetos de Valor, Entidades, etc. 

Independente disso, tente sempre trabalhar com a injeção de dependência. É a forma mais eficiente para separar responsabilidades, gerenciar dependencias e manter a organização entre camadas. 

Geralmente, eu costumo abstrair regras de negócios em uma camada de Serviços (não confundir com "services" no DI do Symfony). Para cada serviço, eu injeto as dependências necessárias para o que ela deve fazer. Tem gente que prefere inserir o Container inteiro para pegar o que for necessário e, quando necessário. Eu prefiro inserir somente aquilo que eu preciso, além de ficar mais lógica, ajuda na questão da organização do namespace e deixa o auto-complete orientado pelas interfaces mais produtivo, dependendo da IDE utilizada. 

Marcelo



2013/5/16 Carlos Wherbet <carlos...@gmail.com>

--
Você está recebendo esta mensagem porque se inscreveu no grupo "Symfony Brasil" dos Grupos do Google.
Para cancelar a inscrição neste grupo e parar de receber seus e-mails, envie um e-mail para symfony-pt+...@googlegroups.com.
Para postar neste grupo, envie um e-mail para symfo...@googlegroups.com.
Visite este grupo em http://groups.google.com/group/symfony-pt?hl=pt-BR.
Para obter mais opções, acesse https://groups.google.com/groups/opt_out.
 
 



--
Marcelo Rodrigues

Analista Desenvolvedor
Zend Certified Engineer ZEND018059

+55 (61) 9273 2058

Rafael Goulart

unread,
May 16, 2013, 10:23:47 AM5/16/13
to symfo...@googlegroups.com
Marcelo,

Concordo com tua análise. Model tem a ver com negócio, enquanto Entity tem a ver com banco. O que acontece é que o Doctrine 2 desacoplou a Entity de modo que ela é uma classe comum com annotations, ou seja, pode (ou não) ser também ser o Model no contexto da aplicação (o que é mais comum e simples na maioria das utilizações).

Na minha resposta dei o exemplo injetando o Container e do Request, e fiz o mesmo alerta que você: é melhor injetar apenas o que se necessita, e não o Container inteiro, dá mais consistência ao serviço, fica mais claro, mais fácil de utilizar a complementação de código por classes de uma IDE... enfim, reforçando tudo o que dissestes, é o que recomendo também.

Além disso, adiciono mais um item: fica mais fácil escrever testes.

[]'s
Rafael Goulart

Bruno Avelino

unread,
May 16, 2013, 12:33:07 PM5/16/13
to symfo...@googlegroups.com
Sou iniciante no symfony 2 também,

Estou com uma dúvida que acho parecida, preciso chamar uma função (regra de negócio) que retorna um array com o conteúdo do banco no model, mas como vi que o Rafael citou, isso não é correto,

O meu problema é o seguinte: Tenho que chamar uma variável menu que está com os dados no banco de dados no meu base.html.twig, para isso estou gerando através do controller um array do menu e mostrando no base.html.twig, só que dessa forma não está legal, pois além de não ser legal chamar no controller (essa função que seria do model), eu ainda preciso chamar para que funcionasse em outras páginas automaticamente.

Alguém poderia me dar uma ajuda de como fazer isso? (A parte parecida com a dúvida do carlos seria chamar essa função de algum model de forma correta)

Bascimente estou criando a variavel menu no controller dessa forma:

public function indexAction($name)
    {

         $em = $this->getDoctrine()->getManager('s3');

        $entities = $em->getRepository('S3LoginBundle:TMenu')
        ->findBy(array('menuSistema' => '48'),array('menuOrdem' => 'ASC'));
       
        $menu = array();
       
        foreach( $entities as $valor ) {

            if( $valor->getMenuParent() == 0 ) {
                $menu[$valor->getMenuSeq()][0] = $valor->getMenuTitulo();
            } else {
                $menu[$valor->getMenuParent()][$valor->getMenuSeq()] = $valor->getMenuTitulo();
               
            }

        }
        return array('name' => $name, 'menu'=> $menu);
    }

Esse controller está retornando a variável menu que é usada no base.html.twig

Aguardo notícias,

Obrigado.
"Perceber o erro é importante, mas corrigí-lo é mais importante ainda!", Bruno Avelino

Bruno Martins Rodrigues Avelino
Engenheiro de Computação - IFCE
Desenvolvedor WEB na SEJUS (Secretaria de Justiça e Cidadania)
Currículo Lattes: http://lattes.cnpq.br/8109361433831613


Contatos:
E-mail, MSN e Gtalk: bmrav...@gmail.com
Facebook: http://www.facebook.com/bmravelino
Twitter: http://twitter.com/bmravelino

Rafael Goulart

unread,
May 16, 2013, 1:09:00 PM5/16/13
to symfo...@googlegroups.com
Sugestão "forte": use o KnpMenuBundle https://github.com/KnpLabs/KnpMenuBundle/blob/master/Resources/doc/index.md

Ele faz o que você precisa e já possui uma extensão para chamar no Twig o menu.

Neste caso, bastaria você montar seu menu baseado no banco de dados, ou seja, criar um serviço para seu MenuBuilder injetando o @doctrine, colocar este código lá dentro gerando o menu (bem simples isto, veja os exemplos).

Isto te permitiria criar um menu sem fazer nada no controller, apenas diretamente no template.


Em tempo: veja com carinho o uso de um template para renderizar o menu. Eu uso um para o Twitter Bootstrap que incorporei a este meu bundle, funciona que é um doce:


[]'s
Rafael

Marcelo Rodrigues

unread,
May 16, 2013, 1:08:54 PM5/16/13
to symfo...@googlegroups.com
Bruno, 

No seu caso, ela ultrapassa a regra de negócio em si e torna-se lógica a ser resolvida na camada da view, especificamente. A estratégia aí é transformar o menu em um componente "dinâmico" da view, chamando a action do controller direto do template, ao invés de enviar esse variável direto da action para o template principal. 

Dá uma olhada:


Marcelo




2013/5/16 Bruno Avelino <bmrav...@gmail.com>

Jorge Vahldick

unread,
May 17, 2013, 12:27:41 AM5/17/13
to symfo...@googlegroups.com
Olá Carlos,

Vamos ver se posso te ajudar.
1 - onde coloco minha regra de negocio, em entity? (estou criando um model que extend da minha entity, é correto?)
2 - Quero acessar as configurações definidas em config.yml no meu Model. (no controller cosegui por meio de $this->container->getParameter('service_pentaho'))
3 - Nao estou usando injeção de dependencia, sera que o  caminho é esse? (Estou no processo de entender a injeção no symfony)

Creio que os três questionamentos envolvem o mesmo processo, que é separar as dependências.
Cada "objeto" deve ter sua função bem especifica, deixando assim uma manutenção futura mais fácil e organizada.

Para você tratar as regras de negócio da entidade, creio que um exemplo poderá lhe auxiliar:

O primeiro é quem recebe a entidade e algumas especificidades passadas por di, no qual estende um operação, que neste sim efetuo o tratamento das regras de negócio.
É essencial que os parâmetros e objetos sejam passados por DI.

Espero que tenho lhe ajudado a dar uma idéia de trabalhar com as regras.

Att.
Jorge Vahldick

Jorge Vahldick

unread,
May 17, 2013, 12:30:16 AM5/17/13
to symfo...@googlegroups.com
Boa noite Bruno,

Tem algo que vai lhe ajudar muito neste caso.

Com certeza ele fará exatamente este serviço que estás procurando.

Procure também por DoctrineExtensionsBundle para integrá-lo com o Symfony.

Atenciosamente,
Jorge Vahldick

Carlos Wherbet

unread,
May 17, 2013, 8:24:34 AM5/17/13
to symfo...@googlegroups.com
Galera valew mesmo, com a ajuda de vcs estou conseguindo fazer o que preciso. Estou usando DI mesmo como vcs todos sugeriram!
"tem algo no symfony muito interessante que me motiva trabalhar!"

__________________________
Carlos Wherbet




--

Carlos Wherbet

unread,
May 17, 2013, 8:32:50 AM5/17/13
to symfo...@googlegroups.com
Outra coisa, existe a possibilidade de eu pegar um objeto criado por meio do container. ex:
$graf = new Grafico();


$pentaho = $this->get('pentaho-service');

Eu preciso que nesse  serviço eu receba/inject alem do Container e o Request , receba tbm um objeto de uma outra classe. Como faria?
Pq esse objeto seria recém criado... 


__________________________
Carlos Wherbet


Rafael Goulart

unread,
May 17, 2013, 8:34:42 AM5/17/13
to symfo...@googlegroups.com
Use um setter. Veja o exemplo que te passei.

[]'s
Rafael

Carlos Wherbet

unread,
May 17, 2013, 8:41:46 AM5/17/13
to symfo...@googlegroups.com
Rafael, pois está dessa forma!
Pensei que poderia ter outra forma mais 'atraente'. Vlw

__________________________
Carlos Wherbet


Jorge Vahldick

unread,
May 17, 2013, 10:50:25 AM5/17/13
to symfo...@googlegroups.com
Carlos,

Talvez você devesse verificar a possibilidade do seu próprio serviço criar o objeto.
Você passa o nome da entidade por DI, e cria em seu serviço create"Entidade", retornando new da sua entidade.

Assim você trabalharia com a criação dentro do próprio gerenciador, não havendo necessidade de setar o objeto após criação do serviço.
Se você sempre necessitar criar este objeto, poderá passá-lo como referência, por DI você pode criar new Reference('classe da entidade').

Atenciosamente,
Jorge Vahldick

Marcelo Rodrigues

unread,
May 17, 2013, 11:53:59 AM5/17/13
to symfo...@googlegroups.com
Acho que primeiro você deve avaliar a necessidade de injetar essa dependência ou criar uma instância local, no seu próprio serviço. 

O objeto já deve existir? Ele é reutilizável? Possui uma lógica, identidade, escopo? É um outro serviço? Existem abstrações da mesma interface? O objeto precisa ser configurável? Geralmente, essas perguntas é que levam a inversão de controle (além de testes unitários). 

Esse tipo de responsabilidade deve estar numa Factory, em alguns casos. Se for uma entidade, não vejo necessidade, a não ser que se encaixe nas perguntas acima. Dê uma olhada nesse link, talvez o ajude:


Marcelo




2013/5/17 Carlos Wherbet <carlos...@gmail.com>

Marcelo Rodrigues

unread,
May 17, 2013, 11:56:21 AM5/17/13
to symfo...@googlegroups.com
Outra coisa, evite ao máximo injetar o Request em seus serviços, assim como o Container. No caso do Request, é por conta do "escopo", que pode mudar, dependendo de como o serviço é chamado e isso pode lhe trazer problemas. Veja:


Marcelo


2013/5/17 Carlos Wherbet <carlos...@gmail.com>
Outra coisa, existe a possibilidade de eu pegar um objeto criado por meio do container. ex:

Jorge Vahldick

unread,
May 17, 2013, 6:29:00 PM5/17/13
to symfo...@googlegroups.com
Boa noite Fabiano,

SOA é uma forma de arquitetura de trabalho, no qual você não necessariamente irá utilizada, podendo por exemplo utilizar somente a arquitetura MVC.
A arquitetura MVC é mais "engessada", enquanto o SOA é mais abstrata.

Eu penso da seguinte forma:
O Symfony é um framework que é baseado em Requições e Respostas. O próprio Fabien gosta de frisar bem esta questão, dizendo que o Symfony2 não é um Framework MVC.

Portanto você poderá trabalhar da maneira que achar melhor.
Quanto a pergunta 3, creio que não seja de nenhuma camada, sendo realmente um serviço. E a camada que pode se comunicar com este serviço são outros serviços e a camada controlador.

Vejo muitas pessoas terem estas dúvidas porque é um conceito novo para PHP.
Penso que é importante estudar estes conceitos, pois senão você não estará utilizando a gama de recursos que o Symfony proporciona.

Você deve pensar em grande escala e reutilização de código, que desta forma este framework será espetacular, caso contrário, creio que qualquer outro framework poderá ser útil para desenvolvimento ágil, principalmente Silex.

Espero ter ajudado e espero que outros companheiros também deem suas opiniões.

Att.
Jorge Vahldick

Em sexta-feira, 17 de maio de 2013 16h24min29s UTC-3, Fabiano Tessarolo escreveu:
Olá Pessoal! 

Andei lendo a postagem de todos mas me surgiram algumas dúvidas. Se eu estiver errado por favor me corrijam:

- Pelo que entendi determinadas partes do programa que precisam realizar algum tipo de processamento devem ser tratadas como serviços (SOA)? No contexto do symfony utilizamos o service e DI?
- Se tenho por exemplo um objeto que realiza por exemplo a função de enviar um e-mail, tenho que gerar uma classe e usá-la como serviço? Usando a estrutura de pastas do Symfony, estas classes devem estar dentro da pasta Dependency Injection do Bundle?
- Estes serviços fazem parte da camada Model do MVC?


Um grande abraço e obrigado pela ajuda de vocês.

Fabiano Tessarolo

unread,
May 20, 2013, 11:36:21 AM5/20/13
to symfo...@googlegroups.com
Bom dia Jorge!

Poxa, realmente essa do symfony nao ser MVC eu não sabia.

Obrigado por sua pronta resposta de minha duvida!

Vou então utilizar como servico, como voce orientou.

Um grande abraco e novamente obrigado.
Reply all
Reply to author
Forward
0 new messages