Help | Site Map
Connecting Tech Pros Worldwide
Reply
 
LinkBack Thread Tools
  #1  
Old August 12th, 2008, 01:47 PM
Member
 
Join Date: Jan 2008
Posts: 85
Default OOP: Problem implementing a add, edit, delete Contact form

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
Reply
  #2  
Old August 13th, 2008, 10:37 AM
Member
 
Join Date: Jan 2008
Posts: 85
Default

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.
Reply
  #3  
Old August 14th, 2008, 10:07 AM
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 12,766
Default

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.
Reply
  #4  
Old August 18th, 2008, 10:09 AM
Member
 
Join Date: Jan 2008
Posts: 85
Default

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
Reply
  #5  
Old August 18th, 2008, 11:14 AM
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 12,766
Default

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.
Reply
  #6  
Old August 18th, 2008, 12:45 PM
Member
 
Join Date: Jan 2008
Posts: 85
Default

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?
Reply
  #7  
Old August 18th, 2008, 07:14 PM
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 12,766
Default

You could use a DAO bean. This is a good series of articles, in particular you may find this part useful.
Reply
  #8  
Old August 19th, 2008, 02:05 PM
Member
 
Join Date: Jan 2008
Posts: 85
Default

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
Reply
  #9  
Old August 19th, 2008, 03:04 PM
acoder's Avatar
Site Moderator
 
Join Date: Nov 2006
Location: UK
Posts: 12,766
Default

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

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

Bookmarks

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are Off
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

What is Bytes?

We are a network of experts and professionals in IT and software development that help one another with answers to tough questions and share insights. Get the best answers to your questions from over network members.
Post your question now . . .
It's fast and it's free

Popular Articles