Un CRUD avec Cold Fusion et ColdBox

Un CRUD avec Cold Fusion et ColdBox

tescoldbox

Voici un exercice de départ avec ColdFusion ORM.On va utiliser ici  le framework Coldbox .

L’interet d’utiliser  l’ORM, entre autres, est de ne plus manipuler la base de donnée directement mais d’utiliser des objets à la place, et que ces objets communiquent entre eux et la base.Il n’ya donc plus de requete SQL dans le code, et les tables se remplissent automatiquement.

Une fois installé, placez le dossier Coldbox dans votre wwwroot comme dans l’image:

wwwroot

Ensuite on ouvre ou on crée un projet .On  va l’appeler contacts, avec l’arborescence suivante:

contacts

dans le dossier téléchargé coldbox/application template/ il y  a des projets coldbox type à copier avec une arborescence plus ou moins fournie.Vous pouvez carrément copier l’ensemble des dossiers d’un template pour partir d’un bon exemple.

Ici on utilise le minimum.

  • Dans le dossier includes/styles, tous nos fichiers css et js,
  • Dans views/contacts nos différentes vues(pages du site).
  • Dans Layout, le fichier central censé redispatcher nos différentes vues, grace à la fonction <cfoutput>#renderView()#</cfoutput> qui fonctionne comme un include normal  ou un get_template_part dans un site wordpress.
  • Dans handlers nos controllers,
  • Dans model nos différents objets
  • Dans config, le fichier de configuration Coldbox.cfc

Voici un a un donc, les fichiers à créer.

1-Creation d’un datasource et d’une base de donnée.

Dans phpMyAdmin, créez simplement une base vide nommée contacts.Le tables se rempliront toutes seules.

Rendez vous sur l’admin de coldfusion à l’adresse: http://127.0.0.1:8500/CFIDE/administrator/index.cfm

Dans la colonne de gauche Rendez vous dans Data&Services puis datasources et créez un nouvelle datasource :

contacts

 

L’environnement est en place et la base est prete à accueillir des données.

Pour éviter tout bug ultérieur, on peut dans l’admin de coldfusion créer un mapping à Coldbox (ce qui permet à notre appli d’aller chercher des fonctions dans le dossier Coldbox, en dehors de notre application ):dans Servers.Settings /Mapping, chercher dans votre ordi l’emplacement de colbox puis créer un mapping en cliquant sur Add mapping

2-Application.cfc

Premier fichier, Application.cfc  à la racine de votre projet :

component extends="coldbox.system.Coldbox" {
this.name = hash(getCurrentTemplatePath());
this.sessionManagement = true;
this.sessionTimeout = createTimeSpan(0,0,30,0);
this.setClientCookies = true;

COLDBOX_APP_ROOT_PATH = getDirectoryFromPath(getCurrentTemplatePath());
COLDBOX_APP_MAPPING = "";
COLDBOX_CONFIG_FILE = "";
COLDBOX_APP_KEY = "";

// ORM Settings
this.ormEnabled = true;
this.ormSettings = {
datasource = "newcontacts",
cfclocation = "model",
dialect="MySQL",
autorebuild=true,
dbcreate = "update",
logSQL = true,
flushAtRequestEnd = false,
autoManageSession = false,
eventHandling = true

};
}

On active l’orm via ce fichier, dans le dernier bloc. (orm enabled=true)

3-ColdBox.cfc

Deuxième fichier primordial, le fichier Coldbox.cfc dans le dossier config

component {

// Configure ColdBox Application
function configure(){

// coldbox directives
coldbox = {
//Application Setup
appName = "contacts",

//Development Settings
debugMode = true,
debugPassword = "",
reinitPassword = "",
handlersIndexAutoReload = true,

//Implicit Events
defaultEvent = "contacts.index",

//Error/Exception Handling
customErrorTemplate = "/coldbox/system/includes/BugReport.cfm",

//Application Aspects
handlerCaching = false,
eventCaching = false
};

// Custom Settings
settings = {
};

orm = {
// entity injection
injection = {
// enable it
enabled = true,
// the include list for injection
include = "",
// the exclude list for injection
exclude = ""
}
};
// environment settings, create a detectEnvironment() method to detect it yourself.
// create a function with the name of the environment so it can be executed if that environment is detected
// the value of the environment is a list of regex patterns to match the cgi.http_host.
/*environments = {
development = "^localhost,^cf,^railo"
};*/

//Layout Settings
layoutSettings = {
defaultLayout = "Layout.main.cfm"
};

//Register interceptors as an array, we need order


datasources = {
myDSN = {name="newcontacts",dbtype="mysql"}
};

}

function development(){
coldbox.debugPassword = "";
coldbox.debugMode = true;
coldbox.reinitPassword = "";
coldbox.handlerCaching = false;
coldbox.handlersIndexAutoReload = true;
coldbox.eventCaching = true;
}

}

 

4-Layout.Main.cfm

Ensuite le fichier central Layout.Main.cfm, à mettre dans le dossier layouts

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Welcome to SimpleCrud!!</title>
<link rel="stylesheet" href="includes/styles/style.css" type="text/css">
</head>
<body>
<!-- wrapper -->
<div class="clr" id="top-head"> </div>
<div id="container">
<!--header -->
<div id="header" >
<div class="logo-bg" >
<!--logo -->
<div class="logo">
LOGO
</div>
<!--head right -->
<div class="right">
<!--// Navigation //-->
<div class="menu_nav">
<div id="nav-wrap">
<ul class="arrowunderline" id="nav">
<li class="index"><a href="index.cfm?event=contacts.index">Home</a></li>

