2017-01-14 5 views
1

Ich habe eine Produkttabelle, die zu vielen Tags und Kategorien gehört. Die Tags und Kategorien gehören auch zu vielen Produkten.CakePHP 3 gehört zu vielen Unterabfragen suchen

Ich versuche, eine Suchfunktionalität zu implementieren, die alle Produkte einschließt, bei denen die Suchparameter mit markierten Produkten, kategorisierten Produkten und dem Titel oder der Beschreibung eines Produkts übereinstimmen.

Dies ist, was ich in meinem Controller haben:

public function index() 
{ 
    $this->paginate = [ 
     'sortWhitelist' => [ 
      'Products.title', 
      'Products.msrp', 
      'Products.sale_price', 
     ], 
     'limit' => 48, 
     'order' => ['Products.title' => 'asc'] 
    ]; 
    $products = $this->Products->find(); 
    if ($search = $this->request->query('search')) { 
     $matchingCategories = $this->Products->find()->matching('Categories', function ($q) use ($search) { 
      return $q->where(['Categories.name LIKE' => "%$search%"]); 
     }); 
     $matchingTags = $this->Products->find()->matching('Tags', function ($q) use ($search) { 
      return $q->where(['Tags.name LIKE' => "%$search%"]); 
     }); 
     $products 
      ->where(['Products.title LIKE' => "%$search%"]) 
      ->orWhere(['Products.description LIKE' => "%$search%"]) 
      ->orWhere(['Products.id IN' => $matchingCategories]) 
      ->orWhere(['Products.id IN' => $matchingTags]); 
    } 

    $this->set('products', $this->paginate($products)); 
    $this->set('_serialize', ['products']); 
} 

Sie können Art sehen, was ich hier zu tun versuche, aber es funktioniert offensichtlich nicht. Ich kann jeden Teil der Gleichung funktionieren lassen, was bedeutet, dass ich entweder Produkte mit übereinstimmenden Kategorien oder Produkte mit passenden Tags oder Produkte mit Treffern in ihrem Titel oder Beschreibungen bekommen kann, aber ich kann nicht alle Produkte finden, wo die Suche passt in irgendeinem dieser Teile.

Antwort

0

Es sieht aus wie alles, was ich wählen zu tun hatte, war nur das ID-Feld in den Unterabfragen wie folgt aus:

$matchingCategories = $this->Products->find()->select(['Products.id'])->matching('Categories', function ($q) use ($search) { 
    return $q->where(['Categories.name LIKE' => "%$search%"]); 
}); 

HINWEIS: Ich bin offen für Verbesserungsvorschläge.

+1

Nun, es gibt nicht zu viele Optionen hier ... ein anderes wäre links zu 'Kategorien' und' Tags' zu kommen und die 'LIKE' Bedingungen auf' Produkte' Ebene hinzuzufügen. Kann Ihnen eine bessere Leistung geben, kann Ihnen schlechter, wie so ziemlich immer mit SQL, es "hängt". Eine etwas andere Option wäre die Verwendung von "EXISTS" anstelle von "IN". Auch hier ist die Leistung möglicherweise besser, möglicherweise sogar schlechter. – ndm

+0

@ndm Vielen Dank für den Kommentar. Ich werde damit herumspielen, um zu sehen, ob ich bessere Leistungen erzielen kann. – Battousai