CakePHP Brasil

27 abril 2010

Behavior Super Find veio ao mundo

Arquivado em: CakePHP — Tags:, , — Juan Basso @ 6:49 pm

Depois de ter criado o post sobre o Behavior para melhorar o find, cá está ele! Ontem a noite criei o projeto e enviei o código que tenho para o GitHub, no projeto entitulado de super_find.

Tinha dito que o nome seria power find, mas depois de ver alguns projetos na internet como o SuperAuth, SuperValidatable, etc., resolvi manter o nome de SuperFind.

Bem, vamos ao que interessa, o que faz e como funciona… Basicamente, ele serve para fazer um find podendo colocar condições de relacionamentos hasMany e HABTM. No CakePHP puro isto não é possível, pois ele joga estas condições na query direto e acaba causando um erro de SQL. Aí você dizer, mas e o Containable?! Bem, ele até faz alguns filtros, mas o filtro que ele faz é em cima do valor retornado da consulta principal. Vamos a um exemplo:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
$this->Usuario->find('all', array('contain' => array('Tarefa.nome = "Tarefa 1")));
/* Retorno:
    array(
        array(
            'Usuario' => array('id' => 1, 'nome' => 'Usuario 1'),
            'Tarefa' => array(
                array('id' => 1, 'nome' => 'Task 1', 'usuario_id' => 1)
            )
        ),
        array(
            'Usuario' => array('id' => 2, 'nome' => 'Usuario 2'),
            'Tarefa' => array(
            )
        ),
        array(
            'Usuario' => array('id' => 3, 'nome' => 'Usuario 3'),
            'Tarefa' => array(
            )
        ),
    )
*/
 
$this->Usuario->superFind('all', array('conditions' => array('Tarefa.nome' => 'Tarefa 1')));
/* Retorna:
    array(
        array(
            'Usuario' => array('id' => 1, 'nome' => 'Usuario 1'),
            'Tarefa' => array(
                array('id' => 1, 'nome' => 'Tarefa 1', 'usuario_id' => 1)
            )
        )
    )
*/

Em resumo, no Containable ele listou todos os usuários e no relacionamento Tarefa veio apenas os que tinham a ‘Tarefa 1′. Já no SuperFind ele mostrou apenas os usuários que tinham a ‘Tarefa 1′.

O mesmo funciona com relacionamentos HABTM. Para os relacionamentos hasOne e belongsTo não são necessários, pois isto já funciona nativamente.

Por enquanto é possível fazer isto apenas com um nível de filtro, ou seja, você não poderá colocar nas condições algo como Tarefa.Projeto.nome.

Bem, por enquanto é isso. Alguém tem mais sugestões do que poderia entrar? O que sente falta no find?

Abraços e bom uso.

7 Comentários »

  1. Já que você perguntou, hehe

    eu sinto falta de algo que retorne somente os valores de itens que contenham registro em outro tabela, tipo o select abaixo:
    select * from users where id in (select distinct user_id from posts)

    Tentei usar seu superFind porém ele ainda retorna os users sem posts.
    Eis meu código:

    $conditions = array(‘Questao.curso_id’ => ‘Curso.id’);
    $cursos = $this->Inscricao->Curso->superFind(‘all’, $conditions);

    Se souber de alguma luz no fim do tunel fico agradecido.
    obrigado.

    Comentário por FelipeVR — 28 abril 2010 @ 11:04 am

  2. Código reloaded:

    $conditions = array(‘Post.user_id’ => ‘User.id’);
    $posts = $this->Post->User->superFind(‘all’, $conditions);

    Comentário por FelipeVR — 28 abril 2010 @ 11:06 am

  3. Olá Felipe. Eu não tinha pensado nesta questão, mas você pode fazer algo como “$this->User->superFind(‘all’, array(‘conditions’ => ‘Post.id > 0′));”

    Uma coisa do seu código: não esqueça de colocar a chave ‘conditions’ no superFind, senão ele não irá funcionar.

    Comentário por Juan Basso — 28 abril 2010 @ 1:37 pm

  4. Po esse super find eh uma mão na roda, po juan, vi q você tem um repositório no google de um ERP free, mas não tem nenhum commit, morreu a idéia?

    Comentário por Leonardo — 29 abril 2010 @ 12:24 am

  5. Opa, obrigado. O repositório de ERP foi uma idéia antiga que por falta de tempo meio que morreu sim.

    Comentário por Juan Basso — 29 abril 2010 @ 8:15 am

  6. Assim no Containable:
    $this->Usuario->find(‘all’, array(‘contain’ => array(‘Tarefa’ => array(‘nome’ => “Tarefa 1″))));
    Assim funcionava aqui (pelo que me lembro)… mas mesmo assim sempre tive problemas… principalmente com HABTM (quando queria salvar e associar ao mesmo tempo ou fazer finds)…
    Muito bom o behavior… você poderia alterar para ter um superSave (que funfe o HABTM… se bem que nem seria necessario, um pouco de beforeSave no proprio behavior e foi ontem xD)

    Comentário por Lucas — 5 maio 2010 @ 8:43 am

  7. Mais um grande projeto.
    Vai poupar bastante tempo de criar alguns joins =p
    Obrigado.

    Comentário por Léo Haddad — 1 junho 2010 @ 10:55 pm

Feed RSS dos comentários deste post URL de TrackBack

Deixe um comentário

Powered by WordPress