Log In:Register.
QuickContent: Part 1 - Extending the Core

Ok, so I have this friend. A great coder in all aspects. He's actually what you would call my Teacher, though he is younger than me and even he will admit I have surpassed him in ColdFusion knowledge (he's strictly php for web dev now). For today, I'll call him switchprog. Switchprog has this great page called GreaterScope. Anywho, so one day he mentions this new way of doing content to me. He calls it 'QuickContent'.

So, I decide I need to know more about this 'quickContent' thing of his, so next time he's in Town we head down to the local R.J. Gators for som grub and to take part in our 4-5 hour ritual of talking code with each other. So he tells me in more detail about quickContent and even has brought me printouts of his code (YEAH!!!). It realy looks interesting to me, so I decide that I need to look further into the posiblity of using it for my own ventures.

The way QuickContent works seems really revolutionary to me, but please understand, I am relatively new to programming in an OO enviroment. I wrote MeiliBox OOP to help understand it, but at the time I was introducted to quickContent I still had trouble understanding the finer points of OOP. Ok, so here we go, I will discuss in detail my implementation of quickContent..

QuickContent consists of only a few functions: List, Read, Add and Edit. There are a few more, but those are the basic functions. They are really quite self expanatory, so I'll save you a long unneeded lecture on what they do. Now, to some, this may not seem so revolutionary, but the good part comes in when you add (what I will call) insertion points. These points are functions placed at the beginning and end of each of the 4 major functions for extending the object to handle almost any application for content. In the base object, they merely return the data sent in or basically do nothing.

To see the full potential of QuickContent, I will discuss, in part, my implementation of it into my Gallery located on this site. For this object, I have actually extended the QuickContet object twice. The first time to create what I call a Dynamic QuickContent object. This is also another idea of Switchprogs which uses a 'flex' table to store dynamic fields. In my implementation of the flex fields I actually use 4 tables:

  • extra_fields : stores the fields used by the object. I have a column name 'section_id' that I use to allow me to use this same table for multiple objects.
  • boolean_fields: This is self explanatory. I use this field for boolean fields. When used with SQL Server or any DBMS that supports a bit column, it can really save some space. In MySQL I use a tinyint(1) field.
  • int_fields: This is also self explanatory. This is just used for integer fields.
  • text_fields: This field is used for all other columns.
Some may say this is really inefficient space wise, and I tend to agree, but I am willing to give up some efficiency in order to gain the flexibility of this object. In this object I use the pre and post functions to make sure that I pull and save the appropriate fields to the appropriate tables. For instance, in the read function, the quickContent object calls 'postRead()' which I've overwritten in dyn_quickContent. The preRead() function grabs all the data from the appropriate tables and then appends those fields as columns on the main read funtion. This allows me to use the query returned like any other query without having to do any funky query management in the view files. Here is a copy of my code for the 'retrieveJoinQuery()' function which is called from postRead() to append the data:
retrieveJoinQuery()
 <cffunction name="retrieveJoinQuery" access="private" output="true" returntype="query">
  <cfargument name="funcArgs" required="yes" type="struct"/>
  <cfargument name="qry" required="true" type="query"/>
  <cfset var contentQry = '/>
  <cfset var retQry = arguments.qry/>
  <cfset var contentStruct = structNew()/>
  <cfparam name="arguments.funcArgs.format" default="false"/>
  <!--- <cfif retQry.recordcount eq 0>
   <cfset retQry = queryNew('content_id,name,content,cat_id,section_id,active,authorName,author,created,totalRowsFound')/>
   <cfset queryAddRow(retQry)/>
   <cfset querySetCell(retQry,'content_id',0)/>
   <cfset querySetCell(retQry,'section_id',variables.section_id)/>
   <cfset querySetCell(retQry,'active',0)/>
   <cfset querySetCell(retQry,'created',now())/>
   <cfset querySetCell(retQry,'totalRowsFound',0)/>
  </cfif> --->
  <cfif retQry.recordcount gt 0>
   <cfloop query="retQry">
    <cfquery name="contentQry" datasource="#variables.datasource#">
     select    a.name,
               a.field_id,
               case
                when a.type = '1'
                 then b.data
                when a.type = '2'
                 then c.data
                when a.type = '3'
                 then d.data
                else '
               end as data,
               a.format
     from      #variables.tablePrefix#content_extra_fields a
     left join #variables.tablePrefix#content_text_fields b
            on b.field_id = a.field_id
           and b.content_id = '#retQry.content_id#'
     left join #variables.tablePrefix#content_int_fields c
            on c.field_id = a.field_id
           and c.content_id = '#retQry.content_id#'
     left join #variables.tablePrefix#content_boolean_fields d
            on d.field_id = a.field_id
           and d.content_id = '#retQry.content_id#'
     where     a.section_id = #variables.section_id#
     order by  a.type
    </cfquery>
    <!--- If there are extra fields for the content item, append them as column on the main query --->
    <cfif contentQry.recordcount eq 0>
     <cfset queryAddRow(contentQry)/>
    </cfif>
    <cfloop query="contentQry">
     <cfif retQry.currentRow eq 1>
      <cfset contentStruct[name] = arrayNew(1)/>
     </cfif>
     <cfif arguments.funcArgs.format and variables.usebbCode>
      <cfset contentStruct[name][retQry.currentrow] = variables.bbcodeParser.parseText(data)/>
     <cfelse>
      <cfset contentStruct[name][retQry.currentrow] = data/>
     </cfif>
    </cfloop>
                <cfif arguments.funcArgs.format and variables.usebbCode>
                    <cfset retQry.content = variables.bbcodeParser.parseText(retQry.content) />
                </cfif>
    <!--- <cfdump var="#contentQry#"/><cfdump var="#retQry#"/> --->
   </cfloop>
   <cfloop query="contentQry">
    <cfset queryAddColumn(retQry,name,contentStruct[name])/>
   </cfloop>
  </cfif>
  <cfreturn retQry/>
 </cffunction>

Now that I have my Dynamic QuickContent object, I extend my gallery object to that object. In the gallery Gallery object, the retrieval of data isn't much affected by the new object. Instead the additions are to the Pre and Post save functions. Here I have to deal with the uploads of images.

This is just a simple explanation of the QuickContent Object and I hope to be adding more detailed information in the form of articles in the near future.

(3)Comments | < Back
Comments
Wednesday, August 23, 2006 by
test
Sunday, August 20, 2006 by SirMeili
test
Frank Thompson
aka Sir Meili
Certified Advanced Coldfuction MX Developer
Sunday, August 20, 2006 by SirMeili
test2
Frank Thompson
aka Sir Meili
Certified Advanced Coldfuction MX Developer
Leave a Comment
Please log in to leave a comment.