Blog ENI : Toute la veille numérique !
🐠 -25€ dès 75€ 
+ 7 jours d'accès à la Bibliothèque Numérique ENI. Cliquez ici
Accès illimité 24h/24 à tous nos livres & vidéos ! 
Découvrez la Bibliothèque Numérique ENI. Cliquez ici
  1. Livres et vidéos
  2. PHP et MySQL
  3. Corrigé 4
Extrait - PHP et MySQL Entraînez-vous à développer une application collaborative
Extraits du livre
PHP et MySQL Entraînez-vous à développer une application collaborative Revenir à la page d'achat du livre

Corrigé 4

Prérequis

1.

a., c. et d.

La réponse b est la seule fausse. Il n’existe pas de type stamp, mais timestamp est un type existant. Les autres propositions sont correctes, à savoir time, year et datetime.

2.

c.

La réponse c est correcte, c’est la fonction str_to_date() qui réalise la conversion.

3.

a.

La première proposition est la bonne pour décoder le texte indiqué dans l’énoncé. La documentation de MySQL décrit tous les formateurs acceptés par cette fonction.

4.

b.

C’est date_format qui traduit une date en texte à l’aide d’une chaîne de format.

5.

c.

Seule la réponse c donne le bon résultat, elle est d’ailleurs la seule requête syntaxiquement valide.

6.

a., c. et f.

Les réponses a, c et f sont correctes. Elles reçoivent un paramètre timestamp dont la valeur par défaut est time(). Les autres propositions n’appartiennent pas à PHP.

7.

b., c. et d.

Les réponses b, c et d sont correctes. La réponse a réalise l’opération inverse : formater en texte une date.

8.

b.

La réponse b est la bonne. En MySQL les paramètres sont transmis à la procédure stockée en respectant l’ordre de définition mais sans être nommés.

Corrigé 4.1 Initialisation de la base de données

 Il existe plusieurs moyens pour exécuter le script SQL : passer par la commande Importer, copier-coller le code SQL dans la console SQL, ou encore faire un glisser-déposer dans cette fenêtre.

images/C04TP01.png

Le champ tstamp représente la date et l’heure auxquelles l’invitation a été émise. Le champ uid est un identifiant unique du rendez-vous, il a une utilité lorsqu’un message SMTP portant l’invitation est transmis et de ce fait il identifie l’événement de façon globale.

 Cette fonction SQL génère un nouvel identifiant unique :

images/C04TP02.png

 Dans la requête INSERT, il n’est pas nécessaire de donner une valeur à ID_EVENEMENT qui est auto-calculée. Par ailleurs, la fonction uuid() fournit un identifiant unique :

INSERT INTO `evenement`  
(`id_evenement`,  
`evenement_tstamp`,  
`evenement_dtstart`,  
`evenement_dtend`,  
`evenement_uid`,  
`evenement_subject`,  
`evenement_description`,  
`evenement_location`,  
`evenement_id_utilisateur`)  
VALUES  
( 
    NULL,  
     '2019-08-21', 
    '2019-10-14 10:00', 
    '2019-10-14 11:00',  
    uuid(),  
    'Meeting', 
 ...

Corrigé 4.2 Le DAO et la couche de service pour l’agenda

 Les entités reprennent l’ensemble des colonnes portées par les tables :

/* 
 * evenemententity.php 
 */ 
 
class EvenementEntity { 
   public $id_evenement; 
   public $evenement_tstamp; 
   public $evenement_dtstart; 
   public $evenement_dtend; 
   public $evenement_uid; 
   public $evenement_subject; 
   public $evenement_description; 
   public $evenement_location; 
   public $id_utilisateur; 
} 
/* 
 * participantentity.php 
 */ 
 
class ParticipantEntity { 
   public $id_evenement; 
   public $id_utilisateur; 
} 

 Le DAO est sur le même modèle que les autres :

/* 
 * evenementdao.php 
 */ 
 
class EvenementDAO { 
   private $db_connection; 
 
   public function __construct() { 
       $this->db_connection = get_default_connection(); 
   } 
} 

 Voici les deux premières méthodes, plutôt courtes :

public function evenement_set_participant($id_evenement,array $pe) 
{ 
   $cx = mysqli_connect($this->db_connection["cx_server"], 
       $this->db_connection["cx_login"], 
       $this->db_connection["cx_pwd"], 
       $this->db_connection["cx_dbname"]); 
    
    
   $query = "delete from participant where id_evenement=$id_evenement"; 
   mysqli_query($cx, $query); 
 
   foreach($pe as $p) { 
       $query = "call sp_evenement_set_participant($id_evenement,
$p->id_utilisateur)"; 
       mysqli_query($cx, $query); 
   } 
       mysqli_close($cx); 
} 
 
