Thursday, September 24, 2009

The cowering developer.

I wanted to talk a little bit about ownership and the frustrations I have with developers who don't own up their work. We all do it, just in varying degrees.

Have you ever noticed that some developers never own up to there work? A developer added some logic that made if confusing for you to follow, but they won't own up to their work. Trying to get anything out of them is like talking to a wall. I wonder what they're afraid of. I've put up with this for too long and need to talk about it.

Some developers feel it's "ok" to NOT take ownership or responsibility of their work. I think they are afraid of confrontation. If I want to know who did something, I am not looking to target someone and humiliate them. I am trying to solve an issue with which I am having trouble following their trail. I feel that the developer thinks that if they speak up that they will have to fix something or possibly "do more work". Yes, there are some immature developer that do make you fix it and will call you out in front to make themselves feel smarter, but I feel that most are just trying to solve an issue for which they need an assist with.

These "cowering" developers create more frustration, waste time and resources, and push the work off on other developers. I am sick of watching irresponsible developers go home to their friends and family while other developers clean up the messes. I am sure there is some angry significant others out there whom have a few words to say. I am sick of having long arguments in the same area of the developer who wrote the piece but they are just sitting there and listening and don't have the courage to stand up and assist.

Yes I know there are cases where we had to throw some not so good code in because of some crazy business logic, but it doesn't mean you are stuck with that piece forever. Others will come behind, follow your trail, and try to tweak/fix your piece. They may need help or point them in the right direction. If you choose to "cower" in the corner, it will be noticed and remembered. Swallow some pride and own up to the code.

Sunday, September 20, 2009

PHP and checkboxes with the same name

If you have worked with ColdFusion before you know that if have checkboxes in the form that have the same name they come into the form scope as a comma separated list. I tried to pull the same trick using PHP but only go the last checkbox's value. Confused I did a little a research and found out that if you put [] behind your name PHP interprets it as an array but keeps everything to the left of the [] as your name when comeing in through the $_REQUEST scope. See below.

<form name="the_form" method="post">

<input type="checkbox" name="boarder" value="Joe" >
<input type="checkbox" name="boarder" value="Jamie" >
<input type="checkbox" name="boarder" value="Jake" >

</form>

In ColdFusion when you submit this form you would get an variable in the form scope
called "boarder" with the values "Joe,Jamie,Jake" in a comma seperated list. In PHP you would get "Jake". To solve this I added [] to the checkbox name.

<form name="the_form" method="post">

<input type="checkbox" name="boarder[]" value="Joe" >
<input type="checkbox" name="boarder[]" value="Jamie" >
<input type="checkbox" name="boarder[]" value="Jake" >

</form>

Now in PHP you would get an variable in the $_REQUEST scope called "boarder" which is type array with first element "Joe, the second element "Jamie", and the third element "Jake". Notice the variable name is still "boarder" even though we specified "boarder[]".

I am not choosing sides on PHP or ColdFusion they are both cool, but I found it interesting that you can tell PHP what type this var is through the html form.

I found my answer at:
http://www.computing.net/answers/webdevel/php-amp-checkboxes/1122.html#postfp

Monday, September 7, 2009

Adding a node to an existing xml object

So I struggled with an interesting task the other day, that should have been easy. I had an xml object with which I was to add additional node too. Sounds simple right. The part I struggled with was the ColdFusion function "xmlElemNew()". I kept wanting to put in that third optional argument. Enough blabbing, here's how I did it.

Here is my xml file or xml object.


<boarders>
<boarder>
<name>Joe</name>
<board>Forum</board>
<gender>M</gender>
</boarder>
</boarders>


I want to add another boarder.

Here I am reading from a file but the same thing works for an xml object.


<cfset xml = xmlParse("boarders.xml")/>


I create my new boarder node, using the variable xml as my "xml document".

<cfset boarder = XmlElemNew(xml,"boarder")/>


Next I create some extra nodes "name,gender, and board" and append it to the boarder node using arrayAppend(). Each time I make the "extra nodes" I set the value of the node by using XmlText, which is an attribute of xml object in ColdFusion. Finally we add the node the children of the boarder node created earlier.

<!---name--->
<cfset name = XmlElemNew(xml,"name")/>
<cfset name.XmlText = "Jamie"/>
<cfset arrayAppend(boarder.XmlChildren,name)/>

<!---gender--->
<cfset gender = xmlElemNew(xml,"gender")/>
<cfset gender.XmlText = "F"/>
<cfset arrayAppend(boarder.XmlChildren,gender)/>

<!---board--->
<cfset board = xmlElemNew(xml,"board")/>
<cfset board.XmlText = "Nitro"/>
<cfset arrayAppend(boarder.XmlChildren,board)/>

Once we are ready to add the node the xml object we just arrayAppend() just like we did with the above nodes "name,gender,and board".

<cfset arrayAppend(xml.boarders.XmlChildren,boarder)>

<cfdump var="#xml#">

<cfabort/>



That's it.

To recap quick:
1. Create the node using XmlElemNew().
2. Set the node value using XmlText().(optional)
3. Append the node to the parent node using arrayAppend().

Took me forever to figure it out. Sad I know.

Wednesday, September 2, 2009

PDF's 101

I wanted to share my first experience with pdf's and how simple ColdFusion makes working with. Previously, when I had to do something with a PDF it was changing some styles on a .cfm that's content was wrapped in cfdocument tags, so I didn't really learn much. I got put on a project that had us generate pdfs and learned a lot from the experience. When I first started working on the project I was nervous because I didn't know XML or XSLT, but quickly realized they are not hard at all. Here is a small example of my process for creating a pdf. My goal was no files, which means I save the pdf in the database, but in this example I will show where you can either create a file or save it to the database.