<li class="edit"><a href="index.cfm?event=contacts.editor">Edit</a></li>


</ul>
</div>
</div>
<!--// Navigation End //-->
</div>
<!--// -head right end //-->
</div>
<!--// logo bg end //-->
</div>
<div class="main">
<!--header end -->
<!--- Render The View. This is set wherever you want to render the view in your Layout. --->
<cfoutput>#renderView()#</cfoutput>
</div>
<footer>
Copyright User
</footer>
</body>
</html>

Ici on a fait au plus simple, on pourrait distinguer header et footer, mais pour l’exemple, on inclut ici la structure globale html que l’on veut voir sur toutes les pages.A la place du renderView(), on aura nos différentes pages appelées.

5-Views

Dans le dossier views, j’ai un sous dossier contact, dans lequel j’ai deux fichiers :
editor.cfm

<cfoutput>
<h1>Contact Editor</h1>

#getPlugin("MessageBox").renderit()#
#html.startForm(action="contacts.save")#
#html.entityFields(entity=prc.contacts,fieldwrapper="div")#
#html.submitButton()# or #html.href(href="contacts",text="Cancel")#
#html.endForm()#
</cfoutput>

et index.cfm:

<cfoutput>
<h1>Contacts</h1>
#getPlugin("MessageBox").renderit()#
#html.href(href='contacts.editor',text="Create Contact")#
<br><br>
<cfloop array="#prc.contacts#" index="contact">
<div>
#contact.getName()# (#contact.getEmail()#)<br/>
#html.href(href='contacts.editor&contactID=#contact.getContactID()#',text="[ Edit ]")#
#html.href(href='contacts.delete&contactID=#contact.getContactID()#',text="[ Delete ]",onclick="return confirm('Really Delete?')")#
<hr>
</div>
</cfloop>
</cfoutput>

 

6-Model

Ensuite, notre dossier model, qui contient notre objet Contact.cfc (ou user):

/**
* A cool Contact entity
*/
component persistent="true" table="newcontacts" {

// Primary Key
property name="contactID" fieldtype="id" column="id" generator="native" setter="false";

// Properties
property name="name" ormtype="string";

property name="email" ormtype="string";

// validation
this.constraints = {
name = {required=true},

email = {required=true, type="email"}
};

}

7-Include/styles

Dans Include/styles un petit fichier css pour avoir un minimum de rendu

body {
font: 10pt verdana;
font-family: verdana;
padding: 0;
margin: 10px;
}


td {
padding: 10px;
margin: 0;
}
h2 {
background-color: black;
margin: 0px;
color: #FFFFFF;
padding: 20px;
}

#container{max-width:968px;margin:0 auto;
margin:auto;}
.main{display:table-row}
.content{display:table-cell;min-width: 600px;width:100%;background:#eee}
.aside{display:table-cell; background: red;}
ul, li{list-style-type:none;display:inline-block;margin:0 auto;text-align:center}
ul li{min-width:120px;height:30px;}
ul li a{color:#fff;font-size:16px;line-height:30px;text-decoration:none}
ul li:hover{background:#333}
.menu_nav{background:#444; width:100%}
footer{line-height:30px;text-align:center;width:100%;background:#555}

8-Handlers

Enfin notre controller, dans le dossier handlers : c’est le fichier Contact.cfc dans lequel on place nos différentes fonctions (faisant office de requete) edit, create, delete, et la déclaration de nos différentes vues (avec la fonction SetView)

/**
* I am a new handler
*/
component{

function index(event,rc,prc){
prc.contacts = EntityLoad("Contact", {}, "name");
event.setView("contacts/index");
}

function editor(event,rc,prc){
if(structKeyExists(rc, "contactID") && len(rc.contactID)){
prc.contacts = entityLoad("Contact", rc.contactID, true);
}else{
prc.contacts = entityNew("Contact");
}
event.setView("contacts/editor");
}

function delete(event,rc,prc){
rc.oContact= entityLoad('Contact',rc.contactID,true);
entityDelete(rc.oContact);
ORMflush();

getPlugin("MessageBox").info("Contact Removed!");
setNextEvent("contacts.index");
}

function save(event,rc,prc){
try{
if(structKeyExists(rc, "contactID") && len(rc.contactID)){
oContact = entityLoad("Contact", rc.contactID, true);
}else{
oContact = entityNew("Contact");
}
populateModel( oContact );
entitySave(oContact);
ORMflush();
getPlugin("MessageBox").info("Contact Created!");
setNextEvent("contacts.index");
}catch(any e){
getPlugin("MessageBox").error(e.message);
return editor(event,rc,prc);
}
}

}

 

le fichier index.cfm, présent à la racine du projet doit etre vide, avec la simple mention suivante:

<cfsetting enablecfoutputonly="yes">
<!-----------------------------------------------------------------------
Template : index.cfm
Author : Luis Majano
Date : October 15, 2005
Description :
This is only a place holder since everything occurs in application.cfc now.
----------------------------------------------------------------------->
<cfsetting enablecfoutputonly="no">