Connecting Tech Pros Worldwide Forums | Help | Site Map

OOP: Problem implementing a add, edit, delete Contact form

Member
 
Join Date: Jan 2008
Posts: 113
#1: Aug 12 '08
Hi,

I'm writing a contacts section for a cms on a website, I've decided to write the section in OO code. So far I have my Contacts object and a page structure I would use for a procedural site.

/com/Contacts.cfc
Expand|Select|Wrap|Line Numbers
  1. <cfcomponent displayname="Contact" output="false" hint="Contact component">
  2.     <!--- properties: used for self-documentation --->    
  3.     <cfproperty name="dsn" displayname="dsn" hint="Contact id (UUID)" type="string" required="false" />
  4.     <cfproperty name="id" displayname="id" hint="Contact id (UUID)" type="string" required="false" />
  5.     <cfproperty name="firstName" displayname="firstName" hint="The person's first name" 
  6.         type="string" required="false" />
  7.     <cfproperty name="lastName" displayname="lastName" hint="The person's last name" type="string" 
  8.         required="false" />
  9.     <cfproperty name="address" displayname="address" hint="The person's last name" type="string" 
  10.         required="false" />   
  11.     <cfproperty name="email" displayname="email" hint="The person's email address" type="string" 
  12.         required="false" />
  13.     <cfproperty name="telNo" displayname="telNo" hint="The person's telephone number" type="string" 
  14.         required="false" />
  15.  
  16.     <!--- pseudo-constructor: sets default values if init method isn't called --->
  17.     <cfscript>
  18.         // datasource
  19.         variables.dsn = "";    
  20.         // user details
  21.         variable.id = "";        
  22.         variables.firstName = "";            
  23.         variables.lastName = "";
  24.         variables.email = "";
  25.         variables.address = "";        
  26.         variables.telNo = "";            
  27.     </cfscript>
  28.  
  29.     <cffunction name="init" access="public" output="false" returntype="Contact" hint="Constructor for this CFC">
  30.         <!--- take DSN as argument --->
  31.         <cfargument name="dsn" type="string" required="true" hint="The datasource name" />     
  32.         <!--- arguments for the constructor, all of which are optional (no-arg constructor) --->
  33.         <cfargument name="id" displayName="id" type="string" hint="The person's ID (UUID)" 
  34.             required="false" default="" />
  35.         <cfargument name="firstName" displayName="firstName" type="string" hint="The contact's first name" 
  36.             required="false" default="" />
  37.         <cfargument name="lastName" displayName="lastName" type="string" hint="The contact's last name" 
  38.             required="false" default="" />
  39.         <cfargument name="address" displayName="address" type="string" hint="The contact's address" 
  40.             required="false" default="" />            
  41.         <cfargument name="email" displayName="email" type="string" hint="The contact's email address" 
  42.             required="false" default="" />
  43.         <cfargument name="telNo" displayName="telNo" type="string" hint="The contact's phone 
  44.             number" required="false" default="" />
  45.         <!--- call the setters for each of the Person attributes and pass in the arguments --->
  46.         <cfscript>
  47.             setId(arguments.id);
  48.             setFirstName(arguments.firstName);
  49.             setLastName(arguments.lastName);
  50.             setAddress(arguments.address);
  51.             setEmail(arguments.email);
  52.             setTelNo(arguments.telNo);
  53.         </cfscript>
  54.  
  55.         <!--- return this CFC --->
  56.         <cfreturn this />
  57.     </cffunction>
  58.  
  59.     <!--- getters and setters (aka accessors and mutators) --->
  60.     <cffunction name="getFirstName" access="public" output="false" returntype="string">
  61.         <cfreturn variables.firstName />
  62.     </cffunction>
  63.  
  64.     <cffunction name="setFirstName" access="public" output="false" returntype="void">
  65.         <cfargument name="firstName" type="string" required="true" />
  66.         <cfset variables.firstName = arguments.firstName />
  67.     </cffunction>
  68.  
  69.     <cffunction name="getLastName" access="private" output="false" returntype="string">
  70.         <cfreturn variables.lastName />
  71.     </cffunction>
  72.  
  73.     <cffunction name="setLastName" access="public" output="false" returntype="void">
  74.         <cfargument name="lastName" type="string" required="true" />
  75.         <cfset variables.lastName = arguments.lastName />
  76.     </cffunction>
  77.  
  78.     <cffunction name="getEmail" access="public" output="false" returntype="string">
  79.         <cfreturn variables.email />
  80.     </cffunction>
  81.  
  82.     <cffunction name="setEmail" access="public" output="false" returntype="void">
  83.         <cfargument name="email" type="string" required="true" />
  84.         <cfset variables.email = arguments.email />
  85.     </cffunction>
  86.  
  87.     <cffunction name="getAddress" access="public" output="true" returntype="string">
  88.         <cfreturn variables.address />
  89.     </cffunction>
  90.  
  91.     <cffunction name="setAddress" access="public" output="false" returntype="void">
  92.         <cfargument name="address" type="string" required="true" />
  93.         <cfset variables.address = arguments.address />
  94.     </cffunction>    
  95.  
  96.     <cffunction name="getTelno" access="public" output="true" returntype="string">
  97.         <cfreturn variables.telNo />
  98.     </cffunction>
  99.  
  100.     <cffunction name="setTelno" access="public" output="false" returntype="void">
  101.         <cfargument name="telNo" type="string" required="true" />
  102.         <cfset variables.telNo = arguments.telNo />
  103.     </cffunction>   
  104.  
  105.     <cffunction name="getID" access="public" output="true" returntype="string">
  106.         <cfreturn variables.ID />
  107.     </cffunction>
  108.  
  109.     <cffunction name="setID" access="public" output="false" returntype="void">
  110.         <cfargument name="id" type="string" required="true" />
  111.         <cfset variables.id = arguments.id />
  112.     </cffunction>        
  113.  
  114.     <!--- CRUD - Persistent data functions --->
  115.     <cffunction name="create" access="public" output="false" returntype="boolean" hint="CRUD Method">
  116.         <cfargument name="contact" type="com.Contact" required="true" />
  117.  
  118.         <cftransaction>
  119.             <cfquery name="qCreate" datasource="#variables.dsn#">
  120.                 INSERT INTO
  121.                 contacts
  122.                 (
  123.                 firstName,
  124.                 lastName,
  125.                 address,                
  126.                 email,
  127.                 telNo
  128.                 )
  129.                 VALUES
  130.                 (
  131.                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.car.getFirstname()#" />,
  132.                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.car.getLastname()#" />,
  133.                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.car.getAddress()#" />,
  134.                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.car.getEmail()#" />,
  135.                 <cfqueryparam cfsqltype="cf_sql_varchar" value="#arguments.car.getTelno()#" />                                                             
  136.                 )
  137.                 SELECT @@IDENTITY AS newID
  138.             </cfquery>
  139.               <cfset arguments.contact.setID(qCreate.newID) />
  140.         </cftransaction>
  141.  
  142.       </cffunction>  
  143.      <cffunction name="read" access="public" returntype="Void" output="false" hint="CRUD method">
  144.         <cfargument name="contact" type="com.Contact" required="true" />
  145.         <cfargument name="contactID" type="String" required="yes" />
  146.  
  147.         <cfset var qRead = 0 />
  148.  
  149.         <cfquery name="qRead" datasource="#variables.dsn#">
  150.         SELECT
  151.             firstName,
  152.             lastName,
  153.             address,
  154.             email,
  155.             telNo
  156.         FROM
  157.             contacts
  158.         WHERE
  159.             id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.contactID#" />
  160.         </cfquery>
  161.  
  162.         <cfif qRead.RecordCount>
  163.             <cfset arguments.contact.setID(arguments.contactID) />
  164.             <cfset arguments.contact.setFirstname(qRead.firstname) />
  165.             <cfset arguments.contact.setLastname(qRead.lastname) />
  166.             <cfset arguments.contact.setAddress(qRead.address) />
  167.             <cfset arguments.contact.setEmail(qRead.email) />            
  168.             <cfset arguments.contact.setTelno(qRead.telno) />                           
  169.         <cfelse>
  170.             <cfthrow type="emptyRecordset" errorcode="Contact.read.emptyRecordset" message="Contact with ContactID #arguments.contactID# not found" />
  171.         </cfif>
  172.   </cffunction>
  173.   <cffunction name="update" access="public" returntype="Void" output="false" hint="CRUD method">
  174.     <cfargument name="contact" type="com.Contact" required="yes" />
  175.  
  176.     <cfquery name="qUpdate" datasource="#variables.dsn#">
  177.         UPDATE
  178.             contacts
  179.         SET
  180.             firstName = <cfqueryparam cfsqltype="cf_sql_varchar" value="#contact.getFirstname()#" />,
  181.             lastName = <cfqueryparam cfsqltype="cf_sql_varchar" value="#contact.getLastname()#" />,
  182.             address = <cfqueryparam cfsqltype="cf_sql_varchar" value="#contact.getAddress()#" />,
  183.             email = <cfqueryparam cfsqltype="cf_sql_varchar" value="#contact.getEmail()#" />,
  184.             telNo = <cfqueryparam cfsqltype="cf_sql_varchar" value="#contact.getTelno()#" />
  185.         WHERE
  186.             id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.contact.getID()#" />
  187.     </cfquery>
  188.  
  189.   </cffunction>
  190.  
  191.   <cffunction name="delete" access="public" returntype="Void" output="false" hint="CRUD method">
  192.     <cfargument name="contact" type="com.Contact" required="yes" />
  193.  
  194.     <cfquery name="qDeletePresenter" datasource="#variables.dsn#">
  195.     DELETE FROM
  196.       contacts
  197.     WHERE
  198.       id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.contact.getID()#" />
  199.     ;
  200.     </cfquery>
  201.  
  202.   </cffunction>
  203.  
  204.   <!--- commit methods --->
  205.   <cffunction name="commit" access="public" returntype="Void" output="false" hint="commit method">
  206.     <cfargument name="car" type="com.Contact" required="yes" />
  207.  
  208.     <cfquery name="qExists" datasource="#variables.dsn#">
  209.     SELECT
  210.       id
  211.     FROM
  212.       contacts
  213.     WHERE
  214.       id = <cfqueryparam cfsqltype="cf_sql_integer" value="#arguments.contact.getId()#" />
  215.     ;
  216.     </cfquery>
  217.  
  218.     <cfif qExists.recordcount>
  219.       <cfset this.update(arguments.contact) />
  220.     <cfelse>
  221.       <cfset this.create(arguments.contact) />
  222.     </cfif>
  223.  
  224.   </cffunction>
  225.  
  226.   <!--- public methods --->
  227.   <cffunction name="validate" access="public" returntype="Struct" output="false" hint="I validate all properties in the Contact Object">
  228.     <cfscript>
  229.         // initialize variables
  230.         var errors = StructNew();
  231.  
  232.         // validate values
  233.         if (getFirstName() EQ "") {
  234.             errors.firstName = "The first name field is required";
  235.         }
  236.  
  237.         if (getLastName() EQ "") {
  238.             errors.lastName = "The last name field is required";
  239.         }
  240.  
  241.         if (getAddress() EQ "") {
  242.             errors.address = "The address field is required";
  243.         }
  244.  
  245.         if (getTelno() EQ "") {
  246.             errors.telNo = "The telephone number field is required";
  247.         }
  248.  
  249.         // if we got an email address, validate the format
  250.         if (getEmail() NEQ "") {
  251.             if (Not isEmail(getEmail())) {
  252.                 errors.email = "Your email address is not valid. Please re-enter.";
  253.             }
  254.         }
  255.         else {
  256.             errors.email = "The email field is required.";        
  257.         }
  258.         return errors;
  259.     </cfscript>  
  260.   </cffunction>
  261.     <!--- function to validate email --->
  262.     <cffunction name="isEmail" access="public" output="false" returntype="boolean" hint="Validates 
  263.         the format of the string passed in to see if it's a valid email address">
  264.         <cfargument name="email" type="string" required="true" />
  265.  
  266.         <cfscript>
  267.             if (REFindNoCase("^['_a-z0-9-]+(\.['_a-z0-9-]+)*@[a-z0-9-]+(\.[a-z0-9-]+)*\.(([a-z]{2,3})|(aero|coop|info|museum|name))$", 
  268.                 arguments.email)) {
  269.                 return true;
  270.             } else {
  271.                 return false;
  272.             }
  273.         </cfscript>
  274.     </cffunction>  
  275. </cfcomponent>
  276.  
