Collecting words from an input

2

I'm developing a (study-only) page for a bookstore. The variable titulo_livro receives the data of a input type='text' .

What do I need to do:

The title of the book will often contain more than one word. How do I collect these words, example ("O", "Acopolato", "Odysseus") and fetch them in the database?

The idea of the search is, by typing the full title of the book, the return of the DB can be by any one of the typed words, since the words ("O", "Acopolato", "Odysseus") could separately , to be in the title of some other book.

    
asked by anonymous 22.12.2017 / 18:42

2 answers

4
You can use LIKE and OR in the query and preg_split (equivalent to explode , but you can isolate more spaces without needing to filter) in PHP to split the string:

if (isset($_POST['busca']{0})) { //Tem que ter digita ao menos uma letra
    $buscas = preg_split('#\s+#', $_POST['busca']);

    ... aqui vai o código mysql, podendo usar a API PDO ou MSYQLI ...
}

If the form is POST use $_POST['busca'] , if not use $_GET['busca']

  

Note: If you are using UTF-8 please read this post: Doubt with charset = iso- 8859-1 and utf8

Using with MYSQLI

<?php

$mysqli = new mysqli('SERVIDOR', 'USUARIO', 'SENHA', 'BANCO');

if (mysqli_connect_errno()) {
    printf("Connect failed: %s\n", mysqli_connect_error());
    exit;
}

if (isset($_POST['busca']{0})) {

    $buscas = preg_split('#\s+#', $_POST['busca']);

    $qtdPalavras = count($buscas);

    //Gera os LIKEs
    $where = str_repeat('nome LIKE ? OR ', $qtdPalavras);
    $where = substr($where, 0, -4); // Remove o OR extra

    $query = 'SELECT id, nome, data FROM livros WHERE ' . $where . ' ORDER BY nome LIMIT 100';

    $stmt = $mysqli->prepare($query);

    if ($stmt) {

        //Adiciona os tipos de parâmetros
        array_unshift($buscas, str_repeat('s', $qtdPalavras));
        $qtdPalavras++;//Atualiza o total

        for ($i = 0; $i < $qtdPalavras; $i++) {

            //Evita adicionar o sinal de porcentagem no primeiro item, que são os tipos de parâmetros
            if ($i > 0) {

                //O sinal de porcentagem é necessário para busca em qualquer posição
                $buscas[$i] = '%' . $buscas[$i] . '%';
            }

            //Passa o valor como referencia (& - E comercial), pois bind_param não aceita variáveis normais
            $buscas[$i] = &$buscas[$i];
        }

        //Chava os valores da array como parametros
        call_user_func_array(array($stmt, 'bind_param'), $buscas);

        //Executa
        $stmt->execute();

        //Vá adicionando as colunas aqui que necessitar
        $stmt->bind_result($id, $nome, $ano);

        while ($stmt->fetch()) {
            echo 'Nome:', $nome, '<br>';
            echo 'Ano:', $ano, '<hr>';
        }

        $stmt->close();
    } else {
        die('Erro:' . $mysqli->error);
    }
}

The query according to the search will generate in a POST like "O Acopolato Odisseu" something like:

SELECT id, nome, ano FROM livros WHERE nome LIKE ? OR nome LIKE ? OR nome LIKE ? ORDER BY nome LIMIT 100

The queries get the values of bind_param and the bank will execute something like:

SELECT id, nome, ano FROM livros WHERE nome LIKE '%O%' OR nome LIKE '%Acopolato%' OR nome LIKE '%Odisseu%' ORDER BY nome LIMIT 100

Using with PDO

If PDO should look something like this:

<?php
try {
    $pdo = new PDO('mysql:host=SERVIDOR;dbname=BANCO', 'USUARIO', 'SENHA');
} catch (PDOException $e) {
    die('Connection failed: ' . $e->getMessage());
}

