Development

Documentation/fr_FR/askeet/trunk/D4 (diff)

You must first sign up to be able to contribute.

Changes between Version 7 and Version 8 of Documentation/fr_FR/askeet/trunk/D4

Show
Ignore:
Author:
forresst (IP: 82.255.75.185)
Timestamp:
03/01/08 18:58:07 (10 years ago)
Comment:

Fin de relecture (Et dans les temps :-) )

Legend:

Unmodified
Added
Removed
Modified
  • Documentation/fr_FR/askeet/trunk/D4

    v7 v8  
    196196Un fragment n'a pas d'accès natif aux objets courants. Le fragment utilise la variable `$question`, donc elle doit être définie dans l'appel de `include_partial`. L'additionnel `_` devant le nom du fichier du fragment aide à distinguer ceux des template actuels du dossier `templates/`. Si vous souhaitez en savoir plus sur les fragments, lisez le  [chapitre sur la Vue](http://www.symfony-project.com/book/1_0/07-Inside-the-View-Layer) du livre symfony. 
    197197 
    198 Modifier le modèle, part II 
    199 --------------------------- 
     198Modifier le modèle, partie II 
     199----------------------------- 
    200200 
    201201L'appel `$question->getInterests()` du nouveau fragment fait une requête à la base de données et renvoie un tableau d'objets de la classe `Interest`. C'est une requête lourde juste pour le nombre de personne intéressé, et elle pourrait surcharger la base de données. Rappelez-vous que cet appel est aussi fait dans le template `listSuccess.php`, mais cette fois en boucle, pour chaque question de la liste. Ca serait une bonne idée de l'optimiser. 
    203203Une bonne solution est d'ajouter une colonne à la table `Question` appelée `interested_users`, et de mettre à jour cette colonne chaque fois qu'un intérêt est créé pour cette question. 
    204204 
    205 >**Attention**: Nous sommes sur le point de modifier le modèle sans manière apparente de le tester, puisqu'il n'y a actuellement aucune manière d'ajouter des enregistrements `Interest` grâce à askeet. Vous ne devriez jamais modifier quelque chose sans pouvoir le tester. 
     205>**Caution**: Nous sommes sur le point de modifier le modèle sans manière apparente de le tester, puisqu'il n'y a actuellement aucune manière d'ajouter des enregistrements `Interest` grâce à askeet. Vous ne devriez jamais modifier quelque chose sans pouvoir le tester. 
    206206> 
    207207> Heureusement, nous avons une manière de tester cette modification, et vous la découvrirez plus tard dans cette partie. 
    214214    <column name="interested_users" type="integer" default="0" /> 
    215215 
    216 Ensuite reconstruisez le modle: 
     216Ensuite reconstruisez le modèle: 
    217217 
    218218    $ symfony propel-build-model 
    219219 
    220 C'est exact, nous reconstruisons déjà le modèle sans nous inquiéter des extensions de celui ci. Cest parce que l'extension de la classe User faite dans `askeet/lib/model/User.php`, hérite de la classe générée par Propel `askeet/lib/model/om/BaseUser.php`. Cest pourquoi nous devrions jamais éditer le code du répertoire `askeet/lib/model/om/`: il est remplacé  chaque fois que la commande `build-model` est appelée. Symfony aide à soulager le cycle de vie normal des changements de modèles des premières étapes de n'importe quel projet Web. 
     220C'est exact, nous reconstruisons déjà le modèle sans nous inquiéter des extensions de celui ci. C'est parce que l'extension de la classe User faite dans `askeet/lib/model/User.php`, hérite de la classe générée par Propel `askeet/lib/model/om/BaseUser.php`. C'est pourquoi nous devrions jamais éditer le code du répertoire `askeet/lib/model/om/`: il est remplacé chaque fois que la commande `build-model` est appelée. Symfony aide à soulager le cycle de vie normal des changements de modèles dans les étapes de n'importe quel projet Web. 
    221221 
    222222Vous avez besoin également de mettre à jour la base de données actuelle. Pour éviter d'écrire quelques déclarations SQL, vous pouvez reconstruire votre schéma SQL et recharger vos données de test: 
    231231> 
    232232 
    233 ### Modifier la fonction save() de l'objet Interest 
    234  
    235 La mise à jour de la valeur de ce nouveau champ doit être faite chaque fois qu'un utilisateur déclare son intérêt pour une question, i.e. que chaque fois qu'un enregistrement est ajouté dans la table `Interest`. Vous pouvez implémenter ceci avec les trigger de MySQL, mais cela serait une solution dépendant de la base de données, et nous voulons pouvoir changer de base de données facilement. 
    236 La meilleur solution est de modifier le modèle en remplaçant la fonction `save()` de la classe `Interest`. Cette fonction est appelée chaque fois qu'un objet de la classe `Interest` est créé. Donc ouvrez le fichier  `askeet/lib/model/Interest.php` et écrivez la fonction suivante:  
     233### Modifier la méthode `save()` de l'objet `Interest` 
     234 
     235La mise à jour de la valeur de ce nouveau champ doit être faite chaque fois qu'un utilisateur déclare son intérêt pour une question, par exemple à chaque fois qu'un enregistrement est ajouté dans la table `Interest`. Vous pouvez implémenter ceci avec les trigger de MySQL, mais cela serait une solution dépendant de la base de données, et nous voulons pouvoir changer de base de données facilement. 
     236 
     237La meilleur solution est de modifier le modèle en remplaçant la méthode `save()` de la classe `Interest`. Cette méthode est appelée chaque fois qu'un objet de la classe `Interest` est créé. Donc ouvrez le fichier  `askeet/lib/model/Interest.php` et écrivez la méthode suivante:  
    237238 
    238239    [php] 
    250251    } 
    251252 
    252 La nouvelle fonction `save()` renvoie la question correspondant à l'intérêt courant, et incrémente son champ `interested_users`. Puis, il fait l'habituel `save()`. Par contre`$this->save() ferait une boucle infinie, donc nous utilisons la fonction de classe `parent::save()` à la place. 
     253La nouvelle méthode `save()` renvoie la question correspondant à l'intérêt courant, et incrémente son champ `interested_users`. Puis, il fait l'habituel `save()`. Par contre`$this->save() ferait une boucle infinie, donc nous utilisons la méthode de classe `parent::save()` à la place. 
    253254 
    254255### Sécuriser la requête de mise à jour avec une transaction 
    255256 
    256 Que se passe t-il si la base de données crash entre la mise à jour de l'objet `Question` et celui de lobjet `Interest` ? Vous finiriez avec des données corrompues. C'est le même problème qui est rencontré dans une banque lors d'un transfert d'argent. Une première requête diminue le montant dun compte, et une seconde augmente un autre compte. 
     257Que se passe t-il si la base de données crash entre la mise à jour de l'objet `Question` et celui de l'objet `Interest` ? Vous finiriez avec des données corrompues. C'est le même problème qui est rencontré dans une banque lors d'un transfert d'argent. Une première requête diminue le montant d'un compte, et une seconde augmente un autre compte. 
    257258 
    258259Si  deux requêtes sont hautement dépendantes, vous devriez sécuriser leur exécution avec une **transaction**. Une transaction est une assurance que les deux requêtes réussiront, ou aucunes d'elles. Si quelque chose de mauvais arrive à l'une des requêtes de la transaction, toutes les précédentes réussies sont annulées, et la base de données retourne dans l'état avant la transaction. 
    259260 
    260 Notre fonction `save()` est une bonne opportunité pour illustrer l'implémentation des transactions dans Symfony. Remplacez le code par:  
     261Notre méthode `save()` est une bonne opportunité pour illustrer l'implémentation des transactions dans Symfony. Remplacez le code par:  
    261262 
    262263    [php] 
    287288    } 
    288289 
    289 Premièrement, la fonction ouvre une connexion directe à la base de donnes par Creole. Entre les dclarations de `->begin()` et commit()`, la transaction s'assure que tout sera fait ou rien. Si quelque chose échoue, une exception sera envoyée, et la base de données exécutera un retour à l'état précédent. 
     290Premièrement, la méthode ouvre une connexion directe à la base de données par Creole. Entre les déclarations de `->begin()` et `->commit()`, la transaction s'assure que tout sera fait ou rien. Si quelque chose échoue, une exception sera envoyée, et la base de données exécutera un retour à l'état précédent. 
    290291 
    291292### Changer le template 
    292293 
    293 Maintenant que la fonction `->getInterestedUsers()` de l'objet `Question` fonctionne correctement, il est temps de simplifier le fragment _`_interested_user.php` en remplaçant:  
     294Maintenant que la méthode `->getInterestedUsers()` de l'objet `Question` fonctionne correctement, il est temps de simplifier le fragment `_interested_user.php` en remplaçant:  
    294295 
    295296    [php] 
    301302    <?php echo $question->getInterestedUsers() ?> 
    302303 
    303 >**Note**: Grâce à notre brillante idée d'employer un fragment au lieu de laisser le code reproduit dans les template, cette modification  nécessite seulement que nous le fassions quune fois. Sinon, nous aurions du modifier les template `listSuccess.php` et `showSuccess.php` et pour des gens paresseux comme nous, cela aurait été accablant. 
    304  
    305 En termes de nombre de requêtes et temps d'exécution, cela devrait être meilleur. Vous pouvez le vérifier grâce au nombre de requêtes à la base de données indiquée dans la barre d'outils de débogage, après l'icône base de données. Notez que vous pouvez aussi récupérer des détails sur les requêtes SQL de la page courante en cliquant sur l'icône base de donnes: 
     304>**Note**: Grâce à notre brillante idée d'employer un fragment au lieu de laisser le code reproduit dans les template, cette modification  nécessite seulement que nous le fassions qu'une fois. Sinon, nous aurions du modifier les template `listSuccess.php` et `showSuccess.php` et pour des gens paresseux comme nous, cela aurait été accablant. 
     305 
     306En termes de nombre de requêtes et temps d'exécution, cela devrait être meilleur. Vous pouvez le vérifier grâce au nombre de requêtes à la base de données indiquée dans la barre d'outils de débogage, après l'icône base de données. Notez que vous pouvez aussi récupérer des détails sur les requêtes SQL de la page courante en cliquant sur l'icône base de données: 
    306307 
    307308![database queries before refactoring](/images/askeet/debug_before_day4.gif) 
    315316    $ php load_data.php 
    316317 
    317 Quand nous créons les enregistrements de la table `Interest`, l'objet `sfPropelData`utilisera la mthode save()` et devrait correctement mettre à jour les enregistrements `User` connexes. Donc c'est une bonne manière de tester les modifications du modèle, même s'il n'y a encore aucune interface CRUD établie avec l'objet `Interest`. 
     318Quand nous créons les enregistrements de la table `Interest`, l'objet `sfPropelData` utilisera la méthode `save()` et devrait correctement mettre à jour les enregistrements `User` connexes. Donc c'est une bonne manière de tester les modifications du modèle, même s'il n'y a encore aucune interface CRUD établie avec l'objet `Interest`. 
    318319 
    319320Vérifiez-le en demandant la page d'accueil et le détail de la première question: 
    328329 
    329330Ce qui a été fait pour `count($question->getInterests())` peut être aussi bien fait pour `count($answer->getRelevancys())`. La seule différence sera qu'une réponse peut avoir des votes positifs et négatifs, alors qu'une question peut seulement être notée comme intéressante. 
    330 Maintenant que vous avez compris comment modifier le modèle, nous pouvons aller plus vite. Voici les changements, juste pour rappel. Vous n'avez pas à les copier à la main pour le tutoriel de demain, si vous utilisez [l'espace de stockage SVN d'askeet] (http://svn.askeet.com/tags/release_day_4/). 
    331  
    332 * Ajoutez les colonnes suivantes à la table `answer`dans `schema.xml` 
     331Maintenant que vous avez compris comment modifier le modèle, nous pouvons aller plus vite. Voici les changements, juste pour rappel. Vous n'avez pas à les copier à la main pour le tutoriel de demain, si vous utilisez [l'espace de stockage SVN d'askeet](http://svn.askeet.com/tags/release_day_4/). 
     332 
     333* Ajoutez les colonnes suivantes à la table `answer` dans `schema.xml` 
    333334 
    334335        [xml] 
    377378        } 
    378379 
    379 * Ajoutez les deux fonctions suivantes dans la classe `Answer` du modèle: 
     380* Ajoutez les deux méthodes suivantes dans la classe `Answer` du modèle: 
    380381 
    381382        [php] 
    432433------- 
    433434 
    434 Depuis le début du tutorial, nous appelons lURL: 
     435Depuis le début du tutorial, nous appelons l'URL: 
    435436 
    436437    http://askeet/frontend_dev.php/question/show/id/XX 
    440441    http://askeet/frontend_dev.php?module=question&action=show&id=XX 
    441442 
    442 Mais avoir un systême de routage ouvre beaucoup d'autres possibilits. Nous pouvons utiliser le titre de la question comme une URL, pour pouvoir demander la même page avec: 
     443Mais avoir un systême de routage ouvre beaucoup d'autres possibilités. Nous pouvons utiliser le titre de la question comme une URL, pour pouvoir demander la même page avec: 
    443444 
    444445    http://askeet/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend 
    448449### Créons une version alternative au titre 
    449450 
    450 Premièrement, nous avons besoin d'une version convertie du titre - un titre dépouillé - pour être employée comme URL. [There's more than one way to do it](http://en.wikipedia.org/wiki/Perl), et nous allons choisir de stocker la version alternative dans une nouvelle colonne de la table `Question`. Dans le `schema.xml`, ajoutez la ligne suivante dans la table `Question`:  
     451Premièrement, nous avons besoin d'une version convertie du titre - un titre dépouillé - pour être employée comme URL. [Il y a plus d'une façon de le faire](http://en.wikipedia.org/wiki/Perl), et nous allons choisir de stocker la version alternative dans une nouvelle colonne de la table `Question`. Dans le `schema.xml`, ajoutez la ligne suivante dans la table `Question`:  
    451452 
    452453    [xml] 
    460461    $ symfony propel-build-model 
    461462    $ symfony propel-build-sql 
    462     $ mysql -u youruser -p askeet < data/sql/schema.sql 
    463  
    464 Nous allons redéfinir la fonction `setTitle()` de l'objet `Question` de sorte qu'il mette le titre dépouillé en même temps. 
     463    $ mysql -u youruser -p askeet < data/sql/lib.model.schema.sql 
     464 
     465Nous allons redéfinir la méthode `setTitle()` de l'objet `Question` de sorte qu'il mette le titre dépouillé en même temps. 
    465466 
    466467### Classe personnalisée 
    468469Avant cela, nous allons créer une classe personnalisée pour réellement transformer un titre en titre dépouillé, puisque cette fonction ne concerne pas vraiment l'objet `Question` (nous l'utiliserons probablement aussi pour l'objet `Answer`).  
    469470 
    470 Créons un nouveau fichier `myTools.class.php` dans le rpertoire`askeet/lib/`:  
     471Créons un nouveau fichier `myTools.class.php` dans le répertoire `askeet/lib/`:  
    471472 
    472473    [php] 
    510511    $ php batch/load_data.php 
    511512 
    512 Si vous voulez en savoir plus sur les classes personnalisées et l'aide personnalisé, lisez le [chapitre sur les extensions] (http://www.symfony-project.com/content/book/page/custom_helper.html) du livre Symfony. 
     513Si vous voulez en savoir plus sur les classes personnalisées et l'aide personnalisée, lisez le [chapitre sur les extensions](http://www.symfony-project.com/book/1_0/07-Inside-the-View-Layer) du livre Symfony. 
    513514 
    514515### Changer les liens de l'action `show` 
    558559    http://askeet/frontend_dev.php/question/what-shall-i-do-tonight-with-my-girlfriend 
    559560 
    560 Si vous voulez en apprendre plus à propos des dispositifs de routages, lisez le [chapitre sur la politique de routage] (http://www.symfony-project.com/content/book/page/routing.html) du livre Symfony. 
     561Si vous voulez en apprendre plus à propos des dispositifs de routages, lisez le [chapitre sur la politique de routage](http://www.symfony-project.com/book/1_0/09-Links-and-the-Routing-System) du livre Symfony. 
    561562 
    562563A demain 
    565566Aujourdhui, le site web en lui-même n'a pas beaucoup de nouvelles fonctionnalités. Cependant, nous avons vu plus de codage sur les template, vous savez comment modifier le modèle, et globalement le code a été refait dans beaucoup d'endroit. 
    566567 
    567 Cela arrive tout le temps dans la vie dun projet Symfony: le code qui peut être réutilisé est refait en fragment ou en classe personnalisée, le code qui apparait dans une action ou un template et qui appartient rellement au modèle est déplacé dans celui-ci. Même si cela sépare le code en un bon nombre de petits fichiers disséminés dans beaucoup de dossiers, la maintenance et l'évolution est plus facile. De plus, la structure de fichiers d'un projet Symfony le rend facile à localiser selon sa nature (Aide, modèle, template, action, classe personnalisée, etc.). 
     568Cela arrive tout le temps dans la vie dun projet Symfony: le code qui peut être réutilisé est refait en fragment ou en classe personnalisée, le code qui apparait dans une action ou un template et qui appartient réellement au modèle est déplacé dans celui-ci. Même si cela sépare le code en un bon nombre de petits fichiers disséminés dans beaucoup de dossiers, la maintenance et l'évolution est plus facile. De plus, la structure de fichiers d'un projet Symfony le rend facile à localiser selon sa nature (Aide, modèle, template, action, classe personnalisée, etc.). 
    568569 
    569570Le travail de refactorisation réalisé aujourdhui va accélérer le développement dans les jours à venir. 
    570571Et nous ferons périodiquement encore plus de refactorisation dans la vie de ce projet, puisque la manière dont nous développons - faire une fonctionnalité utilisable sans se préoccuper des  fonctionnalités à venir - requiert une bonne structure du code si nous ne voulons pas finir avec un désordre total. 
    571572 
    572 Qu'est-il prévu pour demain? Nous allons commencer à écrire un formulaire et voir comment récuprer ses informations. Nous allons également diviser la liste des questions de la page d'accueil en plusieurs pages. Dans le même temps, n'hésitez pas à télécharger le code d'aujourd'hui dans l'espace de stockage SVN : 
    573  (tagged release_day_4) )  :  
     573Qu'est-il prévu pour demain? Nous allons commencer à écrire un formulaire et voir comment récupérer ses informations. Nous allons également diviser la liste des questions de la page d'accueil en plusieurs pages. Dans le même temps, n'hésitez pas à télécharger le code d'aujourd'hui dans l'espace de stockage SVN (tagged release_day_4):  
    574574 
    575575    http://svn.askeet.com/tags/release_day_4/ 
    576576   
    577 et à nous envoyer vos questions en utilisant la [mailing-list askeet] (mailto:askeet-subscribe@symfony-project.com)  ou le [forum dédié] (http://www.symfony-project.com/forum/index.php/f/8/). 
     577et à nous envoyer vos questions en utilisant la [mailing-list askeet](mailto:askeet-subscribe@symfony-project.com) ou le [forum dédié](http://www.symfony-project.com/forum/index.php/f/8/). 
    578578   
    579579[1]: http://en.wikipedia.org/wiki/Agile_software_development  "Agile Software development definition at Wikipedia"