Consultez la FAQ sur le ZF avant de poster une question
Vous n'êtes pas identifié.
Bonjour à tous,
Je souhaiterais avoir le titre de la page dans l'url de celle-ci. Ex:
http://monsite.com/news/view/full/title … news/id/12
Ceci dans un but de référencement.
Je rajoute actuellement le titre de la news dans l'url de cette façon.
<a href="<?php echo $this->baseUrl.$this->baseUrlExt; ?>/news/view/full/title/<?php echo $this->escape($news->news_title); ?>/id/<?php echo $this->escape($news->news_id); ?>"><?php echo $this->escape($news->news_title);?> </a></td>
Cependant, les espaces et caractère spéciaux sont remplacer par des %XXX.
Connaissez vous un moyen de faire cela plus proprement en remplaçant les espaces par des "-", en enlevant les accents etc ?
Merci d'avance pour votre aide.
Hors ligne
et bien jette un oeil ici .. je pense que c'est simple
http://fr3.php.net/str_replace
Hors ligne
Donc le mieux serait que je fasse une fonction en utisant str_replace pour tous les caractères que je souhaite enlever?
Hors ligne
J'ai bricolé ça la semaine dernière, avec les infos glanées ici et sur php.net pour faire une url "propre", générée à partir des titres d'articles.
La fonction makeLink est inutile pour toi, moi elle me permet juste de retourner une url du type : ID-titre.html
Mais tu peux regarder la suite.
C'est bricolé et adapté, les noms de fonctions genre "utf2ascii" ne sont peut-être plus très parlants, mais la fonction marche parfaitement pour moi, je n'ai pas rencontré le moindre soucis.
<?php class Fonctions { public function makeLink($id,$titre) { $cleanName = Fonctions::urlize($titre); return $id . '-' . $cleanName . '.html'; } public static function urlize($url) { $search = array('/[^a-z0-9]/', '/--+/', '/^-+/', '/-+$/' ); $replace = array( '-', '-', '', ''); return preg_replace($search, $replace, Fonctions::utf2ascii($url)); } public static function utf2ascii($string) { $string = str_replace("â","a", $string); $string = str_replace("à","a", $string); $string = str_replace("ä","a", $string); $string = str_replace("è","e", $string); $string = str_replace("é","e", $string); $string = str_replace("ë","e", $string); $string = str_replace("ê","e", $string); $string = str_replace("î","i", $string); $string = str_replace("ï","i", $string); $string = str_replace("ö","o", $string); $string = str_replace("ô","o", $string); $string = str_replace("û","u", $string); $string = str_replace("ü","u", $string); $string = str_replace("ù","u", $string); $string = str_replace("Â","a", $string); $string = str_replace("À","a", $string); $string = str_replace("Ä","a", $string); $string = str_replace("È","e", $string); $string = str_replace("É","e", $string); $string = str_replace("Ë","e", $string); $string = str_replace("Ê","e", $string); $string = str_replace("Î","i", $string); $string = str_replace("Ï","i", $string); $string = str_replace("Ö","o", $string); $string = str_replace("Ô","o", $string); $string = str_replace("Û","u", $string); $string = str_replace("Ü","u", $string); $string = str_replace("Ù","u", $string); $iso88591 = "\\xE0\\xE1\\xE2\\xE3\\xE4\\xE5\\xE6\\xE7"; $iso88591 .= "\\xE8\\xE9\\xEA\\xEB\\xEC\\xED\\xEE\\xEF"; $iso88591 .= "\\xF0\\xF1\\xF2\\xF3\\xF4\\xF5\\xF6\\xF7"; $iso88591 .= "\\xF8\\xF9\\xFA\\xFB\\xFC\\xFD\\xFE\\xFF"; $ascii = "aaaaaaaceeeeiiiidnooooooouuuuxyy"; return mb_strtolower(utf8_decode($string), 'ISO-8859-1'); } }
Hors ligne
C'est pas le rôle de Zend_Filter?
Pourquoi ne pas le dériver plutôt que de créer des classes "indépendantes"?
Hors ligne
Nikkau a écrit:
C'est pas le rôle de Zend_Filter?
Pourquoi ne pas le dériver plutôt que de créer des classes "indépendantes"?
D'accord avec Nikkau, je derive la class Zend_Filter_Interface comme ceci :
<?php require_once 'Zend/Filter/Interface.php'; class filters_tmstptodateFilter implements Zend_Filter_Interface{ var $string; public function filter($tab){ $this->string = date('d/m/Y h:m:s',$tab[0]); return($this->string); } }
Ensuite dans ton controleur tu passes ton filter à ta vue (dans la function init() par exemple) :
$this->filter_time_stamp = new Zend_Filter(); $this->filter_time_stamp->addFilter(new filters_tmstptodateFilter()); $this->view->filter = $this->filter; $this->view->filter_time_stamp = $this->filter_time_stamp;
Ca permet ensuite dans ta vue d'appeler ton filter comme ca :
<?php echo $this->escape($this->filter_time_stamp->filter(array($invite->$key)));?>
enfin voila il faut adapter a ton besoin
Bon courage
Hors ligne
Je pense que la solution est un mix des deux. Le but c'est de faire une classe dérivée de la class Zend_Filter_Interface avec un traitement de la chaîne de caractère comme le fait la classe de neojick.
Je vais donc me pencher là dessus.
Hors ligne
Pour comparer voici un exemple en production par Neil Garb qui a créé son blog avec zf :
Les tags, les titres sont des jolies urls :
http://codecaine.co.za/posts/whitelist- … -framework
On peut télécharger le source depuis son svn :
http://codecaine.co.za/svn/
mais ca se passe chez lui dans lib/App/Controller/Router.php
Dernière modification par fte (19-06-2008 09:29:48)
Hors ligne
Je reviens un peu sur le sujet.
Vu que je dois passer mon filtre à ma vue et que la meilleure solution pour l'avoir dans tous les controllers de mon module c'est de le faire directement dans le init.
Je ne m'y connait pas en helper et en plugin mais ne faut-il pas utiliser l'un des deux pour avoir ce filtre dans toute mon application?
Et dans le principe, ce n'est pas au controller de gérer la modification des variables et juste à la vue d'afficher le lien?
Dans ce cas, là ou je faisais un
$this->view->news = $news->fetchAll();
, comment je fait pour passer un filtre sur un champ particulier ou mieux comment rajouter un champ au tableau avec dedans le titre des news passé dans le filtre.
Au départ j'aurai donc un tableau (fetchall) avec les champs 'id', 'titre', 'contenu' et au final j'aurai les champs 'id', 'titre', 'urltitre', 'contenu'.
Je ne sais pas si c'est possible mais ça serait tout de même fort pratique...
Dernière modification par slaughter (25-06-2008 01:42:12)
Hors ligne
Petit Up ...
Hors ligne
slaughter a écrit:
Je reviens un peu sur le sujet.
Vu que je dois passer mon filtre à ma vue et que la meilleure solution pour l'avoir dans tous les controllers de mon module c'est de le faire directement dans le init.
Je ne m'y connait pas en helper et en plugin mais ne faut-il pas utiliser l'un des deux pour avoir ce filtre dans toute mon application?
Et dans le principe, ce n'est pas au controller de gérer la modification des variables et juste à la vue d'afficher le lien?
Dans ce cas, là ou je faisais unCode:
$this->view->news = $news->fetchAll();, comment je fait pour passer un filtre sur un champ particulier ou mieux comment rajouter un champ au tableau avec dedans le titre des news passé dans le filtre.
Dans le principe, à moins que je ne dise une bétise, tu devrais faire ton $news->fetchAll() au niveau du model... enfin perso c'est ce que j'essaye de faire au max... mais bon je sais pas trop
Maintenant tu peux peut etre essayer un truc du genre dans le controller ou tu déclares les filters :
$news = $news->fetchAll(); $news->ton_champ = $this->filter_time_stamp($news->ton_champ); $this->view->news=$news;
Dernière modification par thomasb (26-06-2008 09:49:59)
Hors ligne
Si je ne me trompe pas, fetchAll() renvoie un Rowset qui se présente donc sous la forme de conteneur d'objet. On peut parcourir ce conteneur avec un foreach (grâce à l'implémentation de l'interface Iteror).
Le seul moyen que j'ai trouvé pour appliqué un filtre à tout les données d'un champ (news_title dans mon cas) c'est de faire ainsi :
//filtre $filter_url = new Zend_Filter(); $filter_url->addFilter(new Mylib_Filter_Urltitle()); $bd0x_News = new bd0x_News(); $news = $bd0x_News->fetchAll(); foreach ($news as $row) { $row->news_title = $filter_url->filter($row->news_title); } $this->view->news = $news;
Au final je récupère bien mes titre de news avec la modification du titre. La chose qu'il me reste à savoir faire c'est de ne pas modifier le champ "news_title" mais d'en créer un nouveau "news_title_url".
De cette façon, dans ma vue je peux parcourir mes enregistrement, afficher la liste des news avec un lien qui contient le titre de la news passé dans le filtre.
Dans ma vue:
<?php foreach($this->news as $news) : ?> <a href="<?php echo $this->baseUrl; ?>/news/view/full/id/<?php echo $this->$news->news_id; ?>/title/<?php echo $this->$news->news_title_url; ?>"><?php echo $this->escape($news->news_title);?> </a> <?php endforeach; ?>
J'ai donc essayé de faire ainsi :
foreach ($news as $row) { $row->news_title_url = $filter_url->filter($row->news_title); }
mais j'ai le message suivant :
"Fatal error: Uncaught exception 'Zend_Db_Table_Row_Exception' with message 'Specified column "news_title_url" is not in the row"
Je ne vois donc pas comment faire....
Hors ligne
Pourquoi ne fait tu pas un view_helper.
Tu ne modifie le titre que pour l'url donc que pour la vue, tu n'as aucune raison que le traitement se fasse avant la vue.
Pour moi, ca n'a pas non plus de raison d'etre un filter.
Hors ligne
Comment se créer exactement un view_helper ? je vois comment utiliser les view_helper existant de la lib ZEND mais pas des perso (ex : Mylib_View_Helper_HelperName ).
Avez vous des infos là dessus?
Hors ligne
De mon coté, j'utilise le routeur, car c'est sa responsabilité de faire ça.
Par exemple :
[routes]
auteurs.type = "Zend_Controller_Router_Route_Regex"
auteurs.route = "auteurs/edit\-(\d+)\-(.+)"
auteurs.defaults.controller = auteurs
auteurs.defaults.action = edit
auteurs.map.1 = id
auteurs.reverse = "auteurs/edit-%d-%s"
Pour éditer les auteurs, le view helper url me mappe donc ca avec le routeur, et me sort des urls du style site/app/auteurs/edit-4-Pauli-Julien
Hors ligne
J'ai du mal à voir l'ensemble du code nécessaire à la création de route "propre". A part le Zend Manual, y a-t-il quelques tutos qui pourrais expliquer cela.
Pour l'instant, j'avais faire ne sorte d'avoir une route générique site\module\controller\action\parametres--- dans le but de ne pas avoir à rajouter des routes pour chaques controller ou module que je rajoute à mon application.
Je ne sais d'ailleurs pas quelle maintenance est nécessaire au fur et à mesure de l'évolution de l'application.
Tout cela reste assez abstrait pour moi et je ne serais pas contre quelques informations...
PS : En tout cas, je vous remercie déjà pour ce post et cette reflexion.
Hors ligne
Si je reprends l'exemple de codecaine, voici comment il définit ses route
<?php class App_Controller_Router extends Zend_Controller_Router_Rewrite { function __construct () { parent::__construct(); // index $this->addRoute( 'home', new Zend_Controller_Router_Route( '', array( 'controller' => 'posts', 'action' => 'index' ) ) ); // about $this->addRoute( 'about', new Zend_Controller_Router_Route( 'about', array( 'controller' => 'index', 'action' => 'about' ) ) ); // spam $this->addRoute( 'spam', new Zend_Controller_Router_Route( 'spam', array( 'controller' => 'index', 'action' => 'spam' ) ) ); // sitemap $this->addRoute( 'sitemap', new Zend_Controller_Router_Route( 'sitemap.xml', array( 'controller' => 'index', 'action' => 'sitemap' ) ) ); // post > archive $this->addRoute( 'post_archive_year', new Zend_Controller_Router_Route( 'posts/:year/:month', array( 'controller' => 'posts', 'action' => 'archive' ), array( 'year' => '\d{4,4}', 'month' => '[01][0-9]' ) ) ); // post > view $this->addRoute( 'post', new Zend_Controller_Router_Route( 'posts/:label', array( 'controller' => 'posts', 'action' => 'view' ) ) ); // post > comment $this->addRoute( 'post_comment', new Zend_Controller_Router_Route( 'posts/:label/comment', array( 'controller' => 'posts', 'action' => 'comment' ) ) ); // rss $this->addRoute( 'rss', new Zend_Controller_Router_Route( 'rss', array( 'controller' => 'posts', 'action' => 'rss' ) ) ); // post > rss $this->addRoute( 'post_rss', new Zend_Controller_Router_Route( 'posts/:label/rss', array( 'controller' => 'posts', 'action' => 'commentrss' ) ) ); // tag > view $this->addRoute( 'tag', new Zend_Controller_Router_Route( 'tags/:label', array( 'controller' => 'tags', 'action' => 'view' ) ) ); } }
N'est-ce pas compliqué à maintenir ?
Hors ligne
Oui, l'alternative c'est d'avoir ces définitions dans un fichier de configuration ini ou xml :
bootstrap (html/index.php)
....... $controller = Zend_Controller_Front::getInstance (); ....... /** * Router pour les chemins */ $router = new Zend_Controller_Router_Rewrite(); $router->addConfig( new Zend_Config_Ini('../application/default/config/routes.ini', 'routes') ); $controller->setRouter($router);
et dans routes.ini la section [routes] de Julien.
Hors ligne
Donc il faut bien rentrer toutes les routes possibles à la main dans le fichier de configuration ?
Il n'y a pas moyen d'avoir un type de route par défaut genre /:language/:module/:controller/:action/ et tous les paramètres et de rajouter des spécification pour certain controller pour avoir des dates par exemple /jj/mm/aaaa/.
Autre question. Je n'arrive pas à comprendre comment marche la translation des titres qui passent de "bonjour à tous" à "bonjour-a-tous".
Avez vous de la doc en plus de celle du ZF ?
Hors ligne
Je sais pas si ça a déjà été posté (bis repetita placent) :
http://fashion.hosmoz.net/post/2006/10/ … end_Config
http://www.spotsec.com/blogs/archive/20 … framework/
Le mieux c'est de faire des petits essais ici, sans regexp puis avec.
Dernière modification par fte (30-06-2008 11:52:13)
Hors ligne
Je viens de mettre ça en place sur mon site et la solution de julien est super simple et marche nickel!
Hors ligne
sebondus, peux tu donner une liste à peu près exhaustive de ce que tu as mis en place.
Perso, voici ce que j'ai.
index.php (boostrap)
$router = new Zend_Controller_Router_Rewrite(); $router->addConfig(new Zend_Config_Ini('./../config/routes.ini', 'routes'), 'routes'); $controller = Zend_Controller_Front::getInstance(); $controller->setRouter($router);
routes.ini
[routes] routes.news.type = "Zend_Controller_Router_Route" routes.news.route = "/:language/:sport/:module/:controller/:action/*" routes.news.defaults.language = "fr" routes.news.defaults.sport = "sport1" routes.news.defaults.module = "news" routes.news.defaults.controller = "view" routes.news.defaults.action = "list"
Je peux donc accèder à ma page avec l'adresse suivante : http://monsite/fr/sport1/news/view/full pour avoir ma news. Je voudrais juste maintenant avoir le nom de la news dans l'url et c'est maintenant que je bloque.
Que dois-je rajouter dans ma config et comment faire les liens vers ces news ?
Dernière modification par slaughter (12-07-2008 00:41:33)
Hors ligne
Après de nombreux tests, voilà ce que j'arrive maintenant à faire :
routes.ini
[routes] routes.compat.route = ":language/:sport/:module/:controller/:action/*" routes.news.route = ":language/:sport/:module/:controller/:action/*" routes.news.type = "Zend_Controller_Router_Route_Regex" routes.news.route = "fr/sport1/news/view/full\-(\d+)\-(.+).html" routes.news.defaults.module = "news" routes.news.defaults.controller = "view" routes.news.defaults.action = "full" routes.news.map.1 = "id" routes.news.map.2 = "titre" routes.news.reverse = "fr/sport1/news/view/full-%d-%s.html"
Je peux maintenant accéder à la page d'affichage de la news en tapant http://monsite/fr/sport1/news/view/full-1-montitre.html
Mais comme vous le voyez dans le fichier de config, je suis obligé de mettre en dure dans la règle les valeurs des variables :language et :sport.
Comment s'en passer ?
Dernière question : pour le dernier paramètre (reverse), a quoi correspond les lettres d et s de %d et %s ? Je sais bien que cela désigne les variables d'id et de titre dans mon cas mais pourquoi "d" et "s" ?
Dernière modification par slaughter (12-07-2008 01:20:06)
Hors ligne