Simpele php / sql search

Overzicht Reageren

Sponsored by: Vacatures door Monsterboard

Bryan De Baar

Bryan De Baar

02/05/2019 23:12:09
Quote Anchor link
Goede avond,


Wat ik probeer is om een simpele zoek functie te maken voor een bepaalde tabel in de database.
Met hier en daar wat zoeken op internet heb ik nu dit

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<form action="" method="POST">
<input name="s" value="<?php echo $term; ?>"/>
<input type="submit" value="zoeken" name="submit"/>
</form>

<?php
if(isset($_POST["submit"])){
    $term = $_POST['s'];
    $term = htmlspecialchars($term);
    $term = mysqli_real_escape_string($term);      
    $raw_results = mysqli_query("SELECT * FROM info WHERE ('place' LIKE '%".$term."%')");
    if(mysqli_num_rows($raw_results) > 0){
        while($results = mysqli_fetch_array($raw_results)){
            echo "<p><h3>".$results['place']."</h3></p>";
        }  
    }
else{
        echo "No results";
    }
}

?>


in de database heb ik 2 records gemaakt in de kolom place heb ik "Amsterdam en Eindhoven".

Als ik een van beide invul blijf ik toch nog 'No results' krijgen
 
PHP hulp

PHP hulp

26/11/2020 22:03:23
 
Thomas van den Heuvel

Thomas van den Heuvel

02/05/2019 23:30:32
Quote Anchor link
Place is een kolomnaam, hier dienen dus geen quotes omheen te staan. Anders vergelijk je een letterlijke waarde met iets anders wat geen matches oplevert.

Het lijkt mij beter om zoekfunctionaliteit via GET te laten verlopen.

En htmlspecialchars() lijkt mij niet nodig, tenzij alles in je database ook ge-htmlspecialchars()d is, wat mij geen goede zaak lijkt als dat aan de orde is...
 
Bryan De Baar

Bryan De Baar

03/05/2019 19:57:41
Quote Anchor link
@thomas,

Het functioneert nu :) inderdaad zonder de quotes maar ik zag ook een foutje in SQL staan.
Waarom zou jij kiezen om de GET methode te gebruiken i.p.v. POST?

Dan heb ik nog een vraag betreft SQL, ik zoek nu in 2 kolommen namelijk 'place' en 'location'
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php

$min_length
= 3;
$term = $_POST["s"];
    if(strlen($term) >= $min_length){    
        $raw_results = mysqli_query($conn, "SELECT * FROM info WHERE place LIKE '%$term%' OR location LIKE '%$term%'");
        if(mysqli_num_rows($raw_results) > 0){
            while($results = mysqli_fetch_array($raw_results)){
                echo "<p>".$results['location']."<h3>".$results['place']."</h3></p>";
            }  
        }
else{
            echo "No results";
        }
    }

?>


In de kolom location staan bijvoorbeeld de waarde 'Amsterdam' Eindhoven, Utrecht'
in de kolom location staan de waarde 'Park, station, markt'

Als ik zoek op alles afzonderlijk krijg ik altijd netjes resultaat. Maar hoe maak ik de juiste query als ik bijvoorbeeld zoek op 'Park amsterdam'.
Nu krijg ik geen resultaat terug.

Moet ik dan php explode gebruiken om elke woord apart te behandelen en vervolgens met een foreach de query uitvoeren?
 
- Ariën -
Beheerder

- Ariën -

03/05/2019 20:09:47
Quote Anchor link
Met GET krijg je niet steeds een bevestiging van je browser als je een formulier opnieuw verzendt. Bij POST juist wel. En je kan ook handig een directe link maken naar je zoekopdracht.
 
Adoptive Solution

Adoptive Solution

03/05/2019 20:12:12
Quote Anchor link
Ik heb een tabel platen met velden titel en artiest.

Zoek naar beide velden zo :

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
select titel, artiest from platen where concat(titel, ' ' , artiest) = 'Tapestry Carole King'


Voor 'Tapestry Carole King' kan ook de POST of GET variabelen gebruiken.
 
