Action :
Exemple
Sommaire |
Analyse du besoin applicatif
Afin de permettre une bonne approche du framework nano, nous partirons d'un exemple assez simple : la création d'un site de type "blog".
Ce site servira à la publication de nouvelles (News) ou d'article. Ces deux entités pourrons entre être commentées par des visiteurs non connectés.
Les news et articles seront déposé par des utilisateurs connectés.
Les news et articles pourront être classés par des "tags".
Nous identifierons donc les classes participantes suivantes :
- Article
- News
- Tag
- Comment
- Person (visiteur)
- User (utilisateur connecté)
Le modèle de classes
Définition du modèle : le schéma
Définition du modèle : le fichier yml
Nous pouvons aisément déduire de notre exemple, le diagramme de classes participantes :
Nous pouvons désormais transcrire ce modèle de classes dans un fichier YAML qui va nous permettre de générer les classes PHP nécessaires à la manipulation de nos objets :
/configuration/schemas/schema001.yml (001 correspondant à la version du modèle)
class : Comment : attributes : body : type : text published : type : boolean constraints : created_by : foreignClass : Person localAlias : created_by foreignAlias : comments type : has_one taggable_content : foreignClass : TaggableContent localAlias : taggable_content foreignAlias : comments type : has_one access : final User : extends : Person attributes : login : type : varchar(255) password : type : varchar(255) checked : type : boolean access : final TaggableContent : attributes : title : type : varchar(255) i18n : true extract : type : text i18n : true body : type : text i18n : true created_at : type : timestamp updated_at : type : timestamp published : type : boolean constraints : created_by : foreignClass : User localAlias : created_by foreignAlias : taggable_contents type : has_one access : abstract Article : extends : TaggableContent access : final News : extends : TaggableContent access : final Tag : attributes : label : type : varchar(255) constraints : taggable_content_tag: foreignClass : TaggableContent localAlias : taggable_contents foreignAlias : tags type : has_and_belong_to_many access : final Person : attributes : first_name : type : varchar(255) last_name : type : varchar(255) email : type : varchar(255) web_site : type : varchar(255)
Génération des modèles
Une fois notre modéle de classe décrit dans le fichier YAML, il est trés simple de générer toutes les couches du modèle via la commande script/nano generate-models. Nous obtenons en sortie :
jean-philippe@jean-philippe-laptop:~/www/open-solutions$ script/nano generate-models loading Tag loading Person loading User loading TaggableContent loading Article loading News loading Comment ------------------------------------------------------------ ------------ generating yml class file --------------------- ------------------------------------------------------------ /home/jean-philippe/www/open-solutions/configuration/../configuration/schemas/schema001.class.yml written ------------------------------------------------------------ ------------ generating class model layer ------------------ ------------------------------------------------------------ /home/jean-philippe/www/open-solutions/configuration/../models/class/Tag.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Person.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/User.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/TaggableContent.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Article.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/News.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Comment.php written ------------------------------------------------------------ ------------ generating orm model layer ------------------ ------------------------------------------------------------ / /home/jean-philippe/www/open-solutions/configuration/../models/class/Tag.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Person.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/User.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/TaggableContent.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Article.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/News.php written /home/jean-philippe/www/open-solutions/configuration/../models/class/Comment.php written ------------------------------------------------------------ ------------ generating yml mpd file ----------------------- ------------------------------------------------------------ /home/jean-philippe/www/open-solutions/configuration/../configuration/schemas/schema001.mpd.yml written ------------------------------------------------------------ ------------ generating mpd model layer -------------------- ------------------------------------------------------------ /home/jean-philippe/www/open-solutions/configuration/../models/mpd/Tag.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/Person.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/User.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/TaggableContent.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/TaggableContentI18n.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/Article.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/News.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/Comment.php written /home/jean-philippe/www/open-solutions/configuration/../models/mpd/TaggableContentTag.php written /home/jean-philippe/www/open-solutions/configuration/../configuration/schemas/class.map.yml written written
Le modèle de données
Une fois le modèle de classe généré, il faut générer le modèle de données pour permettre l'abstraction.
Generation du SQL de création
Afin de créer toutes les tables necessaires, nous utiliserons la commande : script/nano build-sql Nous obtenons en sortie :
SET AUTOCOMMIT=0; SET FOREIGN_KEY_CHECKS=0; CREATE DATABASE IF NOT EXISTS opensolutions; DROP TABLE IF EXISTS `tag`; CREATE TABLE `tag` ( `id` integer auto_increment not null, `label` varchar(255), CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; DROP TABLE IF EXISTS `person`; CREATE TABLE `person` ( `id` integer auto_increment not null, `first_name` varchar(255), `last_name` varchar(255), `email` varchar(255), `web_site` varchar(255), CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; DROP TABLE IF EXISTS `user`; CREATE TABLE `user` ( `id` integer auto_increment not null, `login` varchar(255), `password` varchar(255), `checked` boolean, `person_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `user` ADD CONSTRAINT FOREIGN KEY (`person_id`) REFERENCES `person`(`id`) on delete cascade; DROP TABLE IF EXISTS `taggable_content`; CREATE TABLE `taggable_content` ( `id` integer auto_increment not null, `created_at` timestamp, `updated_at` timestamp, `published` boolean, `user_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `taggable_content` ADD CONSTRAINT FOREIGN KEY (`user_id`) REFERENCES `user`(`id`) ; DROP TABLE IF EXISTS `taggable_content_i18n`; CREATE TABLE `taggable_content_i18n` ( `id` int auto_increment, `culture` varchar(8), `taggable_content_id` integer, `title` varchar(255), `extract` text, `body` text, CONSTRAINT PRIMARY KEY (`id`,`taggable_content_id`) ) Type = InnoDB; ALTER TABLE `taggable_content_i18n` ADD CONSTRAINT FOREIGN KEY (`taggable_content_id`) REFERENCES `taggable_content`(`id`) on delete cascade; DROP TABLE IF EXISTS `article`; CREATE TABLE `article` ( `id` integer auto_increment not null, `taggable_content_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `article` ADD CONSTRAINT FOREIGN KEY (`taggable_content_id`) REFERENCES `taggable_content`(`id`) on delete cascade; DROP TABLE IF EXISTS `news`; CREATE TABLE `news` ( `id` integer auto_increment not null, `taggable_content_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `news` ADD CONSTRAINT FOREIGN KEY (`taggable_content_id`) REFERENCES `taggable_content`(`id`) on delete cascade; DROP TABLE IF EXISTS `comment`; CREATE TABLE `comment` ( `id` integer auto_increment not null, `body` text, `published` boolean, `person_id` integer, `taggable_content_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `comment` ADD CONSTRAINT FOREIGN KEY (`person_id`) REFERENCES `person`(`id`) ; ALTER TABLE `comment` ADD CONSTRAINT FOREIGN KEY (`taggable_content_id`) REFERENCES `taggable_content`(`id`) ; DROP TABLE IF EXISTS `taggable_content_tag`; CREATE TABLE `taggable_content_tag` ( `id` integer auto_increment, `tag_id` integer, `taggable_content_id` integer, CONSTRAINT PRIMARY KEY (`id`) ) Type = InnoDB; ALTER TABLE `taggable_content_tag` ADD CONSTRAINT FOREIGN KEY (`tag_id`) REFERENCES `tag`(`id`) on delete cascade; ALTER TABLE `taggable_content_tag` ADD CONSTRAINT FOREIGN KEY (`taggable_content_id`) REFERENCES `taggable_content`(`id`) on delete cascade; SET FOREIGN_KEY_CHECKS=1;
Generation de la base de données
Pour générer la base de données, il suffit d'exécuter la commande : script/nano build-base
on obtient :
jean-philippe@jean-philippe-laptop:~/www/open-solutions$ script/nano build-base Generating sql file... Ok Loading sql file... Ok
Manipulation des objets
Une fois notre modèle et la base de données générés, on peut commencer à manipuler nos objects.
Les méthodes delete() et save()
Pour rentrer dans le vif du sujet, nous allons créer un premier objet User et le sauvegarder en base de données.
//instanciation de l'objet $user=new User(); //attribution des valeurs $user->first_name='Bart'; $user->last_name='Simpson'; $user->login='bart'; $user->pass=md5('my_pass'); //sauvegarde de l'objet $user->save(); //suppression de l'objet $user->delete();
On peut noter que nous ne manipulons que la classe finale User, les données étant elles sauvegardées sur les tables person et user (héritage).
Les finders
Les finders sont des méthodes permettant de récuperer des objets sauvegardés précédement.
//instanciation de l'objet $user=new User(); //récupération de l'objet User d'id 1 $user=$user->find_by_id(1);
La méthode find_by_id($id) renvoi un objet.
//finder par attribut de classe $user=$user->find_by_first_name('Bart'); //finder par object : find_by_local_alias($object) $comment=new Comment(); $comment->find_by_id(1); $user=$user->find_by_comments($comment);
Les autres finders renvoient des collection d'objets.
La methode add_local_alias()
Dans le cas d'une relation n.....n, on peut lier des objects via la methode add_local_alias($object).
$tag=new Tag(); $tag->label="Php"; $tag->save(); $article=new Artcile(); $article=$article->find_by_id(1); $article->add_tags($tag);
La methode remove_local_alias()
Dans le cas d'une relation n.....n, on peut délier des objects via la methode remove_local_alias($object).
$tag=new Tag(); $tag->label="Php"; $tag->save(); $article=new Artcile(); $article=$article->find_by_id(1); $article->remove_tags($tag);



