Usamos cookies para medir audiência e melhorar sua experiência. Você pode aceitar ou recusar a qualquer momento. Veja sobre o iMasters.
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?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?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 '>'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");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'];
?>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 ...
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.
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. :)Sim, essa era a duvida, vlw ai!
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
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?
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.
é 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