formation cakephp 1.3.8 - exercices
TRANSCRIPT
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 1/13
Tutoriel CakePHP
Créez rapidement vos applications avec CakePHP
Auteur Date de dernière version Numéro de version
Christian Buffin 18/04/11 1.2
Formation CakePHP 1.3.8 Page 1 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 2/13
Révisions
SQL1.Trouver tous les posts qui sont visibles
SELECT * FROM posts WHERE visible = true;
2.Trouver tous les posts qui sont visibles et trier le jeu de résultats par date de création en ordredescendant.
SELECT * FROM posts WHERE visible = true ORDER BY created DESC;
3.Ajouter l'utilisateur lié au jeu de résultats.
SELECT * FROM posts INNER JOIN users ON ( posts.user_id = users.id ) WHEREposts.visible = true ORDER BY posts.created DESC;
4.a. PostgreSQL - Trouver l'id et le title de 2 posts, aliaser le nom de la table (par Post) et préfixerle nom de chaque colonne par Post__
SELECT "Post"."id" AS "Post__id", "Post"."title" AS "Post__title"FROM "posts" AS "Post"
LEFT JOIN "users" AS "User" ON ("Post"."user_id" = "User"."id")LIMIT 2
4.b. MySQL - Trouver l'id et le title de 2 posts
SELECT posts.id, posts.titleFROM posts
LEFT JOIN users ON (posts.user_id = users.id)LIMIT 2
Programmation orientée objet1. Créez une classe Animal qui possède un attribut publique nom (dont la valeur par défaut est« Animal ») et une méthode publique manger qui affiche « <nom> mange ».
class Animal{
public $nom = 'Animal';
public function manger() {echo "{$this->nom} mange";
}
Formation CakePHP 1.3.8 Page 2 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 3/13
}
2. Créez une classe Chien qui hérite de la classe Animal et qui surcharge l'attribut name en luidonnant la valeur par défaut « Médor ».
class Chien extends Animal{
public $nom = 'Médor';}
3. Complétez la classe précédente en surchargeant la méthode manger pour qu'elle affiche cequ'affiche la classe Animal, plus une ligne qui affiche « <nom> est un bon chien ».
class Chien extends Animal{
public $nom = 'Médor';
public function manger() {parent::manger();echo "{$this->nom} est un bon chien";
}}
4. Modifiez la classe précédente pour ne pas afficher le résultat de la méthode manger de laclasse Animal. À la place, affichez « <nom> est un bon chien qui mange ».
class Chien extends Animal{public $nom = 'Médor';
public function manger() {echo "{$this->nom} est un bon chien qui mange";
}}
Formation CakePHP 1.3.8 Page 3 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 4/13
Code généré par la console
Localisation
Créez et remplissez le fichier de traduction en français pour le code généré par la console(seulement pour la partie posts/edit.ctp). Testez dans votre navigateur.
# app/locale/fre/LC_MESSAGES/default.po
msgid "Invalid post"msgstr "Billet invalide"
msgid "The post has been saved"msgstr "Impossible d'enregistrer le billet"
msgid "The post could not be saved. Please, try again."
msgstr "Impossible d'enregistrer le billet. Veuillez réessayer"
ParamètresEssayez de déboguer les paramètres qui sont passés au contrôleur dans les méthodes index,view et edit du contrôleur PostsController.
debug( $this->params['pass'] ); // Paramètres GET, façon CakePHP
debug( $this->data ); // Paramètres POST, commenter le redirect pour lesvoir.
debug( $this->params['named'] ); // Paramètres nommés
Pages d'erreurModifiez le code de la méthode view de la classe PostsController pour envoyer une page404 lorsque l'enregistrement n'est pas trouvé.
function view($id = null) {$post = $this->Post->read(null, $id);if( empty( $post ) ) {
$this->cakeError( 'error404' );}$this->set('post', $post);
Formation CakePHP 1.3.8 Page 4 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 5/13
}
Add / edit
Regroupez les méthodes add et edit de PostsController ainsi que les vues associées, afin depasser par la méthode _add_edit.
PostsController
function add() {$args = func_get_args();call_user_func_array( array( $this, '_add_edit' ), $args );
}
function edit() {$args = func_get_args();call_user_func_array( array( $this, '_add_edit' ), $args );
}
function _add_edit( $id = null ) {if( $this->action == 'edit' ) {
$post = $this->Post->read( null, $id );if( empty( $post ) ) {$this->cakeError( 'error404' );}
}
if (!empty($this->data)) {
$this->Post->create();if ($this->Post->save($this->data)) {$this->Session->setFlash(__('The Post has been saved',
true));$this->redirect(array('action' => 'index'));
} else {$this->Session->setFlash(__('The Post could not be saved.
Please, try again.', true));}
}
if( $this>action == 'edit' && empty( $this->data ) ) {$this->data = $post;
}
$this->render( null, null, '_add_edit' );}
_add_edit.ctp
<div class="posts form"><?php echo $this->Form->create('Post');?>
<fieldset><legend><?php
Formation CakePHP 1.3.8 Page 5 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 6/13
if( $this->action == 'add' ) {__('Add Post');
}else {__('Edit Post');
}
?></legend><?php
if( $this->action == 'edit' ) {echo $this->Form->input('id');
}echo $this->Form->input('title');echo $this->Form->input('user_id');echo $this->Form->input('visible');echo $this->Form->input('introduction');echo $this->Form->input('content');echo $this->Form->input('Tag');
?></fieldset>
<?php echo $this->Form->end(__('Submit', true));?></div><div class="actions">
<h3><?php __('Actions'); ?></h3><ul>
<?php if( $this->action == 'edit' ):?><li><?php echo $this->Html->link(__('Delete', true),
array('action' => 'delete', $this->Form->value('Post.id')), null,sprintf(__('Are you sure you want to delete # %s?', true), $this->Form->value('Post.id'))); ?></li>
<?php endif;?><li><?php echo $this->Html->link(__('List Posts', true),
array('action' => 'index'));?></li></ul>
</div>
Formation CakePHP 1.3.8 Page 6 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 7/13
ModèleDans le modèle Post, arrangez-vous pour que l'on puisse supprimer un billet même si son id estclé étrangère pour d'autres modèles.
public $hasMany = array('Comment' => array(
'dependent' => true)
);
Dans le contrôleur Posts, méthode view, déboguez le nombre d'utilisateurs dont l'id est strictementsupérieur à 2.
$count = $this->Post->User->find( 'count', array( 'conditions' =>array( 'User.id >' => 2 ) ) );
debug( $count );
Formation CakePHP 1.3.8 Page 7 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 8/13
Vue1. Dans la vue index liée au contrôleur Posts, changez le colonne user_id en User.username. Aubesoin, modifiez la récursivité dans la méthode du contrôleur. Vérifiez que l'on puisse bien trier letableau de résultats par nom d'utilisateur.
views/posts/index.ctp
<th><?php echo $paginator->sort('title');?></th><th><?php echo $paginator->sort('User.username');?></th><th><?php echo $paginator->sort('introduction');?></th>…
<?php echo $post['Post']['title']; ?></td><td>
<?php echo $post['User']['username']; ?></td>
<td><?php echo $post['Post']['introduction']; ?>
controllers/posts_controller.php
function index() {$this->Post->recursive = 0;$this->set('posts', $this->paginate());
}
2. Recopiez le layout par défaut se trouvant dans cake/libs/views/layout/default.ctp dansapp/views/layouts/default.ctp. Ajoutez des liens (en utilisant la méthode link du helper Html) versles pages d'index de tous vos contrôleurs.
<div id="menu"><?php echo $this->Html->link( 'Billets', array( 'controller' =>
'posts', 'action' => 'index' ) ); ?><?php echo $this->Html->link( 'Utilisateurs', array( 'controller' =>
'users' ) ); ?>// ...
</div>
3. Modifiez la méthode _add_edit du contrôleur Posts, la vue associée et le modèle associé pourobtenir une liste déroulante des utilisateurs pour le champ Post.user_id. Vous utiliserez la méthodefind( 'list' ).
controllers/posts_controller.php
// ...$listUsers = $this->Post->User->find( 'list' );$this->set( 'listUsers', $listUsers );
$this->render( null, null, '_add_edit' );
Formation CakePHP 1.3.8 Page 8 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 9/13
}
models/user.php
<?phpclass User extends AppModel {
var $name = 'User';var $displayField = 'username';// ...
views/posts/_add_edit.ctp
echo $this->Form->input( 'user_id', array( 'options' => $listUsers ) );
Remarque: on n'est pas obligés de de spécifier les options à utiliser pour le champ user_id,puisqu'on a utilisé la variable $users (et que notre champ s'appelle user_id) … magie deCakePHP. Je vous conseille donc d'être explicites pour éviter de mauvaises surprises. Néanmoins,voici le code permettant d'utiliser la magie de CakePHP.
controllers/posts_controller.php
// ...$users = $this->Post->User->find( 'list' );$this->set( 'users', $users );
$this->render( null, null, '_add_edit' );}
views/posts/_add_edit.ctp
echo $this->Form->input( 'user_id' );
L'explication de cette magie est que l'on a bien respecté les conventions CakePHP, et que l'on anommé le champ user_id (nom de la table au singulier, underscore id) puisque ce champcorrespond à une clé étrangère.
4. Modifiez le code précédent pour obtenir par défaut une entrée vide dans la liste déroulante.Aidez-vous du CookBook en regardant l'aide pour la méthode input du FormHelper.
echo $this->Form->input( 'user_id', array( 'empty' => true ) );
5. Modifiez la méthode _add_edit du contrôleur Posts et la vue associée pour obtenir des cases àcocher des divers tags que l'on peut associer au billet. Vérifiez que l'enregistrement s'effectuecorrectement.
controllers/posts_controller.php
Formation CakePHP 1.3.8 Page 9 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 10/13
// ...$this->set( 'tags', $this->Post->Tag->find( 'list' ) );
$this->render( null, null, '_add_edit' );}
views/posts/_add_edit.ctp
echo $this->Form->input( 'Tag', array( 'multiple' => 'checkbox' ) );
5. Dans l'index des billets, ajoutez une colonne contenant la liste des tags, utilisez la classe Set.N'oubliez pas d'augmenter la récursivité.
controllers/posts_controller.php
$this->Post->recursive = 1;$this->set('posts', $this->paginate());
views/posts/index.ctp
<td><?php echo $post['Post']['visible']; ?> </td><td><?php echo implode( ', ', Set::extract( $post, '/Tag/name' ) ); ?> </td><td><?php echo $post['Post']['introduction']; ?> </td>
6. Dans la vue de la méthode view du contrôleur Posts, présentez les données comme pour unvrai blog (Titre, auteur / date de création, tags, introduction, contenu, commentaires). Préoccupez-vous uniquement du HTML (pas du CSS). Utilisez les fonctions PHP strftime et strtotime pourobtenir la date dans la langue définie par setlocale. Inspirez-vous d'un billet du sitehttp://www.zeldman.com/
views/posts/view.ctp
<div class="posts view"><h1><?php echo $post['Post']['title'];?></h1><p>Crée par <?php echo $post['User']['username'];?> le <?php echo
strftime( '%A %e %B %Y à %H:%M', strtotime( $post['Post']['created'] ) );?
>.</p><?php
$tags = Set::combine( $post, 'Tag.{n}.id', 'Tag.{n}.name' );if( empty( $tags ) ) {
echo $this->Html->tag( 'p', 'Non catégorisé' );}else {
$liens = array();foreach( $tags as $id => $name ) {
$liens[] = $this->Html->link( $name,array( 'controller' => 'tags', 'action' => 'view', $id ) );
}echo $this->Html->tag( 'p', 'Catégorisé dans: '.implode( ',
Formation CakePHP 1.3.8 Page 10 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 11/13
', $liens ) );}
?><div class="introduction">
<?php echo $post['Post']['introduction'];?></div>
<div class="content"><?php echo $post['Post']['content'];?>
</div>
<div class="comments"><h2>Commentaires</h2>
<?phpif( empty( $post['Comment'] ) ) {
echo $this->Html->tag( 'p', 'Aucun commentaire' );}else {
foreach( $post['Comment'] as $comment ) {$tmp = '';
$tmp .= $this->Html->tag( 'h3', $comment['name'] );$tmp .= $this->Html->tag( 'p', strftime( 'Crée le %A
%e %B %Y à %H:%M', strtotime( $comment['created'] ) ) );$tmp .= $this->Html->tag( 'div',
$comment['content'] );echo $this->Html->tag( 'div', $tmp, array( 'class' =>
'comment' ) );}
}?></div>
</div>
7. Faites un formulaire de recherche pour la méthode index du contrôleur Posts. Vous afficherez 4champs dans le formulaire: Post.visible , Post.user_id, Post.title et Post.created. Construisez votremoteur champ par champ ( d'abord Post.visible, puis Post.visible et Post.user_id, etc... ). Utilisez(du moins à terme) la méthode postConditions de la classe Controller.
models/post.php
class Post extends AppModel {public $name = 'Post';public $order = array( 'Post.id ASC' );
// ...}
Formation CakePHP 1.3.8 Page 11 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 12/13
views/posts/index.ctp (à rajouter avant le tableau de résultats)
<?php/*
Il faut préciser que l'on retourne bien sur la méthode index ducontrôleur Posts.
Par défaut, CakePHP renverra vers la méthode add du contrôleurcourant.
*/echo $this->Form->create( null, array( 'url' => array( 'controller' =>
'posts', 'action' => 'index' ) ) );
echo $this->Form->input( 'Post.user_id', array( 'empty' => true ) );echo $this->Form->input( 'Post.title' );/*
Le champ created est de type timestamp/datetime, on va le forcerà être de type date,
avec un format francophone et une année maximale correspondant àl'année en cours
*/echo $this->Form->input( 'Post.created', array( 'type' => 'date',
'dateFormat' => 'DMY', 'empty' => true, 'maxYear' => date( 'Y' ) ) );echo $this->Form->input( 'Post.visible' );
echo $this->Form->end( __( 'Search', true ) );?>
controllers/posts_controller.php
public function index() {
$conditions = array();$data = $this->data;
if( !empty( $this->data ) ) {// Nettoyage des champs videsforeach( array( 'Post.user_id', 'Post.title' ) as $path ) {
$value = Set::classicExtract( $data, $path );if( empty( $value ) ) {
$data = Set::remove( $data, $path );}
}
// Variable temporaire pour stocker la date de création$created = $data['Post']['created'];$data = Set::remove( $data, 'Post.created' );
// Transformation en conditions$conditions = $this->postConditions( $data, array( 'Post.title'
=> 'LIKE' ) );
// Ajout éventuel du critère sur la date de création (pour letype timestamp/datetime de la BDD)
if( !empty( $created['day'] ) && !empty( $created['month'] ) && !empty( $created['year'] ) ) {
$createdStart = "{$created['year']}-{$created['month']}-
{$created['day']}";
Formation CakePHP 1.3.8 Page 12 / 13
5/11/2018 Formation CakePHP 1.3.8 - Exercices - slidepdf.com
http://slidepdf.com/reader/full/formation-cakephp-138-exercices 13/13
$createdStop = date( 'Y-m-d', strtotime( $createdStart ) + (24 * 60 * 60 ) );
$conditions[] = "Post.created BETWEEN '{$createdStart}' AND'{$createdStop}'";
}}
$this->Post->recursive = 0;$this->set( 'posts', $this->paginate( null, $conditions ) );$this->set( 'users', $this->Post->User->find( 'list' ) );
}
controllers/posts_controller.php (méthode alternative)
public function index() {$conditions = array();$data = $this->data;
if( !empty( $this->data ) ) {// Variable temporaire pour stocker la date de création$created = $data['Post']['created'];$data = Set::remove( $data, 'Post.created' );
// Transformation en conditions$conditions = $this->postConditions(
$data,array(
'Post.title' => 'LIKE','Post.user_id' => 'LIKE'
)
);
// Ajout éventuel du critère sur la date de création (pour letype timestamp/datetime de la BDD)
if( !empty( $created['day'] ) && !empty( $created['month'] ) && !empty( $created['year'] ) ) {
$createdStart = "{$created['year']}-{$created['month']}-{$created['day']}";
$createdStop = date( 'Y-m-d', strtotime( $createdStart ) + (24 * 60 * 60 ) );
$conditions[] = "Post.created BETWEEN '{$createdStart}' AND'{$createdStop}'";
}}
$this->Post->recursive = 0;$this->set( 'posts', $this->paginate( null, $conditions ) );$this->set( 'users', $this->Post->User->find( 'list' ) );
}
Formation CakePHP 1.3.8 Page 13 / 13