No problem.

How the DOM work in PHP is you load the html or xml string or file into a $dom-object (instantiated by the class)

You make any transformations or changes to that html through the DOM methods

Then you save that back out as a string or a file

So here we're loading your entire template-html file into the main php page's dom-object, and after all is said and done, printing that out to the browser window or saving it as an (probably in your case) temp-html file ... haven't really gone into those options much yet though.

Let me know if this does not make sense and I will try to paraphrase it some ... ?

Ahh... Ok, let me see if I have this correct and I am understanding the flow here. If I am understanding you correctly, this dom object sits between the html template and the browser. All modifications are done to the dom and the ONLY thing I need to do in the html template is add my ids like so:
id="r1" etc..

Then any additional id that are needed need to be coded in the dom itself.
Is this a correct undersanding?

Sorry for the long posts guys.

Thanks Rob!

This is what I get from that:

Undefined index:  report1 
Undefined index:  report2 
Undefined index:  report3 
Invalid argument supplied for foreach()

Let me have a look at it and see what I can come up with. I do have a question about this line. I have never done this and because I am not a wazoo coder, I am probably not correct but I figured it wouldn't hurt to ask.

foreach($reportsarray[$reporttype] as $loopdata)

Is $reporttype supposed to be without a variable sign in front of it?

I'm sure that most people here would tell you that I am not the best teacher, but I will give it a try:

<?
$reporttypes = array("report1", "report2", "report3");
$reportswhere = "'" . implode("', '", $reporttypes) . "'";
$reportsarray = array();
$report1 = $db->Query("SELECT t3.report, t3.report_type 
						FROM location AS t1 
						Inner Join email AS t2 ON t1.customer_id = t2.customer_id AND t1.location_id = t2.location_id 
						Inner Join report AS t3 ON t1.customer_id = t3.customer_id AND t1.location_id = t3.location_id 
						WHERE 
						t3.stamp >= date_sub(now(), interval 1 day) 
						AND t1.customer_id = '$customer_id' 
						AND t1.location_id = '$location_id' 
						AND t3.report_type in(" . $reportswhere . ") 
						order by t3.report_type");
foreach($report1 as $rpt1)
{
	$reportsarray['report_type'][] = $rpt1['report'];
}

foreach($reporttypes as $reporttype)
{
?>
	<h2><? echo $reporttype; ?></h2>
	<?
	foreach($reportsarray[$reporttype] as $loopdata)
	{
		echo $loopdata . "<br />";
	}	
}


?>

This is the way this works(keep the $ on $reporttype because it is a variable, not originated from the database but from the initial array at the top):
1: define the innitial structure array($reporttypes)
2: define the where in cluase with that array($reportswhere) to be inserted into the query
3: $reportsarray is going to be your mulidimentional array
4: the query
5: loop through data and assign the report values to the $reportsarray array (notice that "report_type" matches the values in $reporttypes which is why we can use that as our structure.
6: loop through the multidimentional array. As I mentioned before, $reporttype matches the "report_type" column which is the same name that we assigned to the first dimension of the array. The second demention holds that data for that specific report type.

Member Avatar for langsor

Be right back on your last post ...

I think the Invalid argument supplied for foreach() you're getting might be coming from this section I was looking at.

foreach ( $report as $rpt ) {
  $reportsarray['report_type'][] = $rpt['report'];
}

foreach ( $reporttypes as $reporttype ) {
  print "<h2>$reporttype</h2>";
  foreach( $reportsarray[$reporttype] as $loopdata ) {
    print $loopdata . "<br />"; // insert into DOM here by $reporttype
  }	
}

I don't see how the data going in is being matched to the $reporttype to get it out again...
$reportsarray[] = $rpt;
foreach( $reportsarray[$reporttype] as $loopdata ) {
where $reporttype would be 'report1', 'report2', etc...
...see what I mean? Or maybe I'm missing something here--that's entirely possible.

...

I have to say, guys, I am not a true coder. When we are getting into dimensional arrays I am totally lost. I have also never used implode or explode. :D Not something to be proud of but I am still learning.

I understand to a certain extent but this is truly over my head. This, I cannot troubleshoot. I'm still with you all tho. :)

I don't see how the data going in is being matched to the $reporttype to get it out again...
$reportsarray[] = $rpt;
foreach( $reportsarray[$reporttype] as $loopdata ) {
where $reporttype would be 'report1', 'report2', etc...
...see what I mean? Or maybe I'm missing something here--that's entirely possible.

...

$reporttypes = array("report1", "report2", "report3");
$reportswhere = "'" . implode("', '", $reporttypes) . "'";
$query = "...AND t3.report_type in(" . $reportswhere . ") ..."

pulls from the database from the array $reporttypes so you should be able to extract it from the array with $reporttypes

foreach($reporttypes as $reporttype)
{
     print_r($reportsarray[$reporttype])
}

Does that make sense?

I have to say, guys, I am not a true coder. When we are getting into dimensional arrays I am totally lost. I have also never used implode or explode. :D Not something to be proud of but I am still learning.

I understand to a certain extent but this is truly over my head. This, I cannot troubleshoot. I'm still with you all tho. :)

You can go with the "ifs" instead, it would probably process faster anyway.

Member Avatar for langsor

Ahh... Ok, let me see if I have this correct and I am understanding the flow here. If I am understanding you correctly, this dom object sits between the html template and the browser. All modifications are done to the dom and the ONLY thing I need to do in the html template is add my ids like so:
id="r1" etc..

Then any additional id that are needed need to be coded in the dom itself.

We've got a three ring circus going here -- quite interesting

The DOM (document object model) is the <tag> structure of a document. It can be html or a DTD defined XML document too.

The DOM class parses the tags in the document and makes their properties available (nodeValue -- between the <tag></tag>s, attributes -- inside the <tag name="">, etc)

You can either hook onto existing parts of the document, or you can create your own and attach them to the existing document. So we can find the id's that are in your template, or we can make a new element <tag> and give it an id e.g. $tag->setAttribute('id','my_id'), and place that tag inside the template document.

I suggested expanding your template with <div> tags with specific ids since you were not creating the report headers dynamically and we needed to fill in the blanks between them.

We could have tracked down those blanks other ways, but this made the most sense to me.

Where the DOM sits ??? On the server I guess. So yes, between the html template and the browser.
1. {browser} => request {PHP with DOM methods} load <= {template file}
2. {PHP with DOM methods MODIFY DOM}
3a. {PHP with DOM methods} => print {browser}
or
3b. {PHP with DOM methods} => print {temp file} => redirect {browser to temp file}

I hope I'm making sense. :-)

I would though find a way to work with my query because if you are making 3(obviously complicated joins) queries for each loop, it will take a long time when the data starts to stack up.

LOL... It is a 3 ring circus but it is very cool. This is how stuff actually gets done. I enjoy being able to bounce stuff off of you guys. Two heads (in this case, 3) are better than one. :)

I have a question about the dom. Here is what I have:

$tags = $doc->getElementsByTagName('*');
foreach ( $tags as $i => $tag )
{
	print $tag->nodeName."<br>";
	if ( $tag->getAttribute('id') == 'location_name' )
	{
		$tag->nodeValue = 'My Heading';
	}

	if ( $tag->nodeName == 'p' )
	{
		$tag->setAttribute('class','location_name');
		$tags->item($i)->setAttribute('align','center');
	}
}

This will in fact replace my id tag, however, it is echoing every single element tag known to man to the screen as well. I know that comes from "$tags = $doc->getElementsByTagName('*');".

I have tried to replace the * with div and id but nothing. If I do that, nothing is imported. The only way it will import is with the astrisk. Can you help?

Langsor, I got it. I commented out the "print $tag->nodeName."<br>";"

I am trying to get a handle on this before you guys head off to bed. I would like to somehow finish this tonight sometime.

Thanks for sticking with me guys.

I would though find a way to work with my query because if you are making 3(obviously complicated joins) queries for each loop, it will take a long time when the data starts to stack up.

Absolutely Rob. I totally agree. I hate having to use 3 seperate queries. See.. I can write the sql but can't develop the loop to make it work. :)

Would you happen to have any other ideas about the loop? I could not get it to work even after your changes.

Langsor, I got it. I commented out the "print $tag->nodeName."<br>";"

I am trying to get a handle on this before you guys head off to bed. I would like to somehow finish this tonight sometime.

Thanks for sticking with me guys.

Before you go to bed can you post your code. Just curious how you ended up doing it.

Member Avatar for langsor

I have a question about the dom. Here is what I have:

$tags = $doc->getElementsByTagName('*');
foreach ( $tags as $i => $tag )
{
	print $tag->nodeName."<br>";
	if ( $tag->getAttribute('id') == 'location_name' )
	{
		$tag->nodeValue = 'My Heading';
	}

	if ( $tag->nodeName == 'p' )
	{
		$tag->setAttribute('class','location_name');
		$tags->item($i)->setAttribute('align','center');
	}
}

This will in fact replace my id tag, however, it is echoing every single element tag known to man to the screen as well. I know that comes from "$tags = $doc->getElementsByTagName('*');".

This is the line echoing every tag, you can get rid of that
print $tag->nodeName."<br>";

If your html has <div> tags and your div tags have id's
Then this should definitely work

$divs = $doc->getElementsByTagName('div');
foreach ( $divs as $div ) {
  if ( $div->getAttribute('id') == 'id_your_looking_for' ) {
    // do something with that div
   print $div->nodeValue; // for example
  }
}

...

Before you go to bed can you post your code. Just curious how you ended up doing it.

Hey Rob. I'm not going to bed... I was saying that before YOU AND LANGSTOR go to bed, I would like to have a handle on this. Trust me, I will be up all night on this.

I am able to use Langstor's solution for the template engine but its the darned loop. Unfortunately, my php skills are not that honed to write such a loop and for whatever reason, I can't get yours working.

BTW: I just responded to your last post on the prior page. I think we posted at the same time. Just wanted to let you know in case you missed it.

Langsor, I am trying that now. brb. Thanks!

Langsor, I got it. :) I decided to use TD tags and forgo the divs. I just added a few more if conditions and away I go.

Now..... the loop. Let me ask you a question. If I decided to email these reports dynamically, it shouldn't be an issue. Right? I mean, the dom should create the page and then use a mail function to sent it. Am I correct?

Member Avatar for langsor

Langsor, I got it. :) I decided to use TD tags and forgo the divs. I just added a few more if conditions and away I go.

Now..... the loop. Let me ask you a question. If I decided to email these reports dynamically, it shouldn't be an issue. Right? I mean, the dom should create the page and then use a mail function to sent it. Am I correct?

Hey, I'm glad you're getting it all to work ... quite a project for one night.

If you're sending html email then you're good to go, and I guess you would be using html email with the formatted data you're working with.

Just save the modified dom to a string and insert that string into your email body.
$string = $doc->saveHTML(); // outputs entire page from <html></html>

$body = $doc->getElementsByTagName('body')->item(0);
$string = $doc->saveXML($body); // outputs selected tag and its children, in this case <body></body>

Member Avatar for langsor

Did you also get the SQL stuff to work for you?

If so, I think Rob was interested in seeing what you ended up with, maybe you could attach the file to a post before you sign out for the night.

Cheers

Sure Langsor. I will post what I have. I am afraid that I am not able to troubleshoot Rob's loop. I will however post the solution I am going to use. I just have to get something online by tomorrow and if I need to use the three sql statements for the time being, that is fine with me. I can always come back for help on Rob's loop (and I surly will).

You guys are fantastic. Thanks for all of your help Langsor!

Member Avatar for langsor

Glad to help ... hope you get this out without hitch -- have a cup of coffee for me.

Good night

Thank you buddy. I absolutely will. Good night and look for me tomorrow. I will be back then. :)

