Décryptage de l'application Movies
-
Ce chapitre suppose que vous ayez suivi le tutoriel par l’exemple de développement d’applications sous it.rocks depuis son début.
Il est recommandé de commencer par lire les articles ci-dessous, les concepts déjà présentés ne seront pas repris ici :- Créer une application
- Un carnet d’adresses vite fait bien fait
- Fonctionnalités disponibles en standard sur l’application carnet d’adresses
- Structure du projet et décryptage de l’application carnet d’adresses
Structure du projet
- A la différence des applications Hello world et Carnet d’adresses, on a supprimé le fichier Application_home.html, car on ne souhaite pas personnaliser la page d’accueil.
La plupart des composants de votre logiciel sont optionnels : s’ils sont absents, le framework utilisera un composant par défaut, comme ici une page d’accueil vierge.
- S’agissant pour l’instant d’un petit projet, l’ensemble des classes métier ont été placées directement dans le dossier du projet nickname/movies. Il est cependant conseiller de toujours considérer son logiciel dans son potentiel d’évolution, et dès le commencement de placer les classes métier dans des sous-dossiers correspondants à des modules de votre logiciel, ou des sous-sous-dossiers pour des sous-modules, etc, de manière à ce que vos classes soient dès le départ stockées dans un emplacement durable à long terme.
En effet déplacer une classe après coup nécessitera de modifier son namespace, et donc toutes les références à cette classe dans votre projet.
Voir le tutoriel Organiser votre projet en modules et sous-modules pour l’évolution du logiciel Movies apportée dans ce sens.
Pour l’instant, notre petit logiciel de gestion n’a nécessité rien d’autre que ses fichiers de configuration, sa classe Application et ses classes métiers. Aucun autre fichier particulier ne vient donc complexifier la structure de votre projet.
Nouvelles règles de gestion sur les propriétés
De nombreuses annotations permettent de préciser des règles de gestion sur les valeurs de propriétés.
Quelques exemples ici :- @mandatory : la saisie d’une valeur est obligatoire pour cette propriété
- @max_length 10000 : le nombre de caractères maximum qui peuvent être saisis pour la propriété (par défaut : 255 pour une chaîne de caractères).
- @min_length 100 : il est obligatoire de saisir au moins 100 caractères pour cette propriété.
- dimensionnement des contrôles de saisie en interactif, et guide de l’utilisateur pendant la saisie : par exemple la saisie n’est plus possible si on a atteint le nombre de caractères maximum autorisés,
- contrôles de validation lors de l’enregistrement des enregistrements, si le plugin Validate est activé (par défaut : non).
Nouvelles fonctionnalités sur les propriétés : gérer les relations entre classes
Personnality::$birth_place : propriété de type classe
/** * @link Object * @mandatory * @var Country */ public $birth_place;
Pour stocker le lieu de naissance de notre personnalité, nous avons choisir de gérer une table de noms de pays, chacun stocké dans un objet
Country
. Pour faire référence à un objet, il faut comme ici :- @var Country : Définir le type de la propriété comme étant la classe voulue.
Cette annotation est essentielle pour assurer une bonne complétion automatique dans votre IDE, et est utilisée par it.rocks pour automatiser les accès aux données, affichages avec liste combo, etc.
- @link Object : Annoncer qu’on utilisera le lien de donnée Objet.
Cette simple annotation déclenche les mécanismes nécessaires à la lecture différée de l’objet tiers. C’est elle qui permet que même si vous n’avez récupéré de la base de données qu’un objet personnalité, la première consultation de la propriété$birth_place
dans votre programme déclenche automatiquement la lecture de l’objet depuis votre base de données, sans aucune programmation de votre part.
Exemple :$birth_place = $personality->birth_place;
: l’objet de classeCountry
n’est lu qu’au moment où il est demandé.
Personnality::$jobs : stockage de valeurs prédéfinies multiples
/** * @mandatory * @values actor, director, producer, writer * @var string[] */ public $jobs;
Ici, à la différence de
$birth_place
, on s’affranchit d’une table de valeurs dynamique : lorsque les valeurs possibles pour une chaîne de caractères sont limitées et resteront figées dans votre application, la déclaration d’une propriété avec @var string[] en indiquant la liste des valeurs disponibles dans l’annotation @values suffit.Cas d’école similaire : si l’on avait voulu ne stocker qu’un seul métier par personnalité, il aurait suffi de définir le type de propriété @var string . Cette nuance suffit à modifier le mode de gestion de la propriété pour n’accepter qu’une seule valeur.
/** * @mandatory * @values actor, director, producer, writer * @var string */ public $job;
Movie::$casting : propriété de type tableau d’objets d’une même classe
/** * @link Map * @var Personality[] */ public $casting;
La gestion des personnalités faisant partie du casting d’un film est le cas type correspondant à une relation n-à-n en bases de données : les personnalités sont des entités indépendantes des films, elles peuvent avoir travaillé sur plusieurs films, et un film accueille plusieurs personnalités. Ces annotations permettent de faire référence à une liste d’objets :
- @var Personality[] : Définir le type de propriété comme étant un tableau de la classe voulue.
- @link Map : Annonce qu’on utilisera le lien de donnée Map vers plusieurs instances de la classe indépendantes de notre classe, par opposition au lien de donnée Collection, voir exemple plus loin.
Comme ci-dessus avec le lien de donnée Objet, cette simple annotation déclenche les mécanismes nécessaires à la lecture différée de la liste d’objets tiers. Lorsque vous récupérez un film depuis la base de données, les personnalités associées ne sont pas lues immédiatement : cette lecture n’a lieu que la première fois où vous accédez depuis votre programme à la propriété$casting
, sans besoin de plus de programmation de la part du développeur.
Exemple :foreach ($movie->casting as $personnality)
: les objets de classePersonality
ne sont lus qu’au moment où on a besoin d’y accéder.
Movie::$comments : propriété de type collection d’objets composants
/** * @link Collection * @var Comment[] */ public $comments;
La gestion des commentaires sur un film est le cas type d’une relation 1-à-n en bases de données : un commentaire ne correspond qu’à un seul film, et un film peut se voir associer autant de commentaires que nécessaire.
Les commentaires n’ont pas de sens ni d’existence propre en dehors du contexte d’un film : on parle donc pour
Movie
de classe composite et pourComment
de classe composante. Comme vous le verrez plus loin, la classeComment
doit suivre une déclaration particulière pour renforcer ce lien de dépendance.Ces annotations permettent de faire référence à une collection d’objets composants :
- @var Comment[] : Définir le type de propriété comme étant un tableau de la classe voulue.
- @link Collection : Annonce qu’on utilisera le lien de donnée Collection vers plusieurs instances de la classe composante, par opposition au lien de donnée Map, voir exemple précédemment.
Comme pour les autres valeurs de l’annotation @link, cette simple annotation déclenche les mécanismes nécessaires à la lecture différée de la collection d’objets composants. Lorsque vous récupérez un film depuis la base de données, les commentaires associés ne sont pas lus immédiatement : cette lecture n’a lieu que la première fois où vous accédez dans votre programme à la propriété$comments
, sans besoin de plus de programmation de la part du développeur.
Exemple :foreach ($movie->comments as $comment)
: les objets de classeComment
ne sont lus qu’au moment où on a besoin d’y accéder.
Nouvelles fonctionnalités sur les classes
Classe Movies : Annotation set
* @set Movies
L’annotation @set permet d’indiquer à it.rocks quel est le pluriel du nom de la classe. Ici
Movies
étant déclaré comme pluriel deMovie
, le contrôleur principal de l’application traitera systématiquement les liensMovies
comme étant des ensembles deMovie
, au lieu d’utiliser l’algorithme par défaut qui essaie de deviner le singulier des mots, pas toujours de façon fiable, les règles syntaxiques n’étant pas constantes pour tous les mots du vocabulaire anglo-saxon.
Ici par défaut pour le lien Nickname/Movies/Movies, le framework aurait cherché la classe Nickname/Movies/Movy, qui évidemment n’existe pas. Les règles actuelles de calcul du mot singulier à partir du pluriel sont décrites dans la documentation de l’annotation @set .Classe Personnalities : Annotation sort
* @representative first_name, last_name * @sort last_name, first_name
L’annotation @sort indique l’ordre de tri par défaut appliqué aux collections d’objets de cette classe, lorsque le tri est demandé. Notamment tant que l’utilisateur ne décide pas de changer cet ordre de tri, ce sera celui appliqué aux listes.
On indique ici une liste de propriétés dont les valeur serviront pour ce tri.
A défaut de définition, l’ordre de tri par défaut est celui lu dans l’annotation @representative. Ici, sans annotation @sort, l’ordre tri par défaut serait par prénom, puis par nom. Notre réglage permet de modifier ce choix lorsque le développeur le souhaite.
Classe Countries : Trait pré-programmé Has_Name
use ITRocks\Framework\Trait\Has_Name;
Certains traits très fréquemment utilisés par les logiciels de gestion ont été pré-programmés dans le framework, comme ici le trait Has_Name.
Faire appel à ce trait économise l’inscription dans notre classeCountries
du code nécessaire au stockage d’un nom, et offre à notre classe :- une propriété à saisie obligatoire
$name
, - une méthode __toString par défaut qui va tout simplement représenter votre objet par son nom,
- les annotations de classe par défaut @representative et @sort pour représenter les pays par leur nom, et définir l’ordre de tri standard des pays par leur nom.
Vous pouvez consulter le code source des autres traits présents dans le dossier itrocks/framework/traits de votre projet, pour connaître les différents traits proposés par défaut et éviter de programmer les définitions correspondantes si les modules proposés par le framework conviennent à votre besoin.
Class Comment : Trait pré-programmé Component
use ITRocks\Framework\Mapper\Component;
L’intégration du trait Component est obligatoire lorsque vous créez une classe métier dont les objets n’auront de sens que comme composant d’un objet parent, qu’on appellera composite. Ici les commentaires s’appliquent systématiquement aux films, la classe
Comment
est donc composante deMovie
./** * @composite * @link Object * @mandatory * @var Movie */ public $movie;
La classe composante doit obligatoirement intégrer une propriété reliant l’objet composite, ici
$movie
. On a explicitement identifié cette propriété comme étant le lien vers l’objet composite par l’annotation de propriété @composite, pour que ce soit clair et qu’on ne risque pas de confusion si à l’avenir d’autres propriétés de typeMovie
étaient ajoutées, mais le framework est capable lorsqu’il n’y a pas de conflit possible de deviner seul quelle est la propriété composite d’une classe composante.