I usually structure my pages like this:

index.cfm - Contains case statements for url.action
display/add.cfm
display/edit.cfm
display/delete.cfm
com/contacts.cfc

Then I have the usual header and footer includes.

What I'm struggling with is how to structure my pages and deal with the validation of form data. The following is a structure I've kind of cobbled together, based on the idea that there should only be one form for adding / editing (creating/updating) and a cfm for processing the data sent from the form.

index.cfm - Contains case statements for url.action
display/form.cfm - Displays form for creating, updating of contacts.
display/create.cfm - Creates contact object from form elements and adds contact to database
display/update.cfm - Updates contact object from form elements

Has anyone got any examples of how they structure their OO form pages? I'm at the beginning of the CFOO curve and a bit confused!

Thanks,

Chromis

Member
 
Join Date: Jan 2008
Posts: 113
#2: Aug 13 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Ok, I can't figure out how to delete this post so I'll post a new one about where I've got up to.
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 14,581
#3: Aug 14 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Quote:

Originally Posted by chromis

What I'm struggling with is how to structure my pages and deal with the validation of form data.

The problem with validation in COOP (Coldfusion OOP) is that you have two answers that you don't like to hear: "it depends" and "there's no one right answer". Here's an old link, but it gives you an idea of what I mean. This link may help a little. You may also want to look at the series of blog posts on form validation on bennadel.com.
Member
 
