Chapitre 5: Générer le module Game (I): liste et fiche
A présent que tout est en place pour travailler à notre projet, nous allons générer un premier module: celui du jeu. Avant tout chose, établissons ce qu’un membre peut faire dans ce module:
- ajouter un jeu
- l’éditer
- voir la liste des jeux
- voir un jeu en particulier
Il ne peut donc pas supprimer un jeu, ce qui ne va pas nous empêcher de jouer un peu avec la fonction delete() avant de la retirer définitivement.
Générer le module
Utilisez la commande doctrine:generate-module –with-show –non-verbose-templates frontend game game pour la génération.
Le premier game est le nom du module, le second game est le nom du modèle. Vous êtes libre de l’appeler comme vous voulez (par exemple, dans mon premier projet test, le module s’appelait jeux).
Vous allez à l’adresse suivante: http://localhost:9093/frontend_dev.php/game pour voir votre oeuvre.
Ajout des genres et des plateformes aux jeux
Nos deux jeux existants n’ont pas de genre ni de plateforme. Cliquez donc sur l’id pour afficher leur fiche individuelle puis sur Edit.
Vous constaterez que les noms n’apparaissent pas mais bien les ids des plateformes et des genres.
Il existe donc une méthode __toString qui permet de prendre les noms de chaque élément en fonction de leur id.
Il suffit d’ajouter dans:
[lib/model/doctrine/Genre.class.php]public function __toString() { return sprintf('%s', $this->getNameGenre()); }[lib/model/doctrine/Platform.class.php]
public function __toString() { return sprintf('%s', $this->getNamePlatform()); }
A présent, nous pouvons éditer les jeux et leur attribuer des genres et des plateformes:
- CSI: aventure – PC/PS3/WII/360
- HL2E2: action, shooter – PC/MAC
Personnalisation de l’affichage de l’index et du layout
Nous allons maintenant nous atteler à personnaliser la liste et le layout du frontend. Tout d’abord, allons dans web/css pour ouvrir main.css. Vous faites ce que vous voulez à l’intérieur mais moi, je vais d’abord insérer un background en y inscrivant:
body{
background-image:url('../images/background_main.gif');
}
J’ai trouvé l’image sur GRSites.com, Pattern: Miscellaneous, nom: misc225.gif. Je l’ai placée dans web/images sous le nom de background_main.gif.
Ensuite, j’ai personnalisé les tableaux et les liens:
table {
background-color: #F8F8FF;
}
th{
background-color: #F0FFF0;
}
a{
text-decoration: none;
color: #008B8B;
}
a:hover{
text-decoration: underline;
}
a:visited{
color: #8A2BE2;
}
Maintenant, passons un peu dans apps/frontend/templates/layout.php pour ajouter un titre dans le head de votre page. Il existe plusieurs syntaxes mais étant donné que nous devons personnaliser les autres pages, nous allons mettre ici un titre générique (retirez le include_title):
<title> <?php if (!include_slot('title')): ?> Little Library Games <?php endif; ?> </title>
Ensuite, allons dans modules/game/template pour éditer la template indexSuccess.php. Nous allons retirer les colonnes suivantes: l’id et le background. Nous allons renommer également Name game en Name. Nous allons aussi mettre le lien d’affichage d’un jeu en particulier sur le nom. Ajoutons également un petit texte (avec des classes css supplémentaires) et personnalisons le h1.
Voici donc la template indexSuccess.php:
<h1>Little Library Games</h1> <span class='little'>Add your own games:</span> <table> <thead> <tr> <th>Name</th> <th>Developer</th> <th>Publisher</th> <th>Release date</th> </tr> </thead> <tbody> <?php foreach ($games as $game): ?> <tr> <td><a href="<?php echo url_for('game/show?id='.$game->getId()) ?>"><?php echo $game->getNameGame() ?></a></td> <td><?php echo $game->getDeveloper() ?></td> <td><?php echo $game->getPublisher() ?></td> <td><?php echo $game->getReleaseDate() ?></td> </tr> <?php endforeach; ?> </tbody> </table> </tbody> </table> <a href="<?php echo url_for('game/new') ?>">New</a>
Ajoutez le code qui suit dans le css:
h1{
font-family: Arial,Helvetica,sans-serif ;
color: navy;
}
.little{
letter-spacing: 3px;
word-spacing: 2px;
font-weight: bold;
font-variant: small-caps;
color: maroon;
}
Notez que l’helper url_for permet de transformer les arguments passés en paramètre en URL. Link_to est basé sur le même principe. Mais nous reviendrons sur cela plus tard.
Enfin, vous constaterez qu’un tableau contenant les jeux sont parcourus et que chaque $game est suivi d’une méthode de celui-ci. Cela permet de récupérer leurs données par colonne (getDeveloper() vous renverra le nom du développeur pour ce jeu). Un équivalent en pur php serait:
foreach ($games as $game){ echo $game['name_game']; echo $game['developer']; ........ }
actions.class.php: executeIndex()
Allons jeter un oeil dans le fichier actions.class.php (modules/game/actions). On peut y voir l’exemple d’une requête Doctrine. Il suffirait de remplacer ce code dans notre cas par:
//permet d'afficher la liste des jeux public function executeIndex(sfWebRequest $request) { $this->games = Doctrine_Core::getTable('game')->findAll(); }
Néanmoins, on peut s’amuser à essayer de faire des requêtes simples avec Doctrine, je laisse le soin à Jobeet de vous former à des requêtes plus complexes.
Par exemple, nous pouvons imaginer une fonction getAll() que nous mettrons dans lib/model/doctrine/GameTable.class.php.
GameTable est le fichier où les requêtes sur la table seront gérées. Voici donc notre code:
public static function getAll(){ $q = Doctrine_Query::create() ->select ('game.*') ->from('game'); return $q->execute(); }
Vous auriez donc dans actions.class.php:
public function executeIndex(sfWebRequest $request) { $this->games = Doctrine_Core::getTable('game')->getAll(); }
Maintenant, vos requêtes peuvent ressembler à ceci:
public static function getJeuxForGenre($id_genre){ $q = Doctrine_Query::create() ->select ('j.name_game,j.id') ->from ('game j, gamegenre k') ->where('k.genre_id ='.$id_genre) ->andWhere('j.id = k.game_id'); return $q->execute(); }
Comme vous le constatez, cela reste proche du SQL, si vous avez l’habitude de ce dernier, alors, Doctrine sera plus facile à appréhender.
A vous de voir si vous voulez la function getAll() ou celle déjà intégrée qu’est findAll().
NB: $this->games permet d’assigner à votre template une variable $games qui contiendra la liste de tous les jeux.
Personnalisation de showSuccess.php
En cliquant sur le nom du jeu, vous accédez à la fiche de ce dernier. Il est temps de personnaliser un peu celle-ci. L’ajout des informations qui manquent se fera dans la section suivante.
Nous allons ajouter un slot(‘title’) de manière à ce que ce soit le nom du jeu qui apparaisse. Nous mettrons aussi un h1 de celui-ci au centre et nous allons retirer l’id de cette liste.
Voici le code de showSuccess.php:
<?php slot('title') ?> <?php echo sprintf('%s', 'LLG: '.$game->getNameGame()) ?> <?php end_slot(); ?> <h1><?php echo $game->getNameGame()?></h1> <table> <tbody> <tr> <th>Name</th> <td><?php echo $game->getNameGame() ?></td> </tr> <tr> <th>Developer:</th> <td><?php echo $game->getDeveloper() ?></td> </tr> <tr> <th>Publisher:</th> <td><?php echo $game->getPublisher() ?></td> </tr> <tr> <th>Background:</th> <td><?php echo $game->getBackground() ?></td> </tr> <tr> <th>Release date:</th> <td><?php echo $game->getReleaseDate() ?></td> </tr> </tbody> </table> <hr /> <a href="<?php echo url_for('game/edit?id='.$game->getId())) ?>">Edit</a> <a href="<?php echo url_for('game/index')">List</a>
Ajoutez dans le css:
.milieu{
text-align: center;
}
actions.class.php: executeShow()
La fonction executeShow est aisée à comprendre:
$this->game = Doctrine_Core::getTable('game')->find(array($request->getParameter('id')));
Cette ligne vous permet de récupérer le jeu grâce à la fonction intégrée find(). Il vous suffit dès lors de récupérer le paramètre id (passé dans l’url si vous y faites attention) pour pouvoir envoyer votre demande. Si celle-ci est un échec, vous serez redirigés vers une erreur 4040:
$this->forward404Unless($this->game);
Mais constatez par vous-même, cette manière de faire ne vous renvoie ni les genres ni les plateformes. Et pourtant, il existe un moyen plus simple que de faire une nouvelle requête en combinant les conditions.
Vous comprendrez par là que j’ai essayé la second méthode avant la première (que j’ignorais).
J’avais donc ce code-là dans GenreTable:
public static function getGenresGame($id_jeu){ $q = Doctrine_Query::create() ->select('g.name_genre') ->from('genre g,gamegenre k') ->where('g.id=k.genre_id') ->andWhere('k.game_id='.$id_jeu); $names = $q->execute(); return $names; }
Mais comme je l’ai dit, il y a plus simple: ouvrez le fichier BaseGame.class.php dans lib/model/doctrine/base. Vous trouverez toutes les méthodes de l’objet Game en commentaire dont:
//@method Doctrine_Collection getGenres() Returns the current record's "Genres" collection //@method Doctrine_Collection getPlatforms() Returns the current record's "Platforms" collection
Cela veut dire que ces méthodes vont aller chercher les genres et les plateformes d’un jeu en particulier sans vous casser la tête à faire des requêtes. Donc, voici le code que nous allons mettre:
/* * Jeu en particulier */ public function executeShow(sfWebRequest $request) { //id du jeu (récupération avec getParameter() $id_jeu = $request->getParameter('id'); //récupère le jeu $this->game = Doctrine_Core::getTable('game')->find(array($id_jeu)); $this->forward404Unless($this->game); //récupère les genres et plateformes associés au jeu $this->genres = $this->game->getGenres(); //voir BaseGame.class.php dans lib/model/doctrine/base $this->platforms = $this->game->getPlatforms(); }
Donc, maintenant, vous avez trois variables assignées à votre template. Nous pouvons à présent ajouter les genres et les plateformes dans showSuccess.php.
Modification de showSuccess.php: genres et plateformes
Il suffit simplement de faire un foreach dans votre tableau, après la date de sortie:
<tr> <th>Genre</th> <td><?php foreach ($genres as $genre){ echo $genre.'<br />';} ?></td> </tr> <tr> <th>Platforms:</th> <td><?php foreach ($platforms as $platform){ echo $platform.'<br />';} ?></td> </tr>
En savoir plus:
Doctrine
_toString dans Symfony
_toString en PHP