Executar if com 2 funções ao mesmo tempo

23 respostas
R

Boa tarde.

Tenho 2 funções que inserem dados em um bd ao mesmo tempo. Preciso fazer um “if” ondeele executa as duas funções e dá uma resposta caso as duas sejam executadas corretamente.

Mas caso uma delas não execute, a outra também não pode executar.

Tentei assim:

if((adicionaCategoria01($conecta01, $categoria)) && (adicionaCategoria02($conecta02, $categoria))){

23 Respostas

B

e assim?

if(adicionaCategoriaApp($conecta, $categoria) && adicionaCategoriaSite($conectaSite, $categoria)){
R

Assim assim executou uma delas.

A intenção é não executar nenhuma se uma delas não executar.

E só executar as 2 se as 2 funcionarem corretamente.

B

do jeito q eu fiz vai executar as duas pq o if espera uma “e” a outra pra ser satisfeito…

crie duas variaveis do tipo boolean e debuga pra vc ver é batata

R

Eu testei aqui.

As duas funções inserem a mesma informação em bd diferentes.

Deixei uma das funções com erro, e a outra executou.

Será que o problema é a função em si?

function adicionaCategoria01($conecta, Categoria $categoria){	  
	$sql  = 'INSERT INTO categoria (cat_nome) ';
	$sql .= 'VALUES (:nome)';
	  
	try{
	  $query = $conecta -> prepare($sql);  
	  $query -> bindValue(':nome', $categoria->getNome(), PDO::PARAM_STR);
	  $query -> execute();
			
	  return $query;
	}catch(PDOException $error){
	  return 0;
	}
  }
B

haaaa intendi o q vc quer…

não ponha o try catch dentro da função lance ela e trate fora daí vc vai ter o resultado esperado

rodevops

Não se esqueça de usar transactions (commit e rollback) assim os dados no banco não serão gravados se algo der errado…

B

isso ai…

R

Desculpa, nessa caso não entendi o que devo fazer exatamente.

Teria como ajudar, mesmo se for indicando algo que eu possa estudar?

B

pior q eu num sei php só te dei uma dica de lógica, sou programador java…mais tem bastante gente aki no guj q pode te ajudar

R

Ok, muito obrigado pela ajuda.

rodevops
$conecta->beginTransaction();  

try{
    funcao1()...
    funcao2()...

    $conecta->commit(); // confirma a gravacao
} catch (PDOException $error){
    $conecta->rollback(); // volta tudo pq deu zica!!!...
}

E o try/catch em cada função você retira, deixa apenas os comandos de gravar e tal… só tem um problema… cada objeto PDO fica “amarrado” a um banco de dados por vez, você citou que cada função executa um insert em bancos diferentes né? Vai precisar fazer o commit/rollback para cada conexão pegou?

R

Acho que entendi.

posso fazer assim:

if(adicionaCategoria($conecta, $categoria)){
  //deu certo
}else{
  //deu errado
}

e ai a funçao fazer isso que vc disse?

function adicionaCategoria($conecta, $categoria){
    $conecta01->beginTransaction();
    $conecta02->beginTransaction();  

try{
    // da o insert no bd 01
    // da o insert no bd 02

    $conecta01->commit();
    $conecta02->commit();

     return true;  
} catch (PDOException $error){
    $conecta01->rollback();
    $conecta02->rollback();

    return false;
}
rodevops

Não cara, faz uma coisa mais limpa…

function adicionaCategoria01($conecta, Categoria $categoria){	  
    $sql  = 'INSERT INTO categoria (cat_nome) ';
    $sql .= 'VALUES (:nome)';
  
    $query = $conecta->prepare($sql);  
    $query->bindValue(':nome', $categoria->getNome(), PDO::PARAM_STR);
    return $query->execute(); // isso ja retorna true ou false...
}

Faça algo parecido na outra função… depois de tudo…

$conecta->beginTransaction();  
$conecta2->beginTransaction();

try{
    adicionaCategoria($conecta, $categoria);
    funcao2($conecta2, ...);

    $conecta->commit();
    $conecta2->commit();
} catch (PDOException $error){
    $conecta->rollback();
    $conecta2->rollback();
}

A função apenas tenta executar os comandos, o tratamento deixa para “fora” dela, pegou?

rodevops

E apenas uma dica, quando você estiver afiado em PHP OOP, crie uma classe DAO e coloque suas funções lá dentro e peça uma conexão apenas uma única vez, por exemplo essa categoria ai…

class CategoriaDAO {
    private $conexao; //sera PDO

    public function __construct(PDO $pdo) {
        $this->conexao = $pdo;
    }

    public function lista() {...}
    public function busca($id) {...}
    public function adiciona(Categoria $categoria) {...}
    public function atualiza(Categoria $categoria) {...}
    public function remove(Categoria $categoria) {...}
}

Seu $conecta de dentro da função acabaria sendo o $this->conexao preenchido na construção do objeto (quando der um new)…

$dao = new CategoriaDAO($conecta);
$dao->adiciona($categoria);

Viu como fica “cheiroso” seu código, mais limpo e organizado…

R

Acho que entendi. Vou tentar aqui e mais tarde aviso se deu certo.

Mas mesmo assim, muito obrigado pela ajuda.

R

Bom dia amigo.

Eu segui a ajuda que deu e fiz, e funcionou!!! Agora, poderia me ajudar dizendo se estou usando as melhores praticas para a programação?

No final, ficou asssim:

Categoria_forms.php
Contém os formulários para adição, edição, exclusão, etc.

Categoria_funcoes.php
Trata os chamados dos forms, onde coloquei:

$dao  = new CategoriaDao();
$categoria -> setNome($_POST['nome']);

$conecta01 -> beginTransaction();  
$conecta02 -> beginTransaction();

try{
  $dao -> adiciona($categoria, 'tipo01', $conecta01);
  $dao -> adiciona($categoria, 'tipo02', $conecta02);

  $conecta01 -> commit();
  $conecta02 -> commit();
  $_SESSION['mensagem'] = 'Categoria adicionada com sucesso!';
  header("Location: Categoria_forms.php");
  
}catch (PDOException $error){
	
  $conecta01 -> rollback();
  $conecta02 -> rollback();
  $_SESSION['mensagem'] = 'Não foi possível adicionar a categoria.';
  header("Location: Categoria_forms.php");	
}

Depois:
CategoriaDao.php

class CategoriaDao{
   function adiciona(Categoria $categoria, $tipo, $conexao){	  
	$sql  = 'INSERT INTO '.$tipo.'_categoria (cat_nome) ';
	$sql .= 'VALUES (:nomeCategoria)';
  
	$query = $conexao->prepare($sql);  
	$query->bindValue(':nomeCategoria', $categoria->getNome(), PDO::PARAM_STR);
	return $query->execute();
   }		
 }

No fim, funcionou exatamente como queria, executa as 2 instruções e caso uma delas dê problema, não executa nenhuma. Mas esta é a melhor forma de construir um código “cheiroso”??? rsrs

rodevops

Ta ficando “da hora”! :joy:

Agora fiquei na dúvida, o conecta01 e conecta02 apontam para bases de dados diferentes como você disse antes, ou apontam para a mesma base?

Pergunto porque você reutilizou o método adiciona mudando apenas o nome da tabela?

Se sim, é necessário criar duas conexões com o banco?

R

Sim, apontam para bancos diferentes.

Mas para facilitar, eu coloquei as tabelas com nomes parecidos:

banco01_categorias
  banco02_categorias

Assim consigo reutilizar o método com mais facilidade. Visto que um banco é uma cópia do outro. Ai é apenas passar o PDO de cada banco e sua respectiva tabela.

Será que estou no caminho certo?

rodevops

Em se tratando de cópia, o ideal seria a aplicação php guardar registros apenas em uma base, e no banco você deixar uma rotina (job, schedule, etc) que faça backup do banco de tempos em tempos, há configurações no banco que fazem replicação (raid) de um servidor para outro…

Isso deixa o php mais leve ainda, e sem responsabilidade demais (não sei se é seu caso), mas vale dar uma estudada a respeito…

Sempre tenha em mente que para o php (ou qualquer outro backend) um recurso externo (banco de dados, arquivos, web services, ftp, etc) são caros de se manter, quanto menos você precisar usá-los e mais rapidamente possível liberá-los (fechar conexões, etc) melhor…

R

Entendi, vou estudar a respeito disso.

Mas quando eu faço qualquer movimentação no bd, a mesma movimentação tem que ser instantânea no outro, e eu preciso da confirmação que foi executada a msm coisa no outro banco.

Isso é possível através desse job ou schedule?

rodevops

Job/schedule são recursos para processos agendados, e são recomendados para lotes de dados, por isso mencionei de “tempos em tempos”, geralmente agendamos na madrugada para copiar tudo o que aconteceu numa base para outra…

Eu imaginei que você poderia “acumular” tudo numa base e no final do dia copiar tudo, por isso recomendei mas vejo que não é o seu caso…

R

Desculpe te atormentar tanto… Mas é que estou no começo e toda ajuda para mim é muito muito útil.

Mas realmente, meu caso é basicamente que tudo que eu fizer em um banco, tem que aparecer em tempo real no outro banco, que seria para outro site diferente. E realmente não existe a possibilidade de usarem o msm banco.

Achei que faria tudo no PHP, e vc deu essa possibilidade de JOB/Schedule. Mas como vc disse, vou fazer realmente em PHP, e deixar agendado para ter uma “cópia de segurança” sim.

E muito muito obrigado pela sua ajuda, foi mto importante para mim.

rodevops

Outro recurso, mas esse seria em último caso, é usar trigger’s, mas se o fluxo de inserts for muito alto, você deve desconsiderá-lo porque pode afetar a performance… por isso que nem mencionei antes, porque na maioria das vezes é desencorajado… mas além de agregar seu conhecimento, é um recurso…

Nesse sentido, sua tabela na base principal digamos assim, teria uma trigger configurada para cada insert nela, faria um insert para outra base… pesquise a respeito só pra brincar e conhecer, boa sorte!

Criado 16 de agosto de 2017
Ultima resposta 21 de ago. de 2017
Respostas 23
Participantes 3