Função Recursiva php

A parte do $codigo = 1 foi um teste que fiz (em vez de usar os teus dados, simplesmente usei dados 1/2/3, etc).
A variavel código deve ter simplesmente o código que queres procurar.

Para usares o meu código só tens que chamar a função com os teus dados

"$contagem = descer($conn, $codigo, $contador = 0, $comparador= 0);"

No entanto pelo que me apercebi, acho que estás a fazer confusão com a gestão e criação da tua tabela.
Para teres 2 níveis de referidos, deves ter 2 tabelas para o efeito.

Sabendo que o MyReferal é o código único de cada referido ( ou seja, quem se registar, fica associado por aquele código ), o patrocinador é o nível 1 (código de quem se registou pelo utilizador 1). Não podes ir contar pelos utilizadores todos infinitos níveis de referidos em duas tabelas. Tens que separar a informação. Pelo que me dizes a coluna MyReferal serve tanto para código único de referido como para nivel 2 de referido. Isso não pode ser, a não ser que faças a separação dos dados dentro da row (o que ainda é mais complicado)

Tens que ter tantas tabelas como níveis de referidos e aquando o registo, tens que validar quem é o referido de quem e adicionar à BD.

Por exemplo (vou utilizar dígitos para ser mais fácil):
- Utilizador 2 regista-se com o código 1 (Fica com código de referido [MyReferal] 1)
- O nivel 1 de referido [patrocinador] do utilizador 2 é 1 e o código de referido [MyReferal] é 2
- O utilizador 3 regista-se pelo utilizador 2. É referido nível 1 [patrocinador] do utilizador 2 com o valor 2 e fica com o código de referido [MyReferal] 3.
- Numa terceira coluna [patrocinador2], o utilizador 1 fica com o valor 3.

Uma imagem para ser mais simples:
qYYMAtD.png


É suposto cada coluna na BD ter um propósito.
Se tens 2 níveis de referidos, tens que ter 3 colunas (código do referido, nível 1 e nível 2)
Se tivesses 10 níveis de referidos ias ter que ter 11 colunas (código de referido, nível 1..10)

A minha função o que faz (que foi o que percebi) é contar o número de referidos que têm o código X.
Depois desses existentes, vai contar quantos é que têm referidos e soma tudo.

Se queres ter mesmo 2 niveis de referidos, até te aconselho o seguinte:
- Usa a coluna userid (que presumo ser a chave primária da tabela) como código de referido. Assim consegues garantir que é sempre único. As strings que estás a usar não é garantido que serão sempre únicas (sim, podes criar uma função para ele criar um código para gerar o código até não existir na BD, mas estás sujeitos que passe a demorar muito tempo).
- Depois usas a MyReferal como nível 1 e a patrocinador como nível 2


Na minha óptica é a melhor forma de o fazer.
No entanto se quiseres fazer à tua maneira é fácil (apesar de vir a dar problemas). Não é uma função recursiva porque tens duas queries diferentes.
Primeiro fazes como tens.
Depois tens que fazer nova query dentro do foreach a pesquisar o Myreferal que extraiste com aquele código.
Depois em cada um desses resultados, comparas se os dados do patrocinador desse referido são iguais ao valor e aumentas o contador.
 
@myguel99 , testa algo assim:

function descer($mysqli, $codigo, $contador = 0){
$query = "SELECT user, myReferal, patrocinador FROM kp_membros WHERE patrocinador = ?";
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
$stmt->bind_param("s", $codigo);
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
if ($stmt_result->num_rows>0) {
while($row_data = $stmt_result->fetch_assoc()) {
$contador++;
$comp[] = $row_data['myReferal'];

}
foreach($comp as $value){
$query = "SELECT user, myReferal, patrocinador FROM kp_membros WHERE patrocinador = ?";
($stmt = $mysqli->prepare($query)) or trigger_error($mysqli->error, E_USER_ERROR);
$stmt->bind_param("s", $value);
$stmt->execute() or trigger_error($stmt->error, E_USER_ERROR);
($stmt_result = $stmt->get_result()) or trigger_error($stmt->error, E_USER_ERROR);
if ($stmt_result->num_rows>0) {
while($row_data = $stmt_result->fetch_assoc()) {
$contador++;
}
}
}
return $contador;
}
$stmt->close();
}