public function evenement_get_participant($id_evenement) 
{ 
   $cx = mysqli_connect($this->db_connection["cx_server"], 
       $this->db_connection["cx_login"], ...

Corrigé 4.3 Saisie et modification d’un rendez-vous

 Voici le point de départ de ce module, le contrôleur agendaController et l’action index(). L’authentification des utilisateurs est exigée à l’aide de l’annotation @Autorisation.

/** 
 * @Autorisation(access_control_mode=Autorisation::DENY_ANONYMOUS) 
 */ 
class agendaController extends BaseController 
{ 
 
   public function index($model) 
   { 
       return $this->View($model,"index"); 
   } 
} 

L’URL du bouton d’action est fournie par la méthode action_link :

<?php html::action_link('agenda', 'agenda', 'agendaadd', 
'Nouveau rendez-vous')?> 

 Commençons par un peu de mise en place. Le formulaire comporte des zones de listes dont les valeurs sont fournies à travers un view model :

/* 
 * agendaviewmodel 
 */ 
require_once 'models/evenemententity.php'; 
require_once 'models/participantentity.php'; 
 
class agendaviewmodel { 
   /** 
    *  
    * @var EvenementEntity 
    */ 
   public $evenement; 
 
   /** 
    *  
    * @var array ParticipantEntity 
    */ 
   public $participants_items; 
 
   /** 
    *  
    * @var string 
    */ 
   public $participants_selected; 
 
   public function __construct() { 
       $this->evenement = new EvenementEntity(); 
       $this->participants_items = array(); 
   } 
} 

Le contrôleur est chargé de remplir le view model à l’aide des composants de service. Tout en parcourant la liste des utilisateurs, il recherche l’utilisateur courant et positionne en conséquence la propriété $id_utilisateur :

/** 
 * @Autorisation(access_control_mode=Autorisation::DENY_ANONYMOUS) 
 */ 
class agendaController extends BaseController 
{ 
 
   public function index($model) ...

Corrigé 4.4 Création d’un composant de sélection de date

 La classe viewComp est abstraite, car la méthode renderBody() n’est pas implémentée. Eclipse indique une erreur jusqu’à ce que le code de la méthode soit défini dans la classe datePicker.

/* 
* datecontrol.php 
*/ 
require_once '../comfpl/views/viewComp.php'; 
 
class datePicker extends viewComp 
{ 
   public $width; 
 
   public function __construct() { 
       $this->width = 300; 
   } 
 
   public function renderBody(){ 
       echo "<input id='$this->id' width='$this->width' value='$this->value' />"; 
   } 
} 

 La closure (nom PHP donné aux méthodes anonymes) permet d’encapsuler du code HTML ou JavaScript dans un code PHP. Cela correspond à la portion de code entre les accolades :

<?php //{layout:../_mainLayout.php}?><?php $model 
require_once=FPLGLobal::
$view_result->model; ?> 
<?php 'controls/datepicker.php'; 
 
   $g = viewComp::instanciate("datePicker","p1"); 
   $g->width = 250; 
   $g->configureJavaScript(...

Corrigé 4.5 Affichage de la liste des rendez-vous

 La liste est définie à l’aide d’une balise <select> qui contient la valeur « Tous » :

<select name="id_utilisateur" id="id_utilisateur"> 
   <option value="null">Tous</option> 
</select> 

Le code JavaScript est exécuté sur l’événement ready() :

// chargement de la liste des utilisateurs 
var lsUrl = '<?php html::action_href("users" , "user", "getuserlist")?>'; 
 
$.get(lsUrl, function (opdata) { 
  $.each(opdata.records, function (key, value) { 
      $('#id_utilisateur').append('<option value=' + 
value.id_utilisateur + '>' + value.utilisateur_nom + '</option>'); 
  }); 
}); 

 Deux composants datePicker sont instanciés :

<?php  
require_once 'controls/datepicker.php'; 
 
$dtstart = viewComp::instanciate("datePicker","dtstart"); 
$dtstart->width = 180; 
$dtstart->value = $model->dtstart; 
$dtstart->configureJavaScript( function() { ?> 
<script> 
$(document).ready(function() { 
   $('#<?php echo $this->id ?>').datepicker({ 
       uiLibrary: 'bootstrap4', 
       locale: 'fr-fr', 
       format: 'dd/mm/yyyy' 
}); 
}); 
</script> 
<?php } ); 
 
   $dtend = viewComp::instanciate("datePicker","dtend"); 
   $dtend->width = 180; 
   $dtend->value = $model->dtend; 
   $dtend->configureJavaScript( function() { ?> 
<script> 
$(document).ready(function() { 
   $('#<?php echo $this->id ?>').datepicker({ ...

Corrigé 4.6 Pour aller plus loin : export de l’agenda dans Outlook ou Gmail

 La classe FPLGlobal comprend une méthode get_route_uri() qui est appelée par HTML::action_href :

<a target="_blank"  
   href="<?php echo  
   html::action_href("agenda", "agenda", "sendmeeting", 
                       array("idev" => $model->evenement->
id_evenement))?>">Obtenir RDV.ics</a> 

 Il faut bien faire attention à nommer dans la route l’identifiant et sa valeur de la même façon, à savoir idev.

/** 
* @Route(parameters="idev-{idev}") 
*/ 
public function sendmeeting($model) { 
   $id_evenement = $model->idev; 
 
   $eservice = new \EvenementService(); 
   $event = $eservice->evenement_get_by_id($id_evenement); 
 
   $participants = $eservice->evenement_get_participant($id_evenement); 

 Compte tenu du nombre d’utilisateurs dans la base et du nombre de participants, itérer sur les utilisateurs est plus avantageux.

$usersvc = new \UserService(); 
$users = $usersvc->getuserlist(); 
 
$organizer = ""; 
$attendees = array(); 
 
foreach($users as $user) { 
   if($user->id_utilisateur==$event->id_utilisateur)  
       $organizer = \ICSService::format_organizer($user->
utilisateur_nom,$user->utilisateur_email); 
    
   foreach($participants as $part) { 
       if($part->id_utilisateur == $user->id_utilisateur) { ...