Join Date: Jan 2008
Posts: 113
#4: Aug 18 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Hi acoder,

Thanks for the links I'll have a look into these. I was going to code the website I'm creating in a OO fashion, though it's taking too long to work out the best way of doing things. I guess I'll have to keep this as a side project until I'm confident enough with it.

Thanks.

Chromis
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 14,581
#5: Aug 18 '08

re: OOP: Problem implementing a add, edit, delete Contact form


If you've never programmed in OO before, it can be a bit of a steep learning curve, but I'm sure you'll get there. If you're trying to stick to MVC as well, it can be even more difficult at first, though it'll be beneficial in the long run. Only use MVC for medium to large projects; there's no need for the complexity for small projects.
Member
 
Join Date: Jan 2008
Posts: 113
#6: Aug 18 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Ok cool I'll remember that. What I struggle with is how to structure the pages for the smaller projects, is the structure I use above ok or do i need to create controller objects for dealing with page requests such as index.cfm?action=edit?

Any chance you could give me an example of a small project you have worked on so I can see how you do things?
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 14,581
#7: Aug 18 '08

re: OOP: Problem implementing a add, edit, delete Contact form


You could use a DAO bean. This is a good series of articles, in particular you may find this part useful.
Member
 
Join Date: Jan 2008
Posts: 113
#8: Aug 19 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Hi acoder,

Thanks I'd actually been reading through that article. I'm building a good list of resources though now, ben nadel and sean corfield have good blogs that i've been looking through. It's just going to take some time i guess.

Thanks,

Chromis
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 14,581
#9: Aug 19 '08

re: OOP: Problem implementing a add, edit, delete Contact form


Yes, those are good blogs as well as Raymond Camden's and a few others.

Anyway, good luck on the OOP quest! :)
Reply


Similar ColdFusion bytes