Well, as promised, I am reporting back with the solution I have used.

I unfortunately could not use dom to template the reports because I could not get the loop to loop through all of the pages.

What I did was to use my loop and simply placed the html within it. This is an absolutely horrible solution and I can honestly say that I don't think I ever coded anything that looked so bad. It works, but even I wouldn't want to troubleshoot it if something went bad.

I will be back later this evening and maybe we can bounce some stuff off of one another again. Thanks a million guys.

Member Avatar for langsor

Just out of curiosity,

Did you ever try using my looping mechanism on page 1 post #8?

If not, give it a spin after you rest up some.

:-)

How secure/large is your database, can you share it, at least those three tables?

Just out of curiosity,

Did you ever try using my looping mechanism on page 1 post #8?

If not, give it a spin after you rest up some.

:-)

Hi Langsor,

Maybe that was the problem. No, I didn't use that method at all. What I did was attempt to loop the actual dom function itself; not the html. Do you mean that I should be looping the html itself? I'm not sure I understand how that will work. The dom calls template.html at runtime but when will the loop in the html fire? I'm sorry, I just don't understand.

Would you mind maybe explaining a bit more? Thanks!

How secure/large is your database, can you share it, at least those three tables?

Hi Rob, I don't mind at all posting the tables, however, I have encountered a new problem that I really need to focus on a bit more than the reports. It seem that the requirements have changed a bit since yesterday and new textboxes and selects need to be added. I have programmed what I could in OOP as best I could. The problem I am having at this point is that I need to now need to go back to my methods and redo them. I have html code inside these methods and I don't believe this is correct.

How good are you guys with OOP? I would like to do this correctly and I think I need some direction. This application should be able to easily scale and if I have started a bad foundation, I will forever be hating myself. :)

I think what I need to do at this point is go back and clean up my code so that when I need to add something else I am not dreading it. That is the whole purpose of OOP.

And.... We're back. :) Looks like ol Dani put the fire to the monkeys to send me the reverification email. I got it this morning if you can believe that. 14 hours later?? Wow. Great system they have

Member Avatar for langsor

Hi Langsor,