Thomas van den Heuvel

Thomas van den Heuvel

03/05/2019 21:19:41
Quote Anchor link
Je zou locaties als checkboxen op kunnen nemen in je zoekformulier en kunnen toevoegen als extra conditie in je query indien er een of meer aangevinkt zijn.

@Adoptive het nadeel daarvan is volgorde/exacte match. Als er ook maar iets verkeerd is ingevuld of ingevuld in de verkeerde volgorde heb je geen match.

Als je niet wilt dat er ruimte is voor het maken van dit soort fouten zorg dan dat deze fouten niet gemaakt kunnen worden door het niet af te laten hangen van datgene wat een gebruiker kan invullen maar laat deze kiezen uit vaste waarden (dropdown, checkbox, radio of zelfs autocompletes). Die waarden hebben dan in ieder geval potentieel om nog iets op te leveren.
Gewijzigd op 04/05/2019 00:49:56 door Thomas van den Heuvel
 
Rob Doemaarwat

Rob Doemaarwat

04/05/2019 09:37:13
Quote Anchor link
Bryan De Baar op 03/05/2019 19:57:41:
Moet ik dan php explode gebruiken om elke woord apart te behandelen en vervolgens met een foreach de query uitvoeren?

Ja.

Wat wil je: zoeken op "park" en "amsterdam".
Hoe doe je dat in SQL: where place like "%park%" and place like "%amsterdam%"
Hoe kneed je dat in PHP:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
<?php
$where
= [];
if($q = trim($_GET['q'] ?? null)){ //of zoiets in ieder geval q = 'park amsterdam'
  $words = preg_split('/\\s+/',$q); //splitsen op white-space = alle losse woorden
  foreach($words as $word)
    $where[] = "place like '%" . mysqli_real_escape_string($conn,$word) . "%'";
}

$sql = 'select * from info' . ($where ? ' where ' . implode(' and ',$where) : '');
//enz
?>

Splitsen met preg_split ipv explode heeft als voordeel dat meerdere spaties, tabs, enz allemaal verdwijnen. Evt. zou je zelfs preg_split('/\\W+/',$q) kunnen doen = splitsen op alle karakters die geen letter of cijfer zijn (of underscore). Bij "park amsterdam-west" zoek je dan dus op "park", "amsterdam", en "west".

2019-05-04 14:00: Nog wat lopen klungelen aan de PHP code. Je kunt er natuurlijk ook voor kiezen om bij een lege $where helemaal niks te doen (of een melding te geven "geef een locatie op").
Gewijzigd op 04/05/2019 14:11:05 door Rob Doemaarwat
 
Jop B

Jop B

04/05/2019 18:20:21
Quote Anchor link
Als je op beide kolommen en elk word wilt checken voor resultaat kun je dit doen

Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<?php
$words
= preg_split('/\\s+/',$_GET["s"]);
    
foreach($words as $word){
    $raw_results = mysqli_query($conn, "SELECT * FROM info WHERE place LIKE '%$word%' OR location LIKE '%$word%'");
}
    
        
if(mysqli_num_rows($raw_results) > 0){
    while($results = mysqli_fetch_array($raw_results)){
        echo "<p>".$results['location']."<h3>".$results['place']."</h3></p>";
    }  
}
else{
    echo "No results";
}

?>
 
Rob Doemaarwat

Rob Doemaarwat

04/05/2019 20:00:03
Quote Anchor link
@Jop: dit werkt niet. $raw_results zal alleen het resultaat van het laatste woord bevatten.

Daarnaast: SQL input escapen (SQL-injectie), HTML output escapen.
Gewijzigd op 04/05/2019 20:03:23 door Rob Doemaarwat
 
Jop B

Jop B

04/05/2019 21:10:03
Quote Anchor link
hmm inderdaad. Maar hij heeft het over 2 kolommen waar hij in wil zoeken.
- Locatie
- Plaats

Ik neem aan dat hij zo een soort data heeft:

plaats locatie
Amsterdam Park, Station
Maastricht Station, Mc Donalds
Eindhoven Gemeentehuis
Utrecht Mc Donalds


