Bonjour a tous,
Je viens sollicité votre aide après plusieurs échec de ma part.
J'essaie de mettre en place un système de recherche dans mon site cependant je n'arrive pas a avoir le résultat que je souhaite.
Ma recherche dois s'effectue sur plusieur table :
* articles => contient les produits et la categorie( category_id)
* users => contient les emplacements geographique ( state_id, province_id et city_id)
* categories => contient la liste des categories
J'effectue une requete GET depuis mon formulaire et debug($this->request->query) me retourne :
array(
'name' => '',
'state_id' => '',
'province_id' => '',
'city_id' => '',
'category_id' => '',
'price_min' => '',
'price_max' => ''
)
Pour avoir la pagination sur le site, j'utilise Paginator.
Ma methode recherche ressemble a cela pour l'instant :
public function search(){
$this->set('title_for_layout','Ewant - Recherche');
if(!empty($this->request->query) && $this->request->is('get')){
debug($this->request->query);
$this->paginate = array(
"ArticlesShopsUser" => array(
'limit' => 15,
'order' => array(
'Article.created' => 'desc'
),
'conditions' => array(
'Article.online' => 1,
'Article.isValid' => 1,
'OR' => array(
'Article.name LIKE' => '%'.trim($this->request->query'name']).'%'
)
)
)
);
$articles = $this->Paginator->paginate('ArticlesShopsUser');
debug($articles);
}
}
Je n'arrive pas a ajoute d'autre conditions, lorsque les différentes requêtes GET tel que state_id, province_id et city_id sont defini.
Un utilisateur a une region, un departement et une ville.
Les articles appartiennent seulement a une boutique.
Une boutique appartient a un et un seul utilisateur.
Du coup pour faire un système de recherche, je me demandais si il ne suffirait pas de rajouter dans articles le user_id ?
ArticlesShopsUser est une table qui comprend les trois tables (articles, shops et users).
Je souhaite éviter une récursivité à 2 pour les performances.
Si vous avez une petite idée de comment pourrais je sortir de ce petit blocage, je vous remercie d'avance :)
Cordialement AcidBrun.
Bon c'est un peu dégueulasse mais le principe est là
public function search($get) {
$prixMax = 99999999;
$prixMin = 0;
if(!empty($get'price_max'])){
$prixMax = h($get'price_max']);
}
if(!empty($get'price_min'])){
$prixMin = h($get'price_min']);
}
$a = array(
'AND' = > array(
'Article.price BETWEEN ? AND ?' = > array($prixMin, $prixMax)
)
);
foreach($get as $k => $v){
if($k != 'name' && $k != 'price_max' && $k != 'price_min' && !empty($v)){
if($k != 'category_id'){
$a'AND']'User.'.$k] = h($v);
}else{
$a'AND']'Article.category_id'] = h($get'category_id']),
}
}
}
}
if(getNameConditions($get)){
$a'AND']'OR'] = getNameConditions($get);
}
}
private function getNameConditions($get){
if(empty($get'name'])){
return false;
}else{
return array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
);
}
}
J'ai fait mes tests a cote et j'ai le résultat attendu, cependant le code est assez répétitif :
$get = $this - > request - > query;
if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']) && !empty($get'price_min']) && !empty($get'price_max'])) {
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array(h($get'price_min']), h($get'price_max']))
)
);
} else if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']) && !empty($get'price_min']) &&
empty($get'price_max'])
) {
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array(h($get'price_min']), 99999999)
)
);
}
.....
.....
.....
Ca test pour different cas, si le category_id est vide ou non, si tout est vide sauf la recherche par prix etc....
Si vous avez une methode qui pourrais me faire passer de 500 lignes à 100, je vous serai tres reconnaissant ;)
Cordialement AcidBrun
Bonjour, pourrais-tu repréciser les tables , leur champs et les liaisons à faire entre elles? je m'y perds dans ton premier post..
cordialement
array(
'Article.name' => '',
'Article.category_id' => '',
'User.state_id' => '',
'User.province_id' => '',
'User.city_id' => '',
// BETWEEN de Article.price
'price_min' => '',
'price_max' => ''
)
Ouais mais au final ça ne sert a rien la boutique.
Avec mes tonnes de conditions, je suis parvenu a 600 - 700 lignes juste pour faire une recherche avec les champs recuperer via $this->request->query.
Je trouve mon code assez repetitif et aussi lourd, car je ne m'y retrouve plus trop, en tout cas cela renvoi bien le resultats de la recherce.
Sauf que maintenant
if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']) && !empty($get'price_min']) && !empty($get'price_max'])) {
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array(h($get'price_min']), h($get'price_max']))
)
);
}
Ce code la a du être répété une dizaine de fois. Mais maintenant je ne sais pas comment l'alleger.
Il dois surement exister une astuce que j'ai pas encore acquise pour passer de 600 - 700 lignes a 50 - 100 lignes, :p
J'ai du mal à visualiser ce que tu veux faire..
Quels sont les champs de recherche obligatoires et ceux qui ne le sont pas?
Tu vois le site "Leboncoin", ils ont un formulaire de recherche qui cherche seulement lorsque certain champs ne sont pas vides.
Hey bien sur mon projet je dois faire un formulaire de recherche dans le même style.
'name' => '', //Obligatoire ou Non?
'state_id' => '',//Obligatoire ou Non?
'province_id' => '',//Obligatoire ou Non?
'city_id' => '',//Obligatoire ou Non?
'category_id' => '',//Obligatoire ou Non?
'price_min' => '',//Obligatoire ou Non?
'price_max' => ''//Obligatoire ou Non?
Donc ils ne le sont pas tous le temps.. Quels sont ceux obligatoire (je veux dire sans conditions, ils doivent être remplies) et ceux qui sont optionnels?
Juste avec ton intervention, je viens d'enlever pas mal de lignes :p
Premiere recherche cela peut donner :
'name' => '', //Obligatoire
'state_id' => '',//Obligatoire
'province_id' => '',//Obligatoire
'city_id' => '',//Obligatoire
'category_id' => '',//Obligatoire
'price_min' => '',//Obligatoire
'price_max' => ''//Obligatoire
Deuxieme recherche cela peut donner :
'name' => '', //Non Obligatoire
'state_id' => '',//Obligatoire
'province_id' => '',//Non Obligatoire
'city_id' => '',//Non Obligatoire
'category_id' => '',//Obligatoire
'price_min' => '',//Obligatoire
'price_max' => ''//Non Obligatoire
Merci :)
Première recherche et deuxième recherche??
Tu gardes en mémoire la première recherche lors de l'exécution de la 2eme?
Je ne garde rien en mémoire c’était un exemple, pour dire que si certains champs sont obligatoires c'est qu'ils étaient pas vides et contenait des informations. Et ainsi il fait la recherche dans la base de donnée pour me renvoyer le résultat avec les informations qu'il a reçu.
Un autre exemple de gain de place (sous réserves des réponses aux questions précédentes)
ICI: il n'a que la valeur prix qui est soit vide soit rempli
if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']) && !empty($get'price_min']) && !empty($get'price_max'])) {
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array(h($get'price_min']), h($get'price_max']))
)
);
} else if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']) && !empty($get'price_min']) &&
empty($get'price_max'])
) {
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array(h($get'price_min']), 99999999)
)
);
}
DEVIENT (je ne sais pas ce qu'est la fonction h mais peu importe , même soyons fou on fait prixmin)
if (!empty($get'name']) && !empty($get'state_id']) && !empty($get'province_id']) && !empty($get'city_id']) && !empty($get'category_id']))) {
$prixMax = 99999999;
$prixMin = 0;
if(!empty($get'price_max'])){
$prixMax = h($get'price_max']);
}
if(!empty($get'price_min'])){
$prixMin = h($get'price_min']);
}
$a = array(
'AND' = > array(
'OR' = > array(
'Article.name LIKE' = > "%".h($get'name']).
"%",
'Article.content LIKE' = > "%".h($get'name']).
"%",
),
'User.state_id' = > h($get'state_id']),
'User.province_id' = > h($get'province_id']),
'User.city_id' = > h($get'city_id']),
'Article.category_id' = > h($get'category_id']),
'Article.price BETWEEN ? AND ?' = > array($prixMin, $prixMax)
)
);
}
Oui mais dans tes paramètres, quels sont ceux obligatoire pour la requête en base.. ceux que le client est obligé de remplir?
je sais pas, par exemple vu le morceau de requête que tu as écris, on voit que le prix est un élément de recherche optionnel pour l'utilisateur.
Obligatoire: si non rempli => pas de recherche possible
Optionnel: rempli =>prix en compte, non rempli => pas bloquant, la recherche ne comprendra pas ces précisions voilà tout.
Là, je comprend mieux, alors ils sont tous optionnel, desole j'ai ete confu xD
h() => Raccourci pour htmlspecialchars();
Merci de ton aide Antho, ta technique est plutot pas mal et prend pas beaucoup de place, je vais l'optimiser pour le rendre plus performant ;)