Ir para conteúdo

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

RogerTi

duvida com bindParam()

Recommended Posts

Pessoal estou fazendo uma função aqui para um portal de noticias, ela consiste em mostrar algumas noticias, eu seleciono as noticias a partir da ultima data de forma decrescente

porem eu chamo a função na primeira vez com limite 1, nas outras o limite é alterado, mas de forma que não exiba a ultima noticia novamente, até ai tudo bem, o problema é o seguinte

eu preciso usar um operador logico que não é statico na função, ele muda de acordo com a chamada da função

public function selecionar_noticias($tema, $operadorlogico,$ultimadata, $quantidade){
        try{
            $query = "SELECT * FROM noticia WHERE tema = :tema AND data_post ".$operadorlogico." :data ORDER BY data_post DESC  LIMIT :quantidade";
            $this->Selecionar = $this->Conn->prepare($query);
            $this->Selecionar->bindParam(':tema'      , $tema           , PDO::PARAM_STR);
            $this->Selecionar->bindParam(':data'      , $ultimadata     , PDO::PARAM_STR);
            $this->Selecionar->bindParam(':quantidade', $quantidade     , PDO::PARAM_INT);
            $this->Selecionar->execute();
            if($this->Selecionar->rowCount() > 0){
                return $this->Selecionar->fetchAll(PDO::FETCH_ASSOC);
            }
        } catch (PDOException $ex) {

        }
    }

porem se eu colocar ele assim

$query = "SELECT * FROM noticia WHERE tema = :tema AND data_post :operador :data ORDER BY data_post DESC  LIMIT :quantidade";
$this->Selecionar->bindParam(':operador'      , $operadorlogico           , PDO::PARAM_STR);

não funciona, alguem sabe pq?

Compartilhar este post


Link para o post
Compartilhar em outros sites

é porque o operador não é um nome de campo, ele tem que ser passando como ele realmente é. se tu butar os operadores numa select tu pode passar ele sem problema porque o usuário não pode inserir dado extra nele

Compartilhar este post


Link para o post
Compartilhar em outros sites

tipo, o grande medo ai é só SQLInjection, a função é chamada assim

 

$noticias_curiosidades = $NoticiasPDO->selecionar_noticias('Curiosidade', '>', $ultimadata, 3);

na própria pagina, então o usuário não insere dado algum, é apenas para separação de conteúdo em cada parte do site.

Acha que tem algum problema em fazer da forma que funcionou?

Compartilhar este post


Link para o post
Compartilhar em outros sites

bem tu pode ainda verificar se tem mais de um caractere sendo passado ou usar um preg_match pra validar de forma a passar só os caracteres validos para o caso tipo

 

$operadorlogico = substr($_POST['operadorlogico'], 0, 1);

 

se tiver mais coisa acrescentada nele só vai passar o primeiro caractere, também pode checar se tem mais de um caractere

 

$operadorlogico = ((str_len($_POST['operadorlogico']) == 1) ? $_POST['operadorlogico'] : '>');

 

nesse caso se tiver só um caractere vai ser usado ele e se tiver mais de um fica apenas '>'

Compartilhar este post


Link para o post
Compartilhar em outros sites

 Até o momento não tem, ou pelo menos desconheço, como tratar isso diretamente pelo PDO, segue uma sugestão:
 

$validOperators = array('=', '>=', '>', '<=', '<');
    
