Groups keyboard shortcuts have been updated
Dismiss
See shortcuts

Como chamar um behavior dentro do arquivo 'tables.php'

26 views
Skip to first unread message

Hermiro Carvalho

unread,
Oct 26, 2020, 12:59:22 PM10/26/20
to CakePHP Tuga
Boa tarde.

Eu procurei aqui no fórum, porém os posts que falam de behavior estão muito desatualizados.
O que eu preciso é o seguinte... ANTES de salvar um registro... eu preciso calcular o valor de um campo em função de outro... a minha idéia seria usar um behavior porém eu não entendi a documentação do cakephp...

É possível chamar um behavior dentro de uma função beforeMarshall? 
Algo assim por exemplo?

// Na classe da sua table ou behavior
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{

$SkillTaxaHora = null;
$Valor_taxa = null;


    if (!isset($data['valor'])) {
        
       //Behavior para recuperar o valor da SKILL
        $SkillTaxaHora = $this->BEHAVIOR->METODO_NO_BEHAVIOR($data['id_skill']);

        $data['valor'] = $SkillTaxaHora * $data['tempo];

    }

Cauan Cabral

unread,
Oct 26, 2020, 1:13:15 PM10/26/20
to CakePHP Tuga
Boa tarde,

Você precisa do Behavior exatamente por que?

A partir do CakePHP 3, com a divisão do ORM em Entities e Tables, boa parte dos casos de uso para behaviors passaram a ser atendidos por uma ou outra.
Como regra básica eu costumo fazer:

 - Se o campo que vai ser calculado não precisa de acesso a outra tabela/registro, defino um mutator/getter na minha entidade
 - Se precisa consultar outro registro, uso na table
 - Se precisa de acesso a outra tabela, daí eu parto para um behavior.

Quanto ao callback para uso, você está pensando em definir o beforeMarshal da tabela pra chamar um método do behavior? Porque você pode fazer isso de forma transparente definindo no Behavior
o método beforeMarshal, e nele você faz as rotinas necessárias.


--
--
CakePHP Tuga (cakephp-pt)
 
Utilize http://bin.cakephp.org para códigos
Cookbook: http://book.cakephp.org
 
Website do CakePHP: http://cakephp.org/
Website do grupo: http://groups.google.com/group/cakephp-pt?hl=pt-PT
---
Recebeu esta mensagem porque subscreveu ao grupo "CakePHP Tuga" do Grupos do Google.
Para anular a subscrição deste grupo e parar de receber emails do mesmo, envie um email para cakephp-pt+...@googlegroups.com.
Para ver este debate na Web, visite https://groups.google.com/d/msgid/cakephp-pt/30175d61-48c1-4747-9976-97ae4e8e5880n%40googlegroups.com.


--
Cauan Cabral
----------------
Onde me encontrar: https://cauancabral.net

Hermiro Carvalho

unread,
Oct 26, 2020, 1:27:13 PM10/26/20
to CakePHP Tuga
Cauan.

Se eu entendi o que voce disse seria o seguinte:
No código que eu postei, o valor da variável  $SkillTaxaHora depende de um outro campo de que está numa tabela diferente...
dependendo da opção que o usuário coloca no formulário esse valor pode mudar.
Eu pensei no Marshall porque eu já tenho ele pronto e eu pensei que chamando o behavior aqui eu conseguiria calcular esse valor como eu seu estivesse preenchendo manualmente este campo do formulário... porém a documentação não me ajuda muito... por isso eu coloquei esse código porque eu pensei que o jeito de usar um behavior fosse parecido com o jeito de usar um componente de controller por exemplo.
Outro ponto importante é que eu posso reutilizar esse código em outro ponto da minha aplicação...
Existe outra forma de fazer isso sem usar o behavior? 

Cauan Cabral

unread,
Oct 26, 2020, 2:00:23 PM10/26/20
to CakePHP Tuga
Entendi, nesse seu caso faz sentido o uso do behavior sim.

Na sua Table, você pode fazer algo assim:

public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    $SkillTaxaHora = null;
    $Valor_taxa = null;

    if (!isset($data['valor'])) {
       
       //Behavior para recuperar o valor da SKILL
        $SkillTaxaHora = $this->getBehavior('NOME_DO_SEU_BEHAVIOR')->METODO_NO_BEHAVIOR($data['id_skill']);

Hermiro Carvalho

unread,
Oct 26, 2020, 3:09:54 PM10/26/20
to CakePHP Tuga
Erro.

Criei meu behavior utilizando o bake e ao tentar inserir dentro da minha table deu o seguinte erro:


Não entendi bem o porque, pois no início da minha table eu fiz:
    public function initialize(array $config): void
    {
     
        //Adiciona o behavior 'OnSaveBehavior' para tratamento de campos.
        $this->addBehavior('OnSave');
 }

Esse é o código da minha função dentro do Behavior:
public function ConfiguraTempoTotal ($id_skill = null, $horas = null){
        //Declaração de variáveis.
        $valor_skill = null;

        //Valida id da skill
        if (empty($id_skill)) {
            return false;
        }

        //Valida quantidade de horas
        if (empty($horas)) {
            return false;
        }

        /*
        ** Se todos os parâmetros forem informados tenta calcular o valor baseado
        ** na quantidade de horas pela skill.
        */
        $valor_skill = $this->Skill->find('all', ['conditions' => ['Skill.id' => $id_skill]]);
        debug($valor_skill);
        die("OnSave Behavior");
    }

O código do Marshal ficou assim:
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{
    $SkillTaxaHora = null;

    if (!isset($data['valor'])) {        

        $valor = $this->OnSave->ConfiguraTempoTotal($data['id_skill'], $data['tempo']);
        die("Hermiro Marshal");
        $SkillTaxa_hora = $data['tempo'] * $valor['valor'];

    }

Alguém sabe me explica porque ele não está aceitando? 

Hermiro Carvalho

unread,
Oct 26, 2020, 3:14:58 PM10/26/20
to CakePHP Tuga

Anexando um print do erro.
Erro_Behavior.jpg

Cauan Cabral

unread,
Oct 26, 2020, 3:25:19 PM10/26/20
to CakePHP Tuga
Você está chamando seu Behavior como se fosse uma Table relacionada, olha novamente como eu tinha sugerido o código para chamar o behavior:

$SkillTaxaHora = $this->getBehavior('NOME_DO_SEU_BEHAVIOR')->METODO_NO_BEHAVIOR($data['id_skill']);

Hermiro Carvalho

unread,
Oct 26, 2020, 3:52:47 PM10/26/20
to CakePHP Tuga
Boa Cauan... Funcionou...

Segue abaixo o código do meu behavior e do Marshall...

Marshall
public function beforeMarshal(Event $event, ArrayObject $data, ArrayObject $options)
{

    $SkillTaxaHora = null;

    if (!isset($data['valor'])) {        

        $SkillTaxaHora = $this->getBehavior('OnSave')->ConfiguraTempoTotal($data['id_skill'], $data['tempo']);//Chama o behavior
        $data['valor'] = $data['tempo'] * $SkillTaxaHora['0']['valor'];//Calcula o custo pela relação SKILL e tempo gasto.
    }
}

Behavior (código completo)
<?php
declare(strict_types=1);

namespace App\Model\Behavior;

use Cake\ORM\Behavior;
use Cake\ORM\Table;
use Cake\ORM\TableRegistry;
/**
 * OnSave behavior
 * Autor: Hermiro Carvalho
 * Objetivo: Padronizar neste behavior, todas as operações de configurar campos ANTES do evento
 *           de salvar.
 */
class OnSaveBehavior extends Behavior
{
    /**
     * Default configuration.
     *
     * @var array
     */
    protected $_defaultConfig = [];
    /**
     * Função: Configura o valor do campo tempototal
     * Objetivo: Através do ID (ID do atendimento), soma os valores de todos os atendimentos e 
     *           retorna o valor.
     */
    public function ConfiguraTempoTotal ($id_skill = null, $horas = null){
        //Declaração de variáveis.
        $valor_skill = null;
        $this->table = TableRegistry::get('Skills');
        $this->table = TableRegistry::getTableLocator()->get('Skills');
        $data = null;
        //Valida id da skill
        if (empty($id_skill)) {
            return false;
        }

        //Valida quantidade de horas
        if (empty($horas)) {
            return false;
        }

        /*
        ** Se todos os parâmetros forem informados tenta calcular o valor baseado
        ** na quantidade de horas pela skill.
        */
        $valor_skill = $this->table->find('all', ['conditions' => ['Skills.id' => $id_skill], 'fields' => ['Skills.valor']]);
        if (!empty($valor_skill)) {
            $data = $valor_skill->toArray();
            return $data;
        }

    }
}

Reply all
Reply to author
Forward
0 new messages