En zoekt op:
Amsterdam -> resultaat = Plaats: Amsterdam Locatie: Park, Station
Maastricht Mc Donalds -> resultaat = Plaats Maastricht Locatie: Mc Donalds
Mc Donalds -> resultaat = Plaats: Maastricht, Utrecht Locatie: Mc Donalds

Loop je dan niet alle keywoorden maar ook niet de kolommen?
 
Rob Doemaarwat

Rob Doemaarwat

04/05/2019 21:31:43
Quote Anchor link
Zoeken in zowel `place` als `location` (in 1 vd 2 voorkomen is voldoende = "OR" binnen de "AND"):
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$where
= [];
if($q = trim($_GET['q'] ?? null)){ //of zoiets in ieder geval q = 'park amsterdam'
  $words = preg_split('/\\s+/',$q); //splitsen op white-space = alle losse woorden
  foreach($words as $word){
    $word = mysqli_real_escape_string($conn,$word);
    $where[] = "(place like '%$word%' or location like '%$word%')";
  }
}

$sql = 'select * from info' . ($where ? "\nwhere " . implode("\n  and ",$where) : '');
//enz
?>

Zoeken op "park amsterdam" levert nu $sql =
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
select * from info
where (place like '%park%' or location like '%park%')
  and (place like '%amsterdam%' or location like '%amsterdam%')
Gewijzigd op 04/05/2019 21:35:21 door Rob Doemaarwat
 
Bryan De Baar

Bryan De Baar

05/05/2019 19:07:53
Quote Anchor link
Rob,

Dit werkt inderdaad zoals ik het had gedacht:)
Maar ik zie dat je shorthand code hebt gebruikt waarmee ik helemaal niet mee bekend ben. Zou je misschien kunnen uitleggen wat er in het script gebeurd bij de shorthands?
 
Rob Doemaarwat

Rob Doemaarwat

05/05/2019 19:28:40
Quote Anchor link
Geen idee welke je bedoelt:
Code (php)
PHP script in nieuw venster Selecteer het PHP script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
<?php
$q
= $_GET['q'] ?? null;
//dit is hetzelfde als:
if(isset($_GET['q'])) $q = $_GET['q'];
else $q = null;
//maar ik had er dan nog een trim() omheen


preg_split('/\\s+/',$q)
/*
/\\s+/ is een regular expression
/    / is de afbakening (ander karakter kan ook, dit wordt veel gebruikt -
       bijvoorbeeld in javascript)
 \\s   dit "matcht" een white-space karakter (spatie, tab, enz); dubbele \\ omdat er
       dan een enkele overblijft (escapen); een enkele \ gaat vaak goed, maar kan soms
       fout gaan, daarom doe ik uit gewoonte altijd \\
    +  1 of meer matches (dus niet nul)
deze hele riedel splitst de $q dus op witruimte; 'aa  bb   cc' wordt dus gesplitst
in ['aa','bb','cc'], waar je met explode(' ',$q) -> ['aa','','','bb','','','','cc']
zou krijgen (merk op dat ik vooraf al een trim() heb gedaan om van white-space aan
begin en eind af te komen).
*/



$sql = 'select * from info' . ($where ? "\nwhere " . implode("\n  and ",$where) : '');
//dit is hetzelfde als:
$sql = 'select * from info';
if($where) $sql .= "\nwhere " . implode("\n  and ",$where);
else $sql .= ''; //maar dit is niet echt noodzakelijk / voegt niks toe
?>

Het scheelt dus meestal wat type werk, of een extra regel.

Zie https://php.net/ternary#language.operators.comparison.ternary
Gewijzigd op 05/05/2019 19:34:15 door Rob Doemaarwat
 



Overzicht Reageren

 
 

Om de gebruiksvriendelijkheid van onze website en diensten te optimaliseren maken wij gebruik van cookies. Deze cookies gebruiken wij voor functionaliteiten, analytische gegevens en marketing doeleinden. U vindt meer informatie in onze privacy statement.