if (!in_array($operator, $validOperators)) {
   throw new Exception('Invalid operator: ' . $operator . ')';
}

$stmt = $conn->prepare("select * from table where :column $operator :value");

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Ficou da seguinte forma

public function selecionar_noticias($tema, $operadorlogico,$ultimadata, $quantidade){
        try{
            $validOperators = array('=', '>=', '>', '=<', '<');    
            if (!in_array($operadorlogico, $validOperators)) {
               throw new Exception('Operador invalido $operadorlogico ' . $operadorlogico);
            }
            $query = "SELECT * FROM noticia WHERE tema = :tema AND data_post $operadorlogico :data ORDER BY data_post DESC  LIMIT :quantidade";
            $this->Selecionar = $this->Conn->prepare($query);
            $this->Selecionar->bindParam(':tema'      , $tema           , PDO::PARAM_STR);
            $this->Selecionar->bindParam(':data'      , $ultimadata     , PDO::PARAM_STR);
            $this->Selecionar->bindParam(':quantidade', $quantidade     , PDO::PARAM_INT);
            $this->Selecionar->execute();
            if($this->Selecionar->rowCount() > 0){
                return $this->Selecionar->fetchAll(PDO::FETCH_ASSOC);
            }
        } catch (PDOException $ex) {

        }
    }

Em relação aos outros dados, eu preciso fazer uma verificação em seus valores? Digo que não existe o formulario para ser alterado os dados, essa função é função de carregamento de pagina, quando o cara entrar na index do site vai abrir cada sessão do site com varias noticias separadas por tema, preciso fazer uma verificação em cada  variavel? Uma vez que tema é FK da tabela noticia, caso não tenha vai retornar 0 ou null.

 

a função é chamada dessa forma na pagina 

 

$noticias_curiosidades = $NoticiasPDO->selecionar_noticias('Curiosidade', '>', $ultimadata, 3);
                            if($noticias_curiosidades != FALSE){
                                foreach ($noticias_curiosidades as $x){
                                    $not_titulo    = $x['titulo'];
                                    $cur_banner    = $x['banner'];
                                    $not_descricao = $x['descricao'];
                                    ?>

 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Roger, não entendi muito bem essa ultima questão, vou tentar responder de forma genérica, do que acho que seja a questão.

Precisamos sempre tratar dados que vem do usuário, e no caso de não poder tratar esse valor pelo PDO, por exemplo, com bindValue,  em  $sql = "...   limit :limit"; Ai temos que validar com outras funções do PHP, como is_int() , FILTER_SANITIZE_NUMBER_INT ...

Compartilhar este post


Link para o post
Compartilhar em outros sites

Correto, estou falando que os dados ai eles são de carregamento do conteudo da pagina, exemplo, você entra agora no site da globo.com e já carrega as ultimas notícias, essa função é justamente para isso, quando a pessoa entrar no site carregar as ultimas notícias, então não tem contato com o usuário, contato por formulario que digo.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Por exemplo:

$this->Selecionar->bindParam(':tema', $tema, PDO::PARAM_STR);
$this->Selecionar->bindParam(':data', $ultimadata, PDO::PARAM_STR);
$this->Selecionar->bindParam(':quantidade', $quantidade, PDO::PARAM_INT);

 

No caso de $tema, $ultimadata e $quantidade serem variaveis criadas por você mesmo, que não veem da pagina do usuario, você esta na duvida se precisa tratar elas? Se for isso, não precisa! Já vi gente defendendo que não custa nada, na verdade custa, custa muito pouco, mas custa. :)
 

Compartilhar este post


Link para o post
Compartilhar em outros sites

Talvez seja mais apropriado um tópico sobre, mas vou colocar os testes que fiz, e quem tiver interesse...

Criando ambiente, no Mysql:

create database Imasters;
use Imasters;
create table php_pdo
(
id int auto_increment primary key,
nome varchar(10),
funcao varchar(10),
objetivo varchar(25)
);


Inserindo registro para teste (Não critiquem esse insert, não vem ao caso :) )

$db = new \PDO("mysql:host=localhost;dbname=Imasters", "root", "");

for($contador = 0; $contador < 15000; $contador++) {
    $db->exec("INSERT INTO php_pdo (nome,funcao,objetivo) VALUES ('PHP PDO','bindValue','teste de desempenho')");    
}


Primeiro teste, com execute e bindValue:

$start = microtime(true);
$sql = "select * from php_pdo where nome = :nome and funcao = :funcao";
$stmt = $db->prepare($sql);
$stmt->bindValue(':nome', 'PHP PDO');
$stmt->bindValue(':funcao', 'bindValue');
$stmt->execute();
$result = $stmt->fetchall(\PDO::FETCH_ASSOC);

$total = (microtime(true) - $start);
echo $total;


Amostra de sete resultados, com execute, com bindValue()
 

0.040969848632812
0.049991130828857
0.044628858566284
0.079172134399414
0.042876005172729
0.041944980621338
0.047070026397705

Segundo teste, com execute e sem bindValue()

$start = microtime(true);
$sql = "select * from php_pdo where nome = 'PHP PDO' and funcao = 'bindValue'";
$stmt = $db->prepare($sql);
$stmt->execute();
$result = $stmt->fetchall(\PDO::FETCH_ASSOC);
$total = (microtime(true) - $start);
echo $total;


Amostra de sete resultados, com execute, sem bindValue:
 

0.023535013198853
0.031256914138794
0.044435024261475
0.042974948883057
0.037087202072144
0.052536964416504
0.030627012252808


Terceiro teste, com query:

$start = microtime(true);
$sql = "select * from php_pdo where nome = 'PHP PDO' and funcao = 'bindValue'";
$resultado = $db->query($sql, PDO::FETCH_ASSOC)->fetchall();
$total = (microtime(true) - $start);
echo $total;


Amostra de sete resultados, com query:
 

0.031246900558472
0.027747869491577
0.026332855224609
0.02532696723938
0.027284145355225
0.02863597869873
0.023416996002197
 

Os teste foram executados em um ambiente isolado (vps na digitalocean) com as seguintes configurações: 


Memoria 1 GB 
1 CPU, 
30 GB SSD,
PHP 7.1

Debian 8.7 x64
Mysql 5.5.54

Compartilhar este post


Link para o post
Compartilhar em outros sites

Da forma que entendi o 3° teste foi o resultado mais rapido, porem ele não trata a variavel com statement?

 

no caso, seria a melhor forma para variaveis que são criadas no ambiente, e não inseridas por algum usuário?

Compartilhar este post


Link para o post
Compartilhar em outros sites

Roger, se for considerar apenas essas amostras, seria isso mesmo. Mas esses simples testes estão longe de provar alguma coisa. Infelizmente, pelo menos nas minhas pesquisas, também não encontrei nada mais concreto sobre o assunto. Bom, mas fica aqui o espaço para quem possui um melhor conhecimento do assunto e quiser compartilhar.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.