I'm using the mPDF class to output a pdf of data from a PHP file. I need to loop through a SQL Server query, save as new variables and write into the $html so it can be outputted to the pdf. I can't place it in the WriteHTML function because it does not recognize PHP code. I need the contents of the whole array so I can't just print one variable.
I have two files:
pdf-test.php:
This file gathers session variables from other php files that are included and reassigns them, so I can use them in the $html.
<?php
// Include files
require_once("form.php");
require_once("configuration.php");
session_start();
$html = '
<h3> Form A </h3>
<div>
<table>
<thead>
<tr>
<th colspan="3">1. Contact Information</th>
</tr>
</thead>
<tr>
<td> First Name: </td>
<td> Last Name: </td>
</tr>
<tr>
<td>'.$firstName.'</td>
<td>'.$lastName.'</td>
</tr>
.
.
.
</table>
';
echo $html;
pdf-make.php:
This file holds the code to actually convert the contents of pdf-test.php into a pdf.
<?php
// Direct to the mpdf file.
include('mpdf/mpdf.php');
// Collect all the content.
ob_start();
include "pdf-test.php";
$template = ob_get_contents();
ob_end_clean();
$mpdf=new mPDF();
$mpdf->WriteHTML($template);
// I: send the file inline to the browser.
$mpdf->Output('cust-form-a', 'I');
?>
This is my loop:
$tbl = "form_Customers";
$sql = "SELECT ROW_NUMBER() OVER(ORDER BY custFirt ASC)
AS RowNumber,
formID,
custFirt,
custLast,
displayRecord
FROM $tbl
WHERE formID = ? and displayRecord = ?";
$param = array($_SESSION["formid"], 'Y');
$stmt = sqlsrv_query($m_conn, $sql, $param);
$row = sqlsrv_fetch_array($stmt);
while ($row = sqlsrv_fetch_array($stmt)) {
$rowNum = $row['RowNumber'];
$firstN = $row['custFirt'];
$lastN = $row['custLast'];
}
When I try to include $rowNum, $firstN or $lastN in the $html such as
<td> '.$rowNum.'</td>
, it just shows up blank.
I'm not sure where the loop should go (which file) or how to include the $rowNum, $firstN and $lastN variables in the $html like the others.
I'm new to PHP (and relatively new to coding in general) and I don't have much experience working with it, but I've been able to make mPDF work for me in similar instances without the query included.
Any help would be greatly appreciated. Thank you so much!
I'm not sure how your loop interacts with the other two files, but this looks overly complex to me. I'd approach this in one .php file, something sort of like this:
<?php
//Include Files
include('mpdf/mpdf.php');
... //Your additional includes
//Define a row template string
$rowtemplate =<<<EOS
<tr>
<td>%%RowNumber%%</td>
<td>%%custFirt%%</td>
<td>%%custLast%%</td>
</tr>
EOS;
//Initialize the HTML for the document.
$html =<<<EOS
<h3> Form A </h3>
... //Your code
<td> Last Name: </td>
</tr>
EOS;
//Loop Code
$tbl = "form_Customers";
... //Your code
$row = sqlsrv_fetch_array($stmt);
while ($row = sqlsrv_fetch_array($stmt)) {
//Copy rowtemplate to a temporary variable
$out_tmp = $rowtemplate;
//Loop through your SQL variables and replace them when they appear in the template
foreach ($row as $key => $val) {
$out_tmp = str_ireplace('%%'.$key.'%%', $val, $out_tmp);
}
//Append the result to $html
$html .= $out_tmp;
}
// Close the open tags in $html
$html .= "</table></div>";
//Write the PDF
$mpdf=new mPDF();
$mpdf->WriteHTML($html);
$mpdf->Output('cust-form-a', 'I');
I'm using heredoc syntax for the strings, since I think this is the cleanest way to include a large string.
Also, I prefer to omit the closing ?> tag as it introduces a stupid source of errors.
Related
I want to format what is output by the following php script:
<?php
$stop = $_POST["stop_number"]; // stop_number is an text input value provided by user
$depart_url = "http://64.28.34.43/hiwire?.a=iNextBusResults&StopId=" . $stop;
$html = file_get_contents($depart_url);
$dom = new DOMDocument();
libxml_use_internal_errors(true);
$dom->loadHTML($html);
$xpath = new DOMXPath($dom);
$my_xpath_query = "//td[#valign='top']";
$result = $xpath->query($my_xpath_query);
foreach($result as $result_object)
{
echo $result_object->childNodes->item(0)->nodeValue,'<br>';
}
?>
Here is the output (at least in one instance, as the data changes over time).
18 - GOLD
OUTBOUND
8:17p
8:16p
8 - GREEN
OUTBOUND
8:46p
8:46p
8 - GREEN
OUTBOUND
18 - GOLD
OUTBOUND
5 - PLUM
OUTBOUND
EDIT:
I want the output info above to go in a table such as the one below. However instead of the text between tags, it would be variables, or items from the php script output.
<!DOCTYPE html>
<html>
<title>Departure Table</title>
<body>
<h4>Next Departures for Stop Number: __ </h4>
<table border="1px solid black">
<tr>
<th>Route</th>
<th>Direction</th>
<th>Scheduled</th>
<th>Estimated</th>
</tr>
<tr>
<td>18 - Gold</td>
<td>Outbound</td>
<td>8:17p</td>
<td>8:16p</td>
</tr>
<tr>
<td>8 - Green</td>
<td>Outbound</td>
<td>8:46p</td>
<td>8:46p</td>
</tr>
</table>
</body>
</html>
Try appending a \n tag after your echo statement:
echo $result_object->childNodes->item(0)->nodeValue."\n";
EDIT:
If you want to store your data in PHP variables, you could do something like this:
Store data in an array like variable (or any other data structure as per your needs) and iterate over the variable.
$store_data_in_array_variable = array();
foreach($result as $result_object)
{
$store_data_in_array_variable[] = $result_object->childNodes->item(0)->nodeValue;
}
//iterate over all stored values
foreach ($store_data_in_array_variable as $key => $value)
{
echo $key;
echo '<br>';
echo $value;
}
I keep trying different methods of extracting the data from the HTML table such as using xpath. The table(s) do not contain any classes so I am not sure how to use xpath without classes or Id. This data is being retrieved from an rss xml file. I am currently using DOM. After I extract the data, I will try to sort, the tables by Job Title
Here is my php code
$html='';
$xml= simplexml_load_file($url) or die("ERROR: Cannot connect to url\n check if report still exist in the Gradleaders system");
/*What we do here in this loop is retrieve all content inside the encoded content,
*which includes the CDATA information. This is where the HTML and styling is included.
*/
foreach($xml->channel->item as $cont){
$html=''.$cont->children('content',true)->encoded.'<br>'; //actual tag name is encoded
}
$htmlParser= new DOMDocument(); //to parse html using DOMDocument
libxml_use_internal_errors(true); // your HTML gives parser warnings, keep them internal
$htmlParser->loadHTML($html); //Loaded the html string we took from simple xml
$htmlParser->preserveWhiteSpace = false;
$tables= $htmlParser->getElementsByTagName('table');
$rows= $tables->item(0)->getElementsByTagName('tr');
foreach($rows as $row){
$cols = $row->getElementsByTagName('td');
echo $cols;
}
This is the HTML I am extracting info from
<table cellpadding='1' cellspacing='2'>
<tr>
<td><b>Job Title:</b></td>
<td>Job Example </td>
</tr>
<tr>
<td><b>Job ID:</b></td>
<td>23992</td>
</tr>
<tr>
<td><b>Job Description:</b></td>
<td>Just a job example </td>
</tr>
<tr>
<td><b>Job Category:</b></td>
<td>Work-study Position</td>
</tr>
<tr>
<td><b>Position Type:</b></td>
<td>Work-study</td>
</tr>
<tr>
<td><b>Applicant Type:</b></td>
<td>Work-study</td>
</tr>
<tr>
<td><b>Status:</b></td>
<td>Active</td>
</tr>
<tr>
<td colspan='2'><b><a href='https://www.myjobs.com/tuemp/job_view.aspx?token=I1iBwstbTs2pau+SjrYfWA%3d%3d'>Click to View More</a></b></td>
</tr>
</table>
You can use xpath to query('//td') and retrieve the td html using C14N(), something like:
$dom = new DOMDocument();
$dom->loadHtml($html);
$x = new DOMXpath($dom);
foreach($x->query('//td') as $td){
echo $td->C14N();
//if just need the text use:
//echo $td->textContent;
}
Output:
<td><b>Job Title:</b></td>
<td>Job Example </td>
<td><b>Job ID:</b></td>
...
C14N();
Returns canonicalized nodes as a string or FALSE on failure
Update:
Another question, how can I grab individual Table Data? For example,
just grab, Job ID
Use XPath contains, i.e.:
foreach($x->query('//td[contains(., "Job ID:")]') as $td){
echo $td->textContent;
}
Update V2:
How can I get the next Table Data after that (to actually get the Job
Id) ?
Use following-sibling::*[1], i.e:
echo $x->query('//td[contains(*, "Job ID:")]/following-sibling::*[1]')->item(0)->textContent;
//23992
$xpathParser = new DOMXPath($htmlParser);
$tableDataNodes = $xpathParser->evaluate("//table/tr/td")
for ($x=0;$x<$tableDataNodes.length;$x++) {
echo $tableDataNodes[$x];
}
This might have been already answered, yes, I used Google, and the search here stackoverflow, but the problem remains...
I'm using TCPDF library to generate PDF file, it works just fine, but I have the following situation, in order for my to generate a PDF ot just the HTML I need to put a few foreach and while's and IF's inside the HTML so that I can get the layout that the user is requesting...
so...
if(isset($_POST['submit'])) {
$ids = htmlentities($_POST['id'], ENT_NOQUOTE;
$con = conectionDB();
$query 'SELECT * FROM books WHERE id = "$ids"';
$doit = $con->query($query);
// at this point everything is file
// a few if's and we are done with the fetching "books" data
// a few other tuff that is required from the library nothing fancy...
// now here is the hard part
// next line will build my layout to display my PDF
$build_HTML = <<<EOD
<style>
.clasess {...}
.nother {...}
</style>
<table width="100%" border="1" cellpadding="0" bordercolor="#333333" >
<tr>
<td>Author</td>
<td>Books</td>
</tr>
<tr>
<td> Jong </td>
<td>
<table>
<tr>
<td>Title</td><td>Year</td>
</tr>
// Here is the problem I need to put a query to fetch the related data from
// another table
$books = conectionDB();
$bookQ = "SELECT * FROM titles WHERE name = '$author_name'";
$doitTitles = $books->query($bookQ);
if ($doitTitles->num_row > 1) {
while($dos = $doitTitles->fetch_assoc()){
// my td's, but this doest work...
}
}
</table>
</td>
</tr>
</table>
EOD;
$pdf->writeHTML($build_HTML, true, false, false, false, '');
} else {
// Go back...
}
As you can see I need that query right there, you may have notice that I have $doitTitles->num_row > 1 why? because if there is more than 1 tittle the layout would different if there is only 1 record...
We know that, that wont work, so the question is, is there another way to do that?
now, before the user go to the PDF, I display the information in plain html, which mean that the HTML that I use before the user go in to the PDF will be the same... so I was wondering, there another library that I can use to render the HTML in to PDF instead of building the PDF from inside the file... the user is able to see the result so those result just put 'em in a PDF...
Thank you!
I have the solution, so the thing is that I'm trying to output an html that is been build with dynamic content, if that was to be show as any other page, my_page.html there is no problem, but in PDF using <<
$raw_html = 'Tables';
// a few while and foreach's and queries
$raw_html .='Closed tables';
// Ready the HTML
$html = <<<EOD
$raw_html
EOD;
$pdf->writeHTML($html, true, false, false, false, '');
$pdf->Output('pdf_file_with_dynamic_html.pdf', 'I');
// the end.
by preparing the html before the output it gives me the data I need the way i need it...
that solved my problem.
I have a question on simplehtmldom.
how can I get a text of certain element that is a next_sibling of another element that contains a certain text?
for example:
I have html text as this:
<div>
<table>
<tr>
<td>prova</td>
<td>pippo</td>
</tr>
</table>
</div>
and I need to extract the text of second "td".Consider that I know that the value "prova" is a fixed value. I thought that i could use this code:
echo $html->find("td:contains('prova')",0)->next_sibling();
but "contains" doesn't exists in simplehtmldom.
How I can do that?
Thanks a lot
thanks for your answer but I need to extract text of td next to td that contains the text "prova".
As example I need to extract the value "pippo" with a similar code
echo $html->find("td:contains('prova')",0)->next_sibling()->innertext;
because I know the value of first column. Unfortunately the function contains doesn't exists in simplehtmldom.
The code
echo $html->find("td:innertext('prova')",0)->next_sibling();
doesn't is the right way.
Do you have other suggestion?
Thanks
try this code
<?php
include_once "simple_html_dom.php";
// the html code loaded (in this case in string mode)
$html = '<div>
<table>
<tr>
<td>prova</td>
<td>pippo</td>
</tr>
</table>
</div>';
$dom = str_get_html($html);
// the selector :contains isn't develop yet
$tds = $dom -> find("td");
foreach($tds as $td){
if ($td -> innertext == "prova"){
echo $td -> next_sibling() -> innertext;
}
}
?>
Hey everyone, I am using simplexml to pull data from an external xml source. I have got values even for limiting the number of results to display. I thought I could paginate with a simple query within the URL, something like "&page=2" but it is not possible as far as documentation shows.
I downloaded a pagination class intended to use within a MYSQL query an tried to used the vars output from the xml. But the output is loading the whole results of the xml and not the specified within the URL vars.
I think what I might do is to count the results first and then paginate, which is what I am trying to do. Do you see anything in this code that can be improved? Sorry If it isn´t clear, but maybe discussing with some coders fellas I can see a bit of light at the end of the tunnel and exaplin a bit better.
So here is the code:
<?
$url ="http://www.somedomain.com/cgi/xml/engine/get_data.php?ref=$ref&checkin=$checkin&checkout=$checkout&rval=$rval&pval=$pval&country=$country&city=$city&lg=$lg&orderby=$orderby&ordertype=$ordertype&maxrows=$maxrows";
// see I am already defining the max num of rows within the url. Which means that the proper way to sort this out is to start counting from the # aheads?
$all = new SimpleXMLElement($url, null, true);
$all->items_total = $hotels->id;
//
require_once 'paginator.class.php';
//calling the paginator class
foreach($all as $hotel) // loop through our hotels
{
$pages = new Paginator;
//creating a new paginator
$pages->mid_range = 7;
$pages->items_total = $hotel->id;
//extracting the var out from the XML
$rest = substr($hotel->description, 0, -150); // returns "abcde"
//echo <<<EOF
<table width="100%" border=0>
<tr>
<td colspan="2">{$hotel->name}<span class="stars" widht="{$hotel->rating}">{$hotel->rating}</span></h2></a><p><b>Direccion:</b> <i>{$hotel->address}</i> - {$hotel->province}</p>
<td colspan="2"><div align="center">PRECIO: {$hotel->currencyCode} {$hotel->minCostOfStay</a>
</div></a></a>
</td>
</tr>
<tr>
<td colspan="2"> $rest...<strong>ampliar información</strong></td>
<td valign="middle"><div align="center"><a href="{$hotel->rooms->room->bookUrl}"><img src="{$hotel->photoUrl}"></div></td>
</tr>
<tr>
<td colspan="2"><div align="center"><strong>VER TODO SOBRE ESTE </strong></div></td>
<td colspan="2"><div align="center">$text</a></div></td>
</a></div></td>
</tr>
//EOF;
echo '</table>';
$pages->paginate();
}
echo $pages->display_pages();
?>
You're clobbering your $all variable:
$all = new SimpleXMLElement($url, null, true); // used by the loop
$all = new Paginator; // reset within the loop