Não consigo criar função recursiva porque tens que guardar os valores a primeira vez numa array para depois ires buscar os dados. Se chamares novamente a função vais entrar num loop infinito porque está sempre a adicionar dados à array.
De qualquer das formas, penso que assim irá funcionar :)

(De qualquer das formas, sugiro-te a fazeres como expliquei no post anterior).
 
Tentei adaptar mas não me está a retornar o contador

Código:
function descer($conn, $codigo, $contador = 0){
            $q = "SELECT myReferal, patrocinador FROM kp_membros WHERE patrocinador = $codigo";
            $query = mysqli_query($conn, $q) or die(mysql_error());
            $row_cnt = mysqli_num_rows($query);
                if ($row_cnt>0) {
                    while($row_data = mysqli_fetch_array($query)) {
                        $contador++;
                        $comp[] = $row_data['myReferal'];
                    }
           
                    foreach($comp as $value){
                        $q2 = "SELECT myReferal, patrocinador FROM kp_membros WHERE patrocinador = $value";
                        $query2 = mysqli_query($conn, $q2) or die(mysql_error());
                        $row_cnt = mysqli_num_rows($query2);
                            if ($row_cnt>0) {
                                while($row_data = mysqli_fetch_array($query)) {
                                    $contador++;
                                }
                            }
                    }
            return $contador;
                }
           
            }
               
                echo descer($conn, $codigo, $contador = 0);

Não posso usar a tua função pois acho que tenho de instalar alguns drivers.
Ainda assim sem recursividade apenas estou a andar dois niveis para baixo certo?
O obejctivo é descer na arvore até que se atingam determinados numeros de users registados o que pode fazer com que se descam centenas de niveis dai ter de usar recursividade.
 
A minha função é PHP normal.
Se tiveres instalado o XAMPP ou WAMP é só utilizar.

Cada vez estou mais confuso. Desculpa =\
O que pediste foi uma função para contar todos os referidos diretos e indiretos associados a um 'código' em específico.
Essa função faz isso mesmo.

A primeira query vai buscar os referidos diretos do código X. A segunda query (dentro do foreach) vai buscar todos os referidos indiretos - ou seja, por cada referido direto, vai contar quantos referidos esse user tem (que são os indiretos do user principal).
Não estou a perceber a parte dos 2 níveis porque tu só queres contar referidos diretos + indiretos (2 níveis). Pelo menos foi o que percebi.

Isso tanto funciona caso tenha que percorrer 5000 users como 10...

Caso não seja esta a função que procuras, desculpa mas não estou mesmo a perceber o que pretendes.
 
Boas o que pretendo é uma função recursiva que desça na árvore tantos níveis quantos necessários ate que já não existem mais referidos.
Na bd só tem dois níveis mas pode ter muitos mais a medida que se registam pessoas, como estavas a dizer ia ter de fazer uma query por nível, dai esta situação só poder ser feita com recursividade.
 
A meu ver com a BD que apresentaste só podes ter dois níveis no máximo.

Dá-me um exemplo concreto onde existe um 3º ou 4º nível de referidos com a informação que passaste para eu tentar apanhar e ajudar-te sff :)
 
581JOxu.png


Por exemplo vamos supor que o user para queremos usar como topo da árvore, ou seja, contar a partir dele quantas pessoas patrocinou directa ou indirectamente foi o user id 181
com o myReferal 9582e4
Este user patrocinou o user 505, 502,508,510
Depois o user 505 com o myReferal 421c3f patrocinou o user 511 que por sua vez patrocinou o user 512 e depois poderia continuar ate que por exemplo o user 512 não patrocinasse mais ninguém e ai parava a função e retornasse o contador de todos os patrocinadores directos e indirectos.
O que eu pretendo e só mesmo a contagem nada mais e penso que a única maneira de fazer isto é com recursividade.
 
Select myReferral, count(*) from table where patrocinador=myReferral group by myReferral

Não é algo parecido com isto que queres?

Podes usar isto na função e usas recursividade para contar até ao pai.

O que me parece é que não sabes usar funções recursivas e aí aconselho te a estudar um pouco.

Não é difícil fazer o que queres mar convém parar para pensar em vez de bater código sem parar [emoji16]

Se precisares de ajuda avisa
 
Última edição:
581JOxu.png


