CakePHP : recherche globale
Pour les besoins de son portail il est fort utile d'avoir des fonctionnalités transversales à tout le portail.
C'est le cas de la fonction de recherche, qui peut aller à la pêche aux actualités/articles/billets/bogues etc...
La solution serait d'avoir une grosse fonction php qui parcourt toutes les tables,
mais cela n'est bien évidement pas satisfaisant, car inmaintenable, pas portable, trop lourd...
Donc l'idée va consister à créer une fonction de recherche par plugin (un plugin "cakephp" est une "partie" de l'application globale).
Puis lorsque le visiteur saisira une phrase sur le moteur de recherche, nous déclencherons la fonction de recherche de chaque plugin.
Comment procéder ?
Chaque plugin possède son propre répertoire, exemple
- app/plugins/news
- app/plugins/articles
- app/plugins/blog
dans chacun d'eux nous créons un script _prepend.php contenant ceci :
pour le plugins news :
<?php
$this->addBehavior('publicSearchHTML', array('newsBehavior','searchNews'));
class newsBehavior
{
public function searchNews()
{
#appel de son modèle
App::import('Model','news.News');
$news = & new News();
$rs = $news->getNews();
/*
* Ici le code sur l'iteration sur le recordset pour afficher le resultat
* en invoquant le Helper HtmlHelper() pour le rendu bien sûr.
*/
}
?>
on comprend ici qu'il faut donc etre muni d'une fonction getNews() dans le model news.
Mais, pour le moment le _prepend.php est "inerte", par inerte j'entends, qu'il n'est pas utilisable en l'etat.
Effectivement, il manque une classe pour exploiter nos "comportements" (les classes xxxBehavior)
Voici donc le Helper (oui car il s'agit d'afficher des données, donc un helper;) qui gère tout cela :
(extrait issue de PunCake)
<?php
class PcbehaviorHelper extends Helper {
public $puncake_behaviors = array();
public function beforeRender() {
/*
*
* ici le code permettant de parcourir le répertoire plugins
*
*/
$this->path = dirname(__FILE__) . '/../../plugins/';
foreach ($this->path as $root)
{
if (!is_dir($root) || !is_readable($root))
continue;
if (substr($root,-1) != '/')
$root .= '/';
if (($d = @dir($root)) === false)
continue;
while (($entry = $d->read()) !== false)
{
$full_entry = $root.'/'.$entry;
if ($entry != '.' && $entry != '..' && is_dir($full_entry)
&& file_exists($full_entry.'/_prepend.php')
)
{
require $full_entry.'/_prepend.php';
}
}
$d->close();
}
}
/*
* la fonction d'ajout du behavior
* au tableau des behaviors (utilisé par chaque _prepend.php)
*/
public function addBehavior($behavior,$func)
{
if (is_callable($func)) {
$this->puncake_behaviors[$behavior][] = $func;
}
}
/*
* Fonction de rappel de la classe et fonction à éxécuter
*/
public function callBehavior($behavior)
{
if (!empty($this->puncake_behaviors[$behavior]))
{
$args = func_get_args();
array_shift($args);
$res = '';
foreach ($this->puncake_behaviors[$behavior] as $f) {
$res .= call_user_func_array($f,$args);
}
return $res;
}
}
}
?>
Ceci fait, dans la vue de son choix, un simple appel $pcbehavior->callBehavior('publicSearchHTML');
déclenchera l'appel de la méthode searchNews de tous les plugins disposant d'un fichier _prepend.php .
Voilà !
Ce Helper s'applique donc quelque soit le behavior qu'on veut coder.
Par exemple, qd je me connecte sur mon portail, je veux etre avertis si j'ai des news/articles à modérer, des billets reçus etc.. etc..
Tout ceci ce gère de la même maniere que ci dessus.
1) ajout d'une fonction newToValidate de plus à ma class newsBehavior
2) ajout du behavior à la pile via $this->addBehavior('toValidate',array('newsBehavior','newsToValidate'))
3) appel du behavior dans la vue de mon choix par un $pcbehavior->callBehavior('toValidate');
Happy Cooking !


Derniers commentaires