Précédent   Forum des professionnels en informatique > PHP > Bibliothèques et frameworks > Templates > Smarty
Smarty Forum d'entraide sur le moteur de templates Smarty. Avant de poster -> FAQ Smarty et Cours Smarty
Partagez cette discussion sur d'autres réseaux sociaux : Viadeo Twitter Google Facebook Digg Delicious MySpace Yahoo
Réponse Proposer ce sujet en actualité
 
Outils de la discussion
Publicité
'
Vieux 01/02/2011, 17h27   #1
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Par défaut Arborescence MVC + Smarty

Bonjour,

j'aimerais avoir votre avis concernant l'arborescence de mon projet. Ce projet doit suivre un pattern MVC, utiliser Smarty pour les templates ainsi qu'être multilingues avec gettext.

Citation:
+/
../models/
............/module1.m.php
............/module2.m.php
../controllers/
................./module1.c.php
................./module2.c.php
../tpls/
........./templates/
......................./module1/*.tpl
......................./module2/*.tpl
........./templates_c/
........./cache/
../locale/
.........../fr_FR/
..................../LC_MESSAGES/
.........../en_EN/
..................../LC_MESSAGES/
../include/
............/js
............/jquery
............/css
............/images
../smarty/
............/internals
............/plugins
../index.php

index.php est mon front controller, il se chargera de répartir les requêtes sur les controllers concernés. Puis affiche le template qui se trouve dans tpls/templates/moduleX/*.tpl

Cela paraît-il cohérent?
Merci d'avance
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 18h18   #2
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Hello,

Il est généralement d'usage de séparer la partie applicative de la partie publique de façon à pouvoir protéger les répertoires sensibles à a donner plus de cohérence à notre arborescence.

Personnellement, j'utilise une arbo proche de celle du Zend Framework:
Citation:
/application/
+ config/
+ + application.ini
+ + bootstrap.php
+ controllers/
+ models/
+ view/
+ + helpers/
/libraries/
+ unelib/
+ uneautrelib/
/public/
+ scripts/
+ images/
+ templates/
+ styles/
+ index.php
.htaccess
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/02/2011, 19h46   #3
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
ok je suis d'accord mais quelle différence tu fais entre tes views de ton dossier /application/ et les templates dans ton /public/ ?

et ton bootstrap.php te sert à quoi? car mon "bootstrap" c'est l'index.php.
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 03/02/2011, 12h57   #4
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Bonjour,

Je me pose une autre question concernant les contrôleurs. Comment structurez vous vos contrôleurs? est-ce un immense switch case? ou utilisez vous une autre structure?

merci d'avance
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 12h35   #5
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Hello

Désolé de pas être venu plus tôt, je suis pas mal pris en ce moment.

Dans le MVC, il est primordial de bien comprendre le rôle du routeur: c'est lui qui en fonction de la demande du client va appeller le(s) bon(s) controlleur(s). Cela se fait généralement au moyen de routes prédéfinies, regarde du coté de CakePHP, il fait ça très bien tu peux t'en inspirer.

Un contrôleur caractérise une route, une section si tu préfères, et ses méthodes caractérisent des actions. Par exemple, pour poster un commentaire sur un article, on pourra avoir: monsite.com/article/xxxx/post (forme réécrite de
monsite.com/index.php?rt=article&act=post&id_article=xxx).
Coté PHP tu aura un contrôleur "ArticleController" qui porte une méthode de classe "post".
Généralement, on affecte une action par défaut à tous nos contrôlleurs, le moyen le plus simple d'avoir une structure commune est de passer par une classe abstraite "BaseController":
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
 
abstract class BaseController {
 
  protected static $_request;
  protected static $_response;
 
  abstract public static function index (); // action par défaut
 
  final public static function setRequest (Request &$request) {
    static::$_request = $request;
  }
 
  final public static function setResponse (Response &$response) {
    static::$_response = $response;
  }
}
 
class ArticleController extends BaseController {
 
  public static function index () {
 
    $list_articles = Articles::list(0,10);
    return compact('list_articles');
 
  }
 
   public static function post () {
 
    if (static::$_request->email, static::$_request->comment) {
       $result = Article::create(static::$_request->email, static::$_request->comment);
    else $result=  false;
 
 
     return compact('result');
   }
}
Le routeur va alors récupérer le retour du contrôleur qu'il à appellé et va passer tout ça à la vue pour l'affichage.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 15h28   #6
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
D'accord je vois, ma vision du contrôleur est différente de celle que tu as donné. J'ai déjà utilisé le framework symfony donc je comprends très bien le système de route. Tu as un contrôleur par classe toi.

Moi ma vision (beaucoup plus simpliste) était plus du genre, un contrôleur pour un module du style :
Code php :
1
2
3
4
5
6
7
8
9
 
$action = secure($_GET['act']);
switch($action){
case "post" : 
   traitement...
break;
default : 
    traitement ..
}

et mon "routeur", soit index.php. Il vérifie que le module demandé existe bien, puis charge le contrôleur correspondant. Et c'est dans les contrôleur que je vais vérifier l'intégrité des données avant d'utiliser les méthodes de mes modèles.

car avec ta méthode, je ne vois pas où tu testes l'intégrité de tes données?

dans tous les cas mon but n'est pas de réécrire un framework complet mais juste de bien séparer les M-V-C
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 04/02/2011, 16h33   #7
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Citation:
Tu as un contrôleur par classe toi
Nah, j'ai une classe par contrôlleur. Mais je peux utiliser plusieurs routes pour le même controller.

Et je teste toujour l'intégrité de mes données dans le contrôleur, où d'autre pourrait-on faire ça de toute manière ? Pour ça, le routeur va gentiment passer les objets Request et Response au contrôleur pour qu'il fasse son taff

J'ai pas réécrit un framework en faisant ça, j'ai besoin de 6 classes de base:
- Router
- BaseController
- Request
- Response
- ViewManager
- Model
On peut pas vraiment dire que c'est bien compliqué

J'ai déjà fait un MVC en procédural, ça marche y'a pas de souci mais tu peines à exprimer les délégations entre contrôleurs: exemple, un contrôleur A reçoit des paramètres que seul un contrôleur B sait traiter (multi insertion en BDD par exemple), comment tu fais avec ton switch ?
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 09h51   #8
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Bonjour,

désolé du temps de réponse, j'étais pas mal occupé sur d'autres projets.

J'ai vraiment du mal à saisir le traitement d'une requête avec ton système.

Par exemple si j'ai une requête de ce genre : monsite.com/article/1111/show pour afficher l'article 1111

Tu reçois donc sur index.php ta requête :
- tu commences par faire une instance de ta classe Router avec l'url en paramètre qui va créer un objet Request et un objet Response (j'ai pas encore tout à fait saisi leurs buts?)
- tu fais une instance de ton ArticleController qui hérite de BaseController (toujours à partir de ton objet Router? avec en paramètre l'objet Request et Response?) , tu exécutes la méthode du controller : ici show(id)
- tu instancies les models nécessaires au traitement et tu exécutes les méthodes pour récupérer/supprimer/mettre à jour les données
- et ton ViewManager? j'imagine qu'il va inclure le bon template en générant avant les variables?


désolé, si c'est faux, mais j'ai toujours été habitué à utiliser du procédural du coup ça me pertube un peu car j'ai du mal à voir où se trouve les différents niveaux de traitement.

Merci de m'aider.

Cordialement.
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 12h07   #9
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Citation:
tu commences par faire une instance de ta classe Router
Inutile d'instancier le routeur, on gagne un facteur 4x de performance en utilisant des méthodes de classes (statiques).

Citation:
créer un objet Request et un objet Response (j'ai pas encore tout à fait saisi leurs buts?)
L'objet Request contiends toutes les informations utiles en provenance du client: les paramètres $_REQUEST pour commencer, les langues que son navigateur accepte, les header que son navigateur accepte etc.
L'objet Response contiens tout ce que les contrôleurs pourront fournir comme information complémentaire mais qu'il ne peuvent pas - du fait de leur signature - renvoyer par 'return' comme par exemple le header à renvoyer (tu peux très bien avoir pour un même contrôleur une méthode getMessage qui renvoie un tableau du message à insérer dans une vue HTML ou une VUE json - tu peux faire différencier les deux cas par un paramètre 'response-type=json' par exemple).

Citation:
tu fais une instance de ton ArticleController qui hérite de BaseController
Là encore, pas besoin d'instance, les methodes statiques conviennent très bien.
Dans le contrôleur tu appelle ta logique métier/modèle et tu renvoie les variables qui vont bien dans un tableau (compact aide bien pour ça).

Donc une fois que le contrôleur à fini son job, il renvoie à au router (puisque c'est lui qui l'a appelé) une série de variables dans un tableau.

Citation:
et ton ViewManager? j'imagine qu'il va inclure le bon template en générant avant les variables?
Une fois que le routeur à reçu du controlleur les variables qui vont bien et que le contrôlleur à mis à jour l'objet 'response' si besoin, le routeur appelle le ViewManager en lui passant tout ça et c'est inZePocket.

Je te fais voir un exemple de la méthode 'load' de mon routeur (celle chargée de lancer le(s) controlleur(s)), ça te donnera des idées:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
 
public static function load ($controller, $action = null) {
        if (empty($action)) $action = "index";
        try {
            call_user_func_array(array($controller, '_init'), array(&self::$_request, &self::$_response));
            self::$_response->addVars(call_user_func(array($controller, $action)));
        }
        catch (BadMethodCallException $e) {
            return self::run("error", "http404");
        }
        catch (Exception $e) {
            return self::run("error", "http500");
        }
 
        $view_path = dirname(__DIR__) . "/application/view/" . lcfirst(str_replace('Controller', '', $controller)) . '/' .
                     $action . '.' . self::$_response->getType() . '.php';
 
        if (file_exists($view_path)) {
            try {
                ViewManager::setHeader(self::$_response->getType());
                ViewManager::addVars(self::$_response->getVars());
                ViewManager::load($view_path);
            }
            catch (Exception $e) {
                header("HTTP/1.0 500 Internal Server Error", true);
                die($e->getMessage());
            }
        }
    }
Il est important que tout ce petit monde (Router, Contrôleur, ViewManager) partagent bien la même instance de Request et de Response, c'est vrai qu'on aurait pu faire en sorte que les contrôleurs appellent Response::addVars() mais c'est plus pratique comme ça (et rien ne l'empêche par ailleur).

Note également, qu'il est tout à fait possible qu'un contrôleur appelle à son tour un autre contrôleur (principe de chain of action). Dans ce cas, il est vital d'avoir bien les mêmes objets de partout pour faire remonter l'information.
Avant je me servais d'un objet 'Registry' qui encapsulait les deux aspects 'Request' et 'Response' mais vu qu'ils caractérient deux entités différentes, il vaut mieux les séparer pour une raison évidente de responsabilité entre les classes impliquées.

Un jeu d'enfant donc.
Note que je ne suis pas particulièrement fier de l'usage de call_user_func_array mais c'est pour garder la compatibilité ascendante avec PHP5.1

Je tiens à préciser que dans mon cas, 'Router' caractérise un genre de Front Contrôleur. Tu trouvera sur Google de la doc sur le 'design pattern router' en Java, c'est tout à fait adaptable à PHP.
L'idée c'est d'avoir un composant capable de comprendre et d'interpréter les routes de ton application. Par exemple monsite.com/articles/news/23-09-2010
peut être vu comme l'appel du contrôleur 'ArticlesControlleurs' et de sa méthode 'news' avec le paramètre de date '23-09-2010'. Au niveau d'Apache, je fais transformer cette url en index.php?rt=articles&act=news&date=23-09-2010 et le routeur se charge de trouver le bon couple contrôleur action soit dans sa hashmap des routes connues soit en tentant de trouver de lui même le bon contrôleur.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 10
Vieux 09/02/2011, 12h22   #10
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Une remarque, j'ai volontairement choisi de ne pas utiliser SMARTY car PHP est déjà un moteur de template - c'est pour ça que Rasmus l'a créé au départ, je trouve inutile de mettre du templating par dessus du templating...

J'utilise ce moteur de template et crois moi, c'est surpuissant
Code :
1
2
3
4
5
6
 
<table id="<?=$un_id?>">
<?php foreach ($mes_vars as $key => $value): ?>
<tr><td><?=$key?></td><td><?=$value?></td></tr>
<?php endforeach; ?>
</table>
Note que Zend Framework et Lithium managent leurs vues comme ça par défaut.

Et fais attention avec Gettext, je ne sais pas si tu connais cette techno mais d'une elle est relativement complexe à mettre en place et de deux tous les hébergeurs ne la propose pas nécéssairement.
Perso j'utilise un moteur linguistique fait maison avec des fichiers ini, c'est diaboliquement simple et efficace:
Code :
1
2
3
 
// coté ini on a today = "today is %s"
<p><?=i18n('today', date())?></p>
On peut difficilement faire plus simple.

Mais c'est toi qui voit en fonction de tes besoins ce que tu veux faire. Mais je trouve que pour des projets modestes (site internet classique de petite taille) c'est pas la peine de s'armer d'un bazooka pour tuer un mouche.
Pour des projets plus important, oui, c'est avantageux le couple Smarty/Gettext, voire l'utilisation d'un bon gros framework.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 14h56   #11
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Déjà merci beaucoup de prendre le temps de m'aider, ta réponse était très claire et super précise.

Si j'ai bien compris,

dans index.php :
- tu découpes ta requête et tu mets tout ça avec $_REQUEST dans un objet Request.
- tu initialises ton router avec l'objet Request et l'objet Response
- tu appelles la méthode load avec le couple (controller,action)

dans ton router :
- la méthode load initialise le controller avec les objets Request et Response
- elle appelle ensuite la méthode qui correspond à l'action à exécuter
- génère et charge la vue grâce aux informations de Response

dans ton controller :
- une méthode par action, tu appelles les méthodes des classes Model, mais ici tu les instancies bien tes classes non? par exemple, si tu veux modifier un article, tu appelles une méthode load(id) qui retourne un objet et apres tu fais $this->edit() ou alors tu fais directement ::edit(id) ?

Pour ce qui est de gettext et de smarty, c'est des contraintes, non négociable. Je trouve aussi que l'utilisation de gettext est discutable mais pas le choix.

si tu peux juste confirmer/corriger ce que je viens d'écrire, je te remercie en tout cas pour le temps qe tu as pris pour m'aider.
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 15h37   #12
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Citation:
dans index.php :
- tu découpes ta requête et tu mets tout ça avec $_REQUEST dans un objet Request.
- tu initialises ton router avec l'objet Request et l'objet Response
- tu appelles la méthode load avec le couple (controller,action)
Pas exactement, le découpage d'une requête réécrite de la forme "monsite.com/articles/new/2011-02-09" se fait avec de l'URL rewriting - au niveau de ton .htaccess si modrewrite.c est actif sur ton serveur apache (disponible chez la quasi-totalité des hébergeurs). Une règle pour cette requête pourrait être:
Code :
1
2
 
RewriteRule ^([^/]*)/([^/]*)/([^/]*)$ index.php?rt=$1&$act=$2&date=$3 [QSA,L]
ça, c'est à toi de voir comment tu vas formater tes URL, il y a un article intéressant par là: http://www.webrankinfo.com/dossiers/...-url-rewriting

Ensuite, sache que c'est traditionnellement le rôle du routeur d'instancier les objets Request et Response. Mais cependant ce n'est pas faux de le faire faire à index.php et ensuite de les passer au Routeur qui les passera à son tour aux contrôleurs etc.

Par exemple voici mon index.php:
Code :
1
2
3
4
5
 
<?php
require_once dirname(dirname(__DIR__)) . "/application/config/bootstrap.php";
 
Router::run();
simple non ? Le bootstrap est là pour toutes les opérations de configuration.

Et j'appelle non pas la méthode 'load' du routeur mais la méthode 'run' qui tente de trouver une route et si elle y arrive, appelle à son tour 'load'.

Citation:
dans ton router :
- la méthode load initialise le controller avec les objets Request et Response
- elle appelle ensuite la méthode qui correspond à l'action à exécuter
- génère et charge la vue grâce aux informations de Response
Tout à fait.

Citation:
dans ton controller :
- une méthode par action, tu appelles les méthodes des classes Model, mais ici tu les instancies bien tes classes non? par exemple, si tu veux modifier un article, tu appelles une méthode load(id) qui retourne un objet et apres tu fais $this->edit() ou alors tu fais directement ::edit(id) ?
Oui bien sûr. Les contrôleurs ne portent pas d'information de classe (car on à en réalité jamais besoin de deux contrôleur identiques) ils sont donc intégralement statiques. En revanche rien ne les empêche d'instancier des objets modèles ou d'appeller des métiers.
Un exemple de contrôleur pourrait être:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
<?php
class MyController extends BaseController {
 
    public static function article () {
         if ($request->id_article) {
             // trouver l'article correspondant en se servant de la classe Article
             $article = Article::find($request->id_article);
         }
         return compact('article');
    }
}
Et ensuite la vue pourrait faire:
Code :
1
2
3
 
<h2><?=$article->title?></h2>
<p><?=$article->body?></p>
Tout simplement.

Note: j'ai créé mon routeur de façon à ce qu'il utilise le couple de paramètres rt / act pour identifier le controleur à utiliser (la route - rt) et l'action à effectuer (act). Ensuite, j'utilise la route pour déterminer quelle vue afficher et l'action pour déterminer quelle template prendre.
Exemple:
monsite/articles/news/2011-02-09
> devient monsite/index.php?rt=articles&act=news&date=2011-02-09
> le router cherche ArticlesController (ucfirst($rt) . 'Controller')
> puis effectue ArticlesController::news
> puis cherche une vue /application/views/articles/news.html.php
> charge les variables et fait l'include de cette vue
> affiche

De cette façon, presque tout est automatisé, pour ajouter une nouvelle page / feature au site, on ajoute juste un contrôleur et une vue qui va avec.
Remarque, si dans le contrôleur on définit le header de sortie à json par exemple, ViewManager se charge (grace au paramètre qui va bien dans Response) d'envoyer le bon header et de charger news.json.php au lieu de news.html.php.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 16h02   #13
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
oui oui j'ai déjà utilisé plusieurs fois l'url rewriting. J'avais pensé plutôt récupérer les paramètres comme $_GET['controller'] par exemple et faire un attribut dans mon objet Request. Mais c'est vrai que si notre objet Request contient déjà $_REQUEST donc $_GET on peut récupérer les variables controller/action/etc via $_REQUEST.

Citation:
la méthode 'run' qui tente de trouver une route et si elle y arrive, appelle à son tour 'load'.
je vois pas de quoi tu as besoin de plus? vu que dans ta requête tu as le controler et l'action, pourquoi ne pas lancer load(controller,action) de suite?
même si tu as plusieurs routes, ça se répercute juste au niveau du htaccess non?
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 09/02/2011, 17h00   #14
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Citation:
Citation:
la méthode 'run' qui tente de trouver une route et si elle y arrive, appelle à son tour 'load'.
je vois pas de quoi tu as besoin de plus? vu que dans ta requête tu as le controler et l'action, pourquoi ne pas lancer load(controller,action) de suite?
même si tu as plusieurs routes, ça se répercute juste au niveau du htaccess non?
Tout simplement parce que les paramètres en provenance de l'URL ne sont par nature par sûrs. Un utilisateur peut très bien rentrer une route inexistante, il faut pouvoir le rerouter sur une erreur 404. De plus, cette façon de faire permet de créer des routes prédéfinies qui évitent au routeur de 'chercher' le bon contrôleur et au passage de créer des alias de routes (multilinguisme) et des routes par défaut indépendamment du htaccess.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 09h00   #15
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Bonjour,

J'ai commencé à dev mon appli en utilisant ce qu'on a dit au dessus, cependant j'ai un soucis pour afficher mes résultats.

Enfin, je m'explique :

Par exemple, mon action qui liste tous les utilisateurs :
Code :
1
2
 
parent::$_response->addVar('users', Utilisateur::loadAll(parent::$_pdo));
ma méthode loadAll() me retourne un tableau d'objet Utilisateur.

jusque là, tout va bien.

mais après c'est pour l'afficher mes objets dans smarty, étant donné que mes attributs de ma classe sont en privés, il veut pas les afficher (normal).

Comment vous faites de votre côté lorsque vous récupérez un ou plusieurs objets et que vous devez les afficher?

Ma deuxième question, où gérez vous les droits pour accéder à une action? j'ai trois profils utilisateur dans mon appli, pour l'instant j'ai fait une méthode :
Code :
1
2
 
Utilisateur::isAllowed(parent::$_pdo,PROFIL_MIN,APPLICATION_PATH . 'utilisateur/connexion') ;
ça me permet de checker si l'utilisateur a les droits minimum. Cependant je suis obligé de le faire dans chaque action, avez vous une meilleure solution?

merci d'avance pour votre aide,
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 10h34   #16
Membre à l'essai
 
Inscription : juin 2009
Messages : 50
Détails du profil
Informations forums :
Inscription : juin 2009
Messages : 50
Points : 21
Points : 21
Rebonjour,

j'ai une autre petite question qui me trotine dans la tête. Pour faire des notices (je pense à faire comme sur symfony) pour afficher un retour à l'utilisateur.

Comment faire pour garder une notice même après un header('Location :') ? c'est possible sans le faire passer en get dans l'url?

merci merci
icl1c est déconnecté   Envoyer un message privé Réponse avec citation 00
Vieux 01/03/2011, 12h38   #17
Modérateur
 
Avatar de Benjamin Delespierre
 
Benjamin Delespierre
Développeur Web
Inscription : février 2010
Messages : 2 984
Détails du profil
Informations personnelles :
Nom : Benjamin Delespierre
Âge : 24
Localisation : France

Informations professionnelles :
Activité : Développeur Web
Secteur : High Tech - Opérateur de télécommunications

Informations forums :
Inscription : février 2010
Messages : 2 984
Points : 5 015
Points : 5 015
Hello

Citation:
mais après c'est pour l'afficher mes objets dans smarty, étant donné que mes attributs de ma classe sont en privés, il veut pas les afficher (normal).
Soit tu mets ces attributs en public (si tu es sûr de ce que tu fais, je te le déconseille car ce sont des données de BDD, on ne doit pas les accéder directement). Soit tu définis la méthode __get dans ton objet modèle afin de pouvoir faire $obj->mon_attr_private.

Citation:
Comment vous faites de votre côté lorsque vous récupérez un ou plusieurs objets et que vous devez les afficher?
Personnellement je mets les objets dans une collection traversable (un Iterator) et fais un foreach dessus tout simplement.

Citation:
Ma deuxième question, où gérez vous les droits pour accéder à une action? j'ai trois profils utilisateur dans mon appli, pour l'instant j'ai fait une méthode :
Une solution élégante consisterait à définir dans tes contrôleurs une méthode statique 'grant' capable de déterminer si un utilisateur peut effectuer une action. Ensuite il faut que le routeur accède à cette information.

Exemple:
Code :
1
2
3
4
5
6
7
8
9
10
11
12
 
abstract class BaseController {
 
  // identique au base controller donné précédement
 
  public static function grant ($action) {
     if (isset($_SESSION['user'])) {
        return $_SESSION['user']->isAdmin(); // méthode de la classe User par exemple
     }
     return false;
  }
}
Les classes filles de BaseControlleur pour surcharger cette méthode pour définir leur propre politique.

Dans ton routeur:
Code :
1
2
3
4
5
6
7
 
public static function load ($route, $action) {
  if (!$route::grant($action))
    router::run('error', 'http503'); // rerouter sur 'forbidden'
 
  // la suite de router::load
}
Où $route est le nom du controlleur à invoquer et $action la méthode à appeller.

Citation:
j'ai une autre petite question qui me trotine dans la tête. Pour faire des notices (je pense à faire comme sur symfony) pour afficher un retour à l'utilisateur.
Que sont les notices dans Symphony ? Si ce sont des messages à afficher le mieux est encore de se servir du pattern Observer.
Dans Observer, un Objet écoute les évènements (on l'appelle un observateur) et lorsqu'il reçoit quelque chose, le dispatch sur les objets qui lui sont attachés (on les appelles des sujets).
Un article qui explique ça: http://julien-pauli.developpez.com/t.../observer-spl/

Dans ton cas, des notices ou warnings pourront être levées n'importe où dans ton application mais il faut que ça arrive au vues. Le Listener va t'aider dans ce sens ou tu vas appeler l'Observateur en lui passant le message, il va ensuite le relancer sur le gestionnaire de vues qui lui à été précédemment attaché - et par exemple un fichier de log ou une trace d'action en BDD.
Le view manager va quand à lui conserver dans un attribut statique la liste des notices / warning et va les passer aux vues pour affichage.

Je vois venir d'ici la question "alors pourquoi ne pas faire appeler directement ViewManager::addNotice($message) par exemple ?" Tout simplement parce que je préfère que les classes des couches métier et modèle ne parlent pas directement au gestionnaire de vues car ils travaillent sur une autre couche que lui. C'est un problème d'architecture: on ne veut pas de couplage entre les différentes couches de note application.

Citation:
Comment faire pour garder une notice même après un header('Location :') ? c'est possible sans le faire passer en get dans l'url?
Tu les fais transiter sur la session, je ne vois pas vraiment d'autre moyen.
Tu peux également te servir des iterateurs pour gérer une pile de messages notice et warning (au niveau du gestionnaire de vues) de telle sorte que les messages sont consommés à l'affichage (on les dépile quand on y accède). Et tu gardes cette pile sur la session.
__________________
A la recherche d'un framework MVC facile a prendre en main ? Essayez Axiom
Nouveau: la référence d'Axiom est disponible sur GitHub (je la peaufine en ce moment même).

Un problème correctement identifié est à moitié résolu, évitez de poster l'intégralité de votre code avec pour seule explication "ça ne marche pas...".
Pour identifier correctement vos problèmes PHP, utilisez la gestion des erreurs et xdebug.

Les boutons et existent, servez-vous en
Benjamin Delespierre est déconnecté   Envoyer un message privé Réponse avec citation 00
Réponse Proposer ce sujet en actualité Cette discussion est résolue.
Outils de la discussion



Fuseau horaire GMT +2. Il est actuellement 07h16.


 
 
 
 
Partenaires

Hébergement Web