Por exemplo vamos supor que o user para queremos usar como topo da árvore, ou seja, contar a partir dele quantas pessoas patrocinou directa ou indirectamente foi o user id 181
com o myReferal 9582e4
Este user patrocinou o user 505, 502,508,510
Depois o user 505 com o myReferal 421c3f patrocinou o user 511 que por sua vez patrocinou o user 512 e depois poderia continuar ate que por exemplo o user 512 não patrocinasse mais ninguém e ai parava a função e retornasse o contador de todos os patrocinadores directos e indirectos.
O que eu pretendo e só mesmo a contagem nada mais e penso que a única maneira de fazer isto é com recursividade.


Agarrei o que querias :)
Então é assim. No PHP deves evitar ao máximo utilizar recursividade, ainda por cima quando utilizas queries.

Eu pessoalmente optaria por uma abordagem diferente, no entanto o MySQL não gosta muito destas coisas.
Tal com o Slash indicou, se queres optar por esse caminho, vai ser complicado e também te sugiro a parares um pouco para veres como realmente isso funciona (que pessoalmente é uma das coisas mais estranhas de fazer).

Sempre podes tentar uma query que te faça logo isso em vez que andares com recursividade (Isto não foi testado, pelo pode conter erros):

Opção 1 (versão antiga mysql):
select userid,
myReferal,
patrocinador
from (select * from kp_membros
order by patrocinador, id) alinhamento_patrocinador,
(select @pv := $codigo) initialisation
where find_in_set(patrocinador , @pv) > 0
and @pv := concat(@pv, ',', id)


Opção 2 (versão recente mysqli):
with recursive kp_membros (userid, myReferal, patrocinador) as
(
select userid,
myReferal,
patrocinador
from kp_membros
where patrocinador = $codigo
union all
select p.userid,
p.myReferal,
p.patrocinador
from kp_membros p
inner join kp_membros
on p.patrocinador = kp_membros.userid
)
select * from kp_membros;

Não te esqueças que tens que fazer a contagem à mesma. Isso é só a query.
Desculpa não poder testar a ver se está tudo OK mas vai ser complicado porque não tenho muito tempo.
 
Select myReferral, count(*) from table where patrocinador=myReferral group by myReferral

Não é algo parecido com isto que queres?

Podes usar isto na função e usas recursividade para contar até ao pai.

O que me parece é que não sabes usar funções recursivas e aí aconselho te a estudar um pouco.

Não é difícil fazer o que queres mar convém parar para pensar em vez de bater código sem parar [emoji16]

Se precisares de ajuda avisa

Boas isso era o que já tinha feito na funcão na pagina anterior.
 
Agarrei o que querias :)
Então é assim. No PHP deves evitar ao máximo utilizar recursividade, ainda por cima quando utilizas queries.

Eu pessoalmente optaria por uma abordagem diferente, no entanto o MySQL não gosta muito destas coisas.
Tal com o Slash indicou, se queres optar por esse caminho, vai ser complicado e também te sugiro a parares um pouco para veres como realmente isso funciona (que pessoalmente é uma das coisas mais estranhas de fazer).

Sempre podes tentar uma query que te faça logo isso em vez que andares com recursividade (Isto não foi testado, pelo pode conter erros):

Opção 1 (versão antiga mysql):



Opção 2 (versão recente mysqli):


Não te esqueças que tens que fazer a contagem à mesma. Isso é só a query.
Desculpa não poder testar a ver se está tudo OK mas vai ser complicado porque não tenho muito tempo.

Não consigo testar essa query com cte não é possível no mysql aplicar recursividade em queries.

em relação á outra

Código:
function desceNaArvore($conn, $codigo){
  
    $q = "select
            myReferal,
            patrocinador
            from (select * from kp_membros
            order by patrocinador) alinhamento_patrocinador,
            (select @pv := '$codigo') initialisation
            where find_in_set(patrocinador , @pv) > 0
            and @pv := concat(@pv, ',')";
  
    $query = mysqli_query($conn, $q) or die(mysql_error());
  

    while ($row = mysqli_fetch_array($query)) {
  
        $contador++;
      
    }
        return $contador;
          
    }
  
    echo desceNaArvore($conn, $codigo, $contador = 0);

sem sucesso, dá 4 quando devia dar 6
Eu vou tentar resolver.
Obrigado.
 
Back
Topo