if (isset($_POST['busca']{0})) {

    $buscas = preg_split('#\s+#', $_POST['busca']);

    $qtdPalavras = count($buscas);

    //Gera os LIKEs
    $where = str_repeat('nome LIKE ? OR ', $qtdPalavras);
    $where = substr($where, 0, -4); // Remove o OR extra

    $sth = $pdo->prepare('SELECT id, nome, data FROM livros WHERE ' . $where . ' ORDER BY nome LIMIT 100');

    if ($sth) {

        for ($i = 0; $i < $qtdPalavras; $i++) {
           $buscas[$i] = '%' . $buscas[$i] . '%';
        }

        $response = $sth->execute($buscas);

        if ($response) {
            while ($row = $sth->fetch(PDO::FETCH_ASSOC)) {
                echo 'Nome:', $row['nome'], '<br>';
                echo 'Ano:', $row['data'], '<hr>';
            }
        } else {
            echo 'Erro: ';
            var_dump($sth->errorInfo());
        }
    }
}
    
22.12.2017 / 19:07
1

As stated in the comment WHERE COLUNA LIKE '%O%' OR COLUNA LIKE '%Acopolato%' OR .......

With PDO

if (isset($_POST['nameInput'])){

  //verifica se só contém espaços
  if (trim($_POST['nameInput'])===''){

    echo "<span style=\"font-size: 24px; color: red\";>nananicanão, só espaço vazio não pode</span>";

  }else{

  $input = $_POST['nameInput'];

  //Substituindo vários espaços por um único espaço
  $titulo_livro= preg_replace('!\s+!', ' ', $input);

    $hostname="localhost";  
    $username="USUARIO";  
    $password="SENHA";  
    $db = "NOME_DB"; 

    $con = new PDO("mysql:host=$hostname;dbname=$db", $username, $password);

    $titulo_livro = strtoupper($titulo_livro);
    //Retira as tags HTML e PHP
    $titulo_livro = strip_tags($titulo_livro); 
    //Retira espaço no ínicio e final
    $titulo_livro = trim($titulo_livro);
    $words = explode(' ', $titulo_livro);

    $words_condition = array();
    $arguments = array();

    foreach ($words as $word) {
        $words_condition[] = 'nomeColuna LIKE ?';
        $arguments[] = '%'.$word.'%';
    }

    $query = $con->prepare('SELECT * FROM nomeTabela WHERE '.implode(' OR ', $words_condition));

    $query->execute($arguments);

    if ($query->rowCount() > 0) {

        while ($row = $query->fetch(PDO::FETCH_ASSOC)) {
           //o que quer retornar relacione aqui
           echo 'Titulo:', $row['nomeColuna'], '<hr>';
        }
    }else{
       echo "<span style=\"font-size: 24px; color: red\";>Sua busca não retornou resultados</span>";
    }
  }
}   

with MYSQLI

We can construct the declaration as follows

//conexão
$servername = "localhost";
$username = "USUARIO";
$password = "SENHA";
$dbname = "NOME_DB";

$conn = new mysqli($servername, $username, $password, $dbname);
if (!$conn) {
die("Connection failed: " . mysqli_connect_error());
}

//pego via POST
$titulo_livro = mysqli_real_escape_string($conn, Trim($_POST['nameInput']));

$palavras = explode(" ", $titulo_livro);

$clausulaWhere = '';
foreach( $palavras as $palavra) {
   $clausulaWhere .= ' nomeColuna LIKE "%' . $palavra . '%" OR';
}

// Remove ultimo 'OR'
$clausulaWhere = substr($clausulaWhere, 0, -2);

$sql = "SELECT * FROM nomeTabela WHERE" . $clausulaWhere;

//echo $sql; 
//para $titulo_livro = "O copolato Odisseu" resulta
// SELECT * FROM nomeTabela WHERE nomeColuna LIKE "%O%" OR nomeColuna LIKE "%copolato%" OR nomeColuna LIKE "%Odisseu%"


$result = $conn->query($sql);

while($row = mysqli_fetch_assoc($result)) {
    echo  $row["nomeColuna"]."<br>";
}
    
22.12.2017 / 20:49