Monday 30 March 2009

Comparing using the DOM in PHP to my standard inline coding

Today I was just doing more website work, trying to make a page using DOMDocument in PHP. I had some xml/html like:
<div>
   <div>
      <div>
      </div>
   </div>
</div>

was trying to select the innermost nested div using an xpath query like $cats = $xpath->query("//fieldset[@id = 'categories']//div[last()]. But this would just return all the divs.

I was stumped for quite a while, though after a bit of googling I came across this page: XPath Expression syntax. What I needed to use was: $cats = $xpath->query("//fieldset[@id = 'categories']/descendant::div[last()].

Another way to do it would be to use xpath (or getElementsById if your id attributes are of the type id) to get the node with the id categories, and then use getElementsByTagName(), e.g. $cats = $xpath->query("//fieldset[@id = 'categories'];
$cats = $cats->item(0)->getElementsByTagName('div');
$cats = $cats->item($cats->length -1)


Generally the native DOM methods are much faster, as evidenced by the link I posted yesterday and Xpath vs getElementsByTagName.

In the evening as well as doing some website stuff I watched 'Pimp My Ride', which was totally funny. X-zibit always talks weirdly and waves his hands around all the time, and they put an electric fireplace in the back of the woman's car that they were 'pimping'. So weird and stupid that it's funny.

I also finished off getting the DOM version of my webpage to the same state as my non-DOM one (i.e. not anywhere near finished, but does have a bit of functionality). The page has an upload file input and a category select box. When you select a category and press the submit button the page will reload, but there will be an additional selectbox that lists the subcategories of the category you chose. If you chose to add a new category rather than an existing category, then the page will reload with the select boxes and a couple of text inputs for you to add a category with.

The reasons I decided to try out using the DOM in PHP are:
In a form normally you will need to have something like <p<php if($error['myEl']){echo ' class="error"';}?>><p> wrapped round each of your form inputs, so that if the form is submitted, and there is an error with the information that was submitted, the input that caused the error can be highlighted (e.g. the css class error might turn the text it is applied to red).
Using the DOM you can set the error as you do the error checking, though you must do the error checking after the element has been created in the DOM, e.g.

//Error with 'myEl'
$error['myEl'] = 'Error msg';
$xpath->query("//p[*[@id = 'myEl']]")->item(0))
$el->setAttribute('class', 'error');
This code assumes you wrap all your form elements in p tags.

Another thing is that normally in a form, in each input element you will need to write it in PHP like:
<input type="file" id="imgExif" name="imgExif"<?php if( isset($imgExif) ){ echo ' value="'.htmlentities($imgExif).'"'; }?>></input>
So that if there is an error with the form after it being submitted and you need to redisplay it, all the original information entered will still be there.
Using the DOM in PHP you could instead loop through all input elements to set their values, something like:

if($_POST)
{
   $inputs = $doc->getElementsByTagName('input');
   foreach($inputs as $input)
   {
      $input->setAttribute('value', htmlentities($_POST[$input->getAttribute('name')]));
   }
}


So basically using the DOM helps you eliminate a lot of inline if statements. Of course, when using inline if statements they do have the advantage that you can see where they are and they're easy to move around if you want and you can deal with each one indivdually.

The other advantage of using the DOM is that you can make your DOM manipulation code for users with javascript disabled in PHP, and write it very similarly as to how you write the javascript DOM manipulations.

So, while I thought that using the DOM should cut down on the code (and I used documentFragments with appendXML() quite a bit to avoid creating each element and setting attributes seperately (kind of like innerHTML/innerXML)), it actually turned out that my page using PHP's DOMDocument class was 205 lines long, whilst my normal PHP page was 176 lines.

I tested the pages by just selecting a category, selecting a sub category with no children, then clicking a button to make some inputs come up to input a new sub category. I then refreshed the page 20 times and made a note of how long the server took (just using a microtime(true) at the top and bottom of the page code). In the code I also looped through the POST values, and set an error for each one. The results were:

DOM 

Ifs 

0.0248391628265 

0.0386390686035 

0.0530791282654 

0.0402488708496 

0.0252490043640 

0.0212869644165 

0.0882880687714 

0.0478379726410 

0.0611557960510 

0.0531520843506 

0.0583279132843 

0.0559401512146 

0.0175540447235 

0.0525538921356 

0.0300509929657 

0.0476679801941 

0.0478260517120 

0.0563178062439 

0.0287899971008 

0.0217041969299 

0.0264458656311 

0.0223338603973 

0.0317590236664 

0.0215539932251 

0.0231108665466 

0.0558059215546 

0.0316941738129 

0.0375928878784 

0.0481081008911 

0.0272078514099 

0.0249459743500 

0.0101881027222 

0.0382578372955 

0.0334050655365 

0.0424761772156 

0.0217411518097 

0.0252931118011 

0.0393078327179 

0.0211040973663 

0.0389711856842 

0.0374177694321 

0.0371728420258 

       



So both methods are about the same speed (at least for this example) If I could get getElementById() to work, the DOM page should be quicker, though doubt it make any real difference. I think I will probably keep on doing inline coding without the DOM at the moment. If I do find I really would like to use the DOM, then I might try something like phpquery, which is meant to be jQuery, but for PHP.

The weather today was overcast all day except for about an hour around lunchtime when it was cloudy and sunny.

Food
Breakfast: Pink grapefruit marmalade toast sandwich; cup o' tea.
Lunch: Ham with mustard and crunchy salad sandwich; clementine; slice of iced lemon madeira layer cake; cup o' tea.
Afternoon snack: Bit of Ben's fudge flapjack he made at school; cup o' tea.
Dinner: Beef burger in a bun with tomato ketchup and grated cheese; fried mashed potato in a cob with tomato ketchup and grated cheese; baked beans; crunchy salad. Pudding was a piece of Ben's fudge flapjack he made at school; coffee.
Supper: Oreo; coffee.

No comments: