Reputation: 225
I have a search that is functional but the issue is that it can only search the exact samething as in the database. I've tried to implement mysql multiple keyword search in any order but to no success. The thing I hope you guys can help me with is a solution to search multiple keywords. Thanks in advance!
Controller:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class VoorraadlijstenController extends Controller
{
/**
* @Route ("/voorraadlijst", name="voorraadlijst")
*/
public function voorraadlijstHomepage(Request $request){
//Variabelen
$search = $request->get('q');
$em = $this->getDoctrine()->getManager();
//Ophalen van data uit database.
if ($search) {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a WHERE a.artikelnummer LIKE :query OR a.omschrijving LIKE :query ORDER BY a.omschrijving ASC')
->setParameter('query', '%'.$search.'%');
}
else {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a ORDER BY a.omschrijving ASC');
}
//Verwijzing naar overzicht & en variabelen die hij meegeeft
return $this->render('voorraadlijst.html.twig', [
'voorraad' => $voorraad->getResult(),
'q' => $search
]);
}
}
?>
Twig (With the search form)
{% extends 'layout/default.html.twig' %}
{% block content %}
{#Style voor de wrapper#}
<style>
.wrapper {
height: 130px;
min-height: 150px
margin: 10px;
padding: 30px;
}
table {
table-layout: fixed;
zoom: 80%
}
{#Style voor de zoekformulier#}
.zoekformulier{
padding: 20px;
margin-top: 20px;
}
</style>
{#Heading#}
<div class="wrapper" style="background-color:#E9ECEF">
<div class="container">
<h3 class="display-4"><center>Voorraadlijst week 29</center></h3>
</div>
</div>
{#Zoekformulier#}
<div class= "zoekformulier">
<form>
<input name="q" value="{{ q }}" placeholder="Artikelnummer of omschrijving" />
<button type="submit">Zoeken</button>
</form>
</div>
<div class="container-fluid">
<div class="row">
<div class="col-md-12">
<table class="table table-striped">
<thead>
<tr>
<th scope="col">Artikelnummer</th>
<th>Omschrijving</th>
<th>Adviesprijs</th>
<th>Nu beschikbaar</th>
<th>Eerste LEV Verwacht</th>
<th>Beschikbaar na eerste LEV</th>
<th>Tweede LEV Verwacht</th>
<th>Beschikbaar na tweede LEV</th>
<th>Derde LEV Verwacht</th>
<th>Beschikbaar na derde LEV</th>
<th>Korting %</th>
<th>Korting €</th>
<th>Opmerking</th>
</tr>
</thead>
<tbody>
{% for artikel in voorraad %}
<tr>
<th scope="row">{{ artikel.artikelnummer }}</th>
<td>{{ artikel.omschrijving }}</td>
<td>{{ artikel.adviesprijs }}</td>
<td>{{ artikel.nuBeschikbaar }}</td>
<td>{{ artikel.eersteLevVerwacht }}</td>
<td>{{ artikel.beschikbaarNaEersteLev }}</td>
<td>{{ artikel.tweedeLevVerwacht }}</td>
<td>{{ artikel.beschikbaarNaTweedeLev }}</td>
<td>{{ artikel.derdeLevVerwacht }}</td>
<td>{{ artikel.beschikbaarNaDerdeLev }}</td>
<td>{{ artikel.kortingProcent }}</td>
<td>{{ artikel.kortingEuro }}</td>
<td>{{ artikel.opmerking }}</td>
</tr>
{% endfor %}
</tbody>
</table>
</div>
</div>
<hr>
</div>
{% endblock %}
Edit: I tried to implement explode function:
/**
* @Route ("/voorraadlijst", name="voorraadlijst")
*/
public function voorraadlijstHomepage(Request $request){
//Variabelen
$search = explode(" ", $request->get('q'));
$em = $this->getDoctrine()->getManager();
$waarde = '';
foreach ($search as $key => $value) {
$waarde .= ' AND a.omschrijving LIKE "%'.$value.'%"';
}
if ($search) {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a WHERE a.artikelnummer LIKE :query OR a.omschrijving LIKE :query ORDER BY a.omschrijving ASC')
->setParameter('query', '%'.$value.'%');
}
else {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a ORDER BY a.omschrijving ASC');
}
//Verwijzing naar overzicht & en variabelen die hij meegeeft
return $this->render('voorraadlijst.html.twig', [
'voorraad' => $voorraad->getResult(),
'q' => $value
]);
}
I think I made some progress, but the it searches only for the last keyword I think. Where am I going wrong?
Upvotes: 1
Views: 1094
Reputation: 225
So basically I added the explode function and some parameters:
<?php
namespace AppBundle\Controller;
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Route;
use Symfony\Bundle\FrameworkBundle\Controller\Controller;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Response;
class VoorraadlijstenController extends Controller
{
/**
* @Route ("/voorraadlijst", name="voorraadlijst")
*/
public function voorraadlijstHomepage(Request $request){
//Variabelen
$zoek = $request->get('q');
$search = explode(" ", $request->get('q'));
$em = $this->getDoctrine()->getManager();
$waarde = '';
foreach ($search as $key) {
$waarde .= '%'.$key.'%';
}
$parameter = [];
$parameters['query1'] = '%'.$zoek.'%';
$parameters['query2'] = '%'.$waarde.'%';
//Ophalen van data uit database.
if ($search) {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a WHERE a.artikelnummer LIKE :query1 OR a.omschrijving LIKE :query2 ORDER BY a.omschrijving ASC')
->setParameters($parameters);
}
else {
$voorraad = $em->createQuery('Select a FROM AppBundle:Voorraadlijst a ORDER BY a.omschrijving ASC');
}
//Verwijzing naar overzicht & en variabelen die hij meegeeft
return $this->render('voorraadlijst.html.twig', [
'voorraad' => $voorraad->getResult(),
'q' => $zoek
]);
}
}
?>
Upvotes: 0
Reputation: 126
I'll give you a full example when I am in front of my computer (on my phone now) but you need to loop ad 'and like :word1', (and like :word2, etc...). After you call set parameter word1, word2, etc.
Upvotes: 0
Reputation: 126
Explode return a array you need to loop and add each section
Upvotes: 0
Reputation: 126
This is more a database design questions than pure Symfony/doctrine.
If you want complex/flexible search system you should use something like elastic search.
Other wise if you want all the word to be found you could split by words (using explode) and then loop through them add a 'and like "%$word%" ' to your query. Draw side this will also find row that have smaller portikn of the word in it or fin row word that have more words than what the user is looking for.
To get back in elastic search it can do fuzzy search and sort by revelency etc... So you do not need to do any magic on your side. You should look into that.
Upvotes: 1