First we have some data that we want to display on a PDF. I like snowboarding so I made an array of structs with data regarding each boarder. Mostly we would have a whole bunch of queries who's data we would to display but I just want to keep it simple.

<cfset boarders = arrayNew(1)/>

<cfset boarder = structNew()/>
<cfset boarder.id = 1/>
<cfset boarder.name = "Joe"/>
<cfset boarder.board = "Forum"/>
<cfset boarder.gender = "M"/>
<cfset arrayAppend(boarders,boarder)/>

<cfset boarder = structNew()/>
<cfset boarder.id = 2/>
<cfset boarder.name = "Ben"/>
<cfset boarder.board = "Burton"/>
<cfset boarder.gender = "M"/>
<cfset arrayAppend(boarders,boarder)/>

<cfset boarder = structNew()/>
<cfset boarder.id = 3/>
<cfset boarder.name = "Jake"/>
<cfset boarder.board = "Santa Cruz"/>
<cfset boarder.gender = "M"/>
<cfset arrayAppend(boarders,boarder)/>

<cfset boarder = structNew()/>
<cfset boarder.id = 4/>
<cfset boarder.name = "Jamie"/>
<cfset boarder.board = "Nitro"/>
<cfset boarder.gender = "F"/>
<cfset arrayAppend(boarders,boarder)/>

<!---dump the data--->
<cfdump var="#boarders#" label="boarders"/>

After we have our data we need make some xml. If you haven't work with xml, think of it like html, but you can make your own tag names. Here I create a node called "boarder" which I store properties about the boarder like name, board, and gender. The xml will act as our data when working with the pdf. Later the xslt will be our styles for the pdf.

<cfset xml = arrayNew(1)/>

<cfloop from="1" to="#arrayLen(boarders)#" index="i">

<cfsavecontent variable="boarder">
<cfoutput>

<boarder>
<id>#boarders[i].id#</id>
<name>#boarders[i].name#</name>
<board>#boarders[i].board#</board>
<gender>#boarders[i].gender#</gender>
</boarder>

</cfoutput>
</cfsavecontent>

<cfset arrayAppend(xml,boarder)/>

</cfloop>

<!---dump the xml--->
<cfloop from="1" to="#arrayLen(xml)#" index="i">
<cfdump var="#xmlParse(xml[i])#" label="#i#">
</cfloop>

After we have the data the next piece is to create some xslt. Remember xslt is the styles of the xml. If you haven't worked with xslt, the basic idea is you loop through your xml nodes "the custom tags you made" and output the data. You loop through a node by doing <xsl:for-each select="boarder">. If you want the value of node you do this <xsl:value-of select="name"/>. This should get you by, you will have to search W3schools for the rest.

<cfsavecontent variable="xslt">
<cfoutput>

<xsl:stylesheet version="1.0"
xmlns:xsl="http://www.w3.org/1999/XSL/Transform">

<xsl:template match="/">
<html>
<body>
<xsl:for-each select="boarder">

<table border="1">

<tr>
<td>Name:</td>
<td><xsl:value-of select="name"/></td>
</tr>

<tr>
<td>Gender:</td>
<td><xsl:value-of select="gender"/></td>
</tr>

<tr>
<td>Board:</td>
<td><xsl:value-of select="board"/></td>
</tr>

</table>

</xsl:for-each>
</body>
</html>
</xsl:template>

</xsl:stylesheet>

</cfoutput>
</cfsavecontent>

<---dump the xslt--->
<cfdump var="#xslt#">


The next piece is where we actually merge the xml and xslt together to create html. Once we have the html we can run it through cfdocument tags and get it in pdf format.

I start an array to hold the info regarding each document.

<cfset documents = arrayNew(1)/>

<cfloop from="1" to="#arrayLen(xml)#" index="i">

<cfset document = structNew()/>


I get the xml which we create earlier.

<cfset document.xml = xml[i]/>

I get the xslt which we create earlier.

<cfset document.xslt = xslt/>

I merge the xml and xslt together using xmlTransform(), a built in ColdFusion function and it will return my html.

<cfset document.html = xmlTransform(xml[i],document.xslt)/>

I wrap my html in cfdocument tags with a format of pdf. This will return me a binary object of the pdf. Earlier I mentioned about creating a file or saving it to the database...this is that point.

<cfdocument name="document.binary" format="pdf">
<cfoutput>#document.html#</cfoutput>
</cfdocument>

Since I didn't want to create any files I convert the binary object to base64 so I can save it in my MSSQL database. I can always pull the base64 from the databased and use toBinary() to convert it back to a binary object.

<cfset document.base64 = toBase64(document.binary)/>

<cfset arrayAppend(documents,document)/>

</cfloop>

<!---dump the documents array--->
<cfdump var="#documents#" label="documents">


At this point you can be done or if you want, since we have the all the pdfs in the array called documents, we can loop through them and merge them into one pdf so we can print 1 document instead of each document individually.

Pretty basic here. The only thing crazy is I loop through the documents again an apply them as source to the main pdf, named "final", I want to merge. The pointer is important because you can't directly throw the variable into the pdfparam source attribute...it requires a variable name, this took me along time to figure out.

<!--- merge documents --->
<cfpdf action="merge" name="final">

<cfloop from="1" to="#arrayLen(documents)#" index="i">
<cfset pointer = documents[i].binary/>

<cfpdfparam source="pointer"/>
</cfloop>

</cfpdf>

That's it, all the documents we created early are all merged into 1 single pdf, we can print them once. Now we just can the content tag to display the pdf to the browser.


<cfcontent type="application/pdf" variable="#toBinary(final)#" reset="no" />

Pretty harmless huh.