Maybe that was the problem. No, I didn't use that method at all. What I did was attempt to loop the actual dom function itself; not the html. Do you mean that I should be looping the html itself? I'm not sure I understand how that will work. The dom calls template.html at runtime but when will the loop in the html fire? I'm sorry, I just don't understand.

Would you mind maybe explaining a bit more? Thanks!

Excerpt post 8

<?php
// ... db connect stuff...

$report_nums = array( 'report1', 'report2', 'report3' );

$rpthdr = $db->Query("SELECT ... ");

foreach( $rpthdr as $hdr ) {
  $customer_id = $hdr['customer_id'];
  $location_id = $hdr['location_id'];
  echo $hdr['location_name']."<br>";
  echo $hdr['name']."<br>";
	
  foreach ( $report_num as $report ) {
    $results = $db->Query("SELECT ... AND t3.report_type='$report'");

     foreach ( $results as $rpt ) {
       // print $rpt['report']."<br>"; // HERE WE WORK THE DOM
      $td = $doc->createElement('td');
      $td->nodeValue = $rpt['report'];
      $rpt1->appendChild( $td );
    }
  }
}

All I'm doing here is
1. creating an array with the 3 report types in it $report_nums
2. foreach array entry running your $results query and filling in the report_type dynamically with the array value
3. and foreach $results-nested associative array produced ...
4. create, assign values, and append DOM elements to the DOM Document.

So we're looping the database results and filling in the html nodes with its data.

Hope this makes sense

I think this will work, or something close to it since I don't have my hands on your exact db environment

Member Avatar for langsor

I have html code inside these methods and I don't believe this is correct.

How good are you guys with OOP? I would like to do this correctly and I think I need some direction. This application should be able to easily scale and if I have started a bad foundation, I will forever be hating myself. :)

Are you using PHP 5? If not, I'm no good at OOP with PHP, otherwise I hold my own.

I agree, mixing html with your code or in your database is generally to be avoided (messy at best), but can be hard to avoid if you aren't using a good template engine that enforces separation (model-view-controller separation).

Your template and the dom methods are close to this, but still require advanced knowledge of the template structure to tie it all together.

Hi Langsor, I am using php5.

What I have so far are 3 files. I don't know what the heck is going on with the dom and don't truly understand how it ties together. Here is the loop that is working for me. This gets me the data that I need.
BTW: Once I get the template working, I will remove one of the foreach loops and use an array to iterate through the report types.

require_once("db.php");
$db = new Database('test');
$rpthdr = $db->Query("SELECT...");

$date = date("m/d/Y");

foreach($rpthdr as $hdr)
{
	$customer_id = $hdr['customer_id'];
	$location_id = $hdr['location_id'];

	$morning = $db->Query("SELECT... WHERE... t1.customer_id = '$customer_id' AND t1.location_id = '$location_id' AND t3.report_type = 'morning'");
	foreach($morning as $rpt2)
	{
		$td = $doc->createElement('td');
		$td->nodeValue = $rpt2['report'];
		$rpt1->appendChild( $td );
	}

	$evening = $db->Query("SELECT... WHERE... t1.customer_id = '$customer_id' AND t1.location_id = '$location_id' AND t3.report_type = 'evening'");
	foreach($evening as $rpt3)
	{
		$td = $doc->createElement('td');
		$td->nodeValue = $rpt3['report'];
		$rpt1->appendChild( $td );
	}
}

Here is my dom that is replacing my fields currently.

$doc = new DOMDocument('1.0');
$doc->loadHTMLFile( 'test.html' );

$tags = $doc->getElementsByTagName('*');
foreach ( $tags as $i => $tag )
{
	if ( $tag->getAttribute('id') == 'location' )
	{
		$tag->nodeValue = '1';
	}

	if ( $tag->getAttribute('id') == 'addr' )
	{
		$tag->nodeValue = '2';
	}

	if ( $tag->getAttribute('id') == 'city' )
	{
		$tag->nodeValue = '3';
	}

	if ( $tag->getAttribute('id') == 'state' )
	{
		$tag->nodeValue = '4';
	}

	if ( $tag->getAttribute('id') == 'margin' )
	{
		$tag->nodeValue = '5';
	}

	if ( $tag->getAttribute('id') == 'employee' )
	{
		$tag->nodeValue = '6';
	}
}

$divs = $doc->getElementsByTagName('div');
foreach ( $divs as $div )
{
	if ( $div->getAttribute('id') == 'location_name' )
	{
		$tag->nodeValue = 'Location Name...';
	}
}
print $doc->saveHTML();

The last file is of course, my template and is straight html with the coorasponding ids. Everything works great without the loop. Once the loop is introduced things stop working.

Also, one thing that I have noticed is that when the data is imported into the html template by the dom, there is a "<br>" that is appended to the database record and is also echoed in the template. Is there a way to get rid of the "<br>"?

Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.