Skip to content

Instantly share code, notes, and snippets.

@learncfinaweek
Created November 20, 2012 21:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save learncfinaweek/4121293 to your computer and use it in GitHub Desktop.
Save learncfinaweek/4121293 to your computer and use it in GitHub Desktop.
ORM - Hands On 21

In this hands on, we are going to add categories to blog posts. The logic for this involves creating a linking entity to which both the blog post and category will be associated. This is an alternative method to using a many-to-many relationship.

Tags Used: <cfloop>, <cfset>

Functions Used: EntitySave, for, listAppend, EntityDelete

  1. In order to be able to associate multiple categories to a blog post and also be able to associate multiple blog posts to a category, we need to create a linking entity. Create a new file called blogPostCategory.cfc in the /www/com/entity/ folder.
  2. Open up the /www/com/entity/blogPostCategory.cfc file in your code editor.
  3. Add the following lines of code:
    component persistent="true" {
    	property name="blogPost" fieldtype="id,many-to-one" cfc="blogPost" column="blogPostid" ;   
    	property name="blogCategory" fieldtype="id,many-to-one" cfc="blogCategory" column="blogCategoryid" ;   
    }	
    
  4. Now that the linking entity is created, you need to associate that entity to both the blogPost entity and the blogCategory entity. To do this, open up the /www/com/entity/blogPost.cfc file in your code editor.
  5. Locate where the comment relationship is defined. This should be on or around line 11.
  6. After this line of code add the following line of code:
    property name="categories" fieldtype="one-to-many" cfc="blogPostCategory" fkcolumn="blogpostid";
    
  7. The line you just entered associates the blog post to the blogPostCategory entity. The next step is to do the same for the blogCategory. Open up the /www/com/entity/blogCategory.cfc file in your code editor.
  8. Locate the name property definition on or around line 2 and add the following line of code below it:
    property name="posts" fieldtype="one-to-many" cfc="blogPostCategory" fkcolumn="blogCategoryid";
    
  9. Now that the entity properties have been set, reload the application so the ORM changes can take effect. To do this, go to the /www/index.cfm page in your browser and append ?reload=1 to the URL.
  10. Your application has now created the new linking table and you have the new entity properties at your disposal. Next, let's write the logic which will save categories to a blog post. Open up the /www/admin/content/blog/editblogpost.cfm file in your code editor.
  11. Locate the 'Add Category to Entity' comment.
  12. Below the comment, instantiate a new instance of the BlogPostCategory and call the variable 'blogPostCategory'.
  13. Below that line, load in a blogCategory object and use the variable categoryID as the identifier and call the variable blogCategory.
  14. Your code should look similar to this:
    <cfloop list="#form.categories#" index="categoryID">
    	<!--- Add Category to Entity --->
    	<cfset blogPostCategory = EntityNew('blogPostCategory') />
    	<cfset blogCategory = EntityLoad('blogCategory',categoryID,true) />
    </cfloop>
    
  15. After the blogCategory variable has been created, set the values of the blogPostCategory. The first value to be set is the blogCategory. To do this, set the blogCategory property value of the blogPostCategory object to the blogCategory variable. Your code should be similar to this:
    <cfset blogPostCategory.blogCategory = blogCategory />
    
  16. Next, set the blogPost property of blogPostCategory with the blogPost variable which was saved earlier in the page.
  17. Once this is done, save the entity. Simply call the entitySave function and pass in the blogPostCategory object. Your final code should look similar to this:
    <cfloop list="#form.categories#" index="categoryID">
    	<!--- Add Category to Entity --->
    	<cfset blogPostCategory = EntityNew('blogPostCategory') />
    	<cfset blogCategory = EntityLoad('blogCategory',categoryID,true) />
    	<cfset blogPostCategory.blogCategory = blogCategory />
    	<cfset blogPostcategory.blogPost = blogPost />
    	<cfset entitySave(blogPostCategory) />
    </cfloop>
    
  18. Now that this logic is complete, we can associate a category with a blog post and save it. Open up the /www/admin/content/editBlogPost.cfm page in your browser.
  19. Enter some blog information, select a category, and click 'save'.
  20. You will see on the listing page showing that the blog post has been saved. Click on the blog post you just saved and review the data on the screen.
  21. You will notice that the category is not pre-checked. This is not because the category has not been saved, but because we have not put the logic in place to generate the list of category ID's that the page needs. To do this, you need to set a form value called 'categories'. Locate the 'Get Entity Data' comment tag.
  22. Below the last <cfset> tag in the <cfif> block, create a new <cfset> tag that sets blogpost.categoryids to the variable form.categories. Your code should look similar to this:
    <cfset form.categories = blogPost.categoryids  />
    
  23. If you were to run the page now, you would generate an error. The functionality to get the category ID's is not present in the blogPost entity. We must first create that functionality by adding a custom function into the blogPost entity. Open up the /www/com/entity/blogPost.cfc file in your code editor.
  24. Below the last property definition, create a public function that returns a string and is called getCategoryIDs.
  25. Inside the function, create a variable called categoryList, assign it to the var scope and set it to an empty string. Your code should look similar to this:
    public string function getCategoryIDs(){
    	var categoryList = '';
    

    }

  26. Next, check that the blogPost actually has some categories from which to generate a list. To do that, create an if statement that calls the hasCategories() function.
  27. Inside of the if statement, begin looping over the categories and concatenating a string of their ID's. To do this, create the following for loop inside the if statement:

    for ( var categoryPost in getCategories() ) {
    
    }
    
    	</li>
    	<li>
    		Inside the <span class="code">for</span> loop, get the <span class="code">ID</span> of the <span class="code">blogCategory</span> and append it to the <span class="code">categoryList</span> variable. To get the category ID access the <span class="code">blogCategory</span> property and then access the ID value from the returned <span class="code">BlogCategory</span> object. Use the <span class="code">listAppend</span> function to append that result with the <span class="code">categoryList</span> variable. The code will look similar to this:
    
    categoryList = listAppend( categoryList, categoryPost.blogCategory.id);
    
    	</li>
    	<li>
    		Finally, return the generated list by calling the <span class="code">return</span> statement and passing it the <span class="code">categoryList</span> Variable.
    	</li>
    	<li>
    		Our final function should look similar to this:
    
    public string function getCategoryIDs(){
    	var categoryList = '';
    	if ( hasCategories() ) {
    		for ( var categoryPost in getCategories() ) {
    			categoryList = listAppend( categoryList, categoryPost.blogCategory.id);
    		}
    	}
    	return categoryList;
    }
    
    	</li>
    	<li>
    		Open up the <span class="code">/www/admin/content/blog/listblogposts.cfm</span> page in your browser and append the <span class="code">?reload=1</span> value to the URL.
    	</li>
    	<li>
    		Click on the blog post and notice that the category is now checked.
    	</li>
    	<li>
    		If you were to click 'save' again, your blog post would end up with duplicate categories associated to it. If you were to uncheck a category and click 'save' teh category woudl not be removed from the blog post.This is because we have added logic to add categories, but we have not check if they are already associated or if they need removing. The easiest way to solve this is to remove all categories from the blog post when editing, then re-add the new categories. To do this, open up the <span class="code">/www/admin/content/blog/editBlogPost.cfm</span> file in your code editor.
    	</li>
    	<li>
    		Find the 'Edit Entity' comment tag and go to the last <span class="code">&lt;cfset></span> tag. After the <span class="code">&lt;cfset></span> tag, create a <span class="code">&lt;cfloop></span> tag with the following attributes:
    		<ul>
    			<li>
    				<strong>array</strong>: #blogPost.getCategories()#
    			</li>
    			<li>
    				<strong>index</strong>: category
    			</li>
    		</ul>
    	</li>
    	<li>
    		Inside the <span class="code">&lt;cfloop></span>, create a <span class="code">&lt;cfset></span> tag that calls the <span class="code">entityDelete</span> function and pass it in the variable <span class="code">category</span>. Your final code should look similar to this:
    
    <cfloop array="#blogPost.getCategories()#" index="category">
    	<cfset entityDelete(category) />
    </cfloop>
    
    	</li>
    	<li>
    		Go back to the <span class="code">/www/admin/content/blog/listblogposts.cfm</span>, click on a blog post, and save the blog to confirm you have no errors.
    	</li>
    </ol>
    

    Homework

    Create a function similar to the getCategoryIDs function. Instead of returning ID's, create a function that returns a list of the category names. Replace the category output, which is currently 'ColdFusion', in /www/blog.cfm with this new function call.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment