HTML テンプレートから PDF レポートを生成するために、php の dompdf ライブラリを使用しています。その html テンプレートには、セクションの目次があります。PDF を生成するときに、目次のページ番号を更新する必要があります。PHPのdompdfライブラリでこれを達成する方法を知っている人はいますか?
前もって感謝します。
私は Drupal でこれを達成しましたが、他の php オープンソースやフレームワークでも同様に機能すると思います。このコードをスクリプトタグ内に保持しました
$GLOBALS['entity_page'][] = $pdf->get_page_number();
ページ番号を格納するテンプレート。テンプレートの拡張子は tpl.php で、エクスポート用の他のコードを追加した後のモジュールに......
$canvas = $dompdf->get_canvas();
$font = Font_Metrics::get_font("helvetica", "normal");
$canvas->page_text(520, 805, "Page {PAGE_NUM}", $font, 9, array(0.4, 0.4, 0.4));
foreach ($GLOBALS['entity_page'] as $key => $val) {
$GLOBALS["entity_val"] = 0;
$GLOBALS["entity_y"] = 110;
$canvas->page_script('if($PAGE_NUM == 3 && $PAGE_NUM < 4){
$font = Font_Metrics::get_font("helvetica", "normal");
$x = 380;
$y = $GLOBALS["entity_y"];
$pdf->text($x, $y, "-------------------------".$GLOBALS["entity_page"][$GLOBALS["entity_val"]]."", $font, 12, array(0, 0, 0, 0.8));
$GLOBALS["entity_y"] = $GLOBALS["entity_y"] + 33;
$GLOBALS["entity_val"] = $GLOBALS["entity_val"] + 1;
}');
}
$pdf->text この部分は、y 軸の位置に一定の増分でページ番号を追加します。他のグローバル変数 entity_y および entity_val は、値を格納するために使用されます。
HTML(h1、h2、h3を使用)から目次を生成し、次のことを行いました。
$matches = null;
$smatches = null;
$had_headers = array();
preg_match_all('/<h[0-9].*?>.*?<\/h[0-9]>/i', $content, $matches);
if (!empty($matches[0]) && count($matches[0]) > 0)
foreach ($matches[0] as $headertag) {
preg_match('/>(.*?)<\/(h[0-9])>/i', $headertag, $smatches);
if (!empty($smatches[1]) && count($smatches[1]) > 0) {
$headerid = strip_tags($headertag);
$headerid = trim(strtolower(preg_replace('/[^a-z0-9]/i', '', $headerid)));
$smatches[2] = strtolower($smatches[2]);
$header_depth = intval(trim(str_ireplace('h', '', $smatches[2])));
while (in_array($headerid, $had_headers)) {
$headerid .= '1';
}
$had_headers[] = $headerid;
$content = str_replace($headertag, '<'. $smatches[2] . ' id="' . htmlentities($headerid) . '">' . $smatches[1] . '</' . $smatches[2] . '>', $content);
}
}
$matches = null;
$smatches = null;
$toc_html = '<ol id="toc">' . "\n";
$old_depth = 0;
$hadfirst = false;
preg_match_all('/<h[0-9].*?>.*?<\/h[0-9]>/i', $content, $matches);
if (!empty($matches[0]) && count($matches[0]) > 0)
for ($i=0; $i < count($matches[0]); $i++) {
$headertag = $matches[0][$i];
preg_match('/<h[0-9][^>]*?id="(.*?)".*?>(.*?)<\/(h[0-9])>/i', $headertag, $smatches);
if (!empty($smatches[1]) && count($smatches[1]) > 0) {
$headerid = trim($smatches[1]);
$header_depth = intval(trim(str_ireplace('h', '', $smatches[3]))) - 1;
// don't take heigher than h3 in TOC
if ($header_depth > 2)
continue;
if ($header_depth < $old_depth) {
$diff = $old_depth - $header_depth; //if going multiple levels up
$toc_html .= '</li>'.str_repeat('</ol></li>', $diff);
} elseif ($header_depth > $old_depth) {
$toc_html .= '<ol>';
} else {
$toc_html .= ($hadfirst) ? '</li>' : null;
}
$toc_html .= '<li><a href="#' . $headerid . '">' . htmlentities(trim(strip_tags($smatches[2]))) . '</a>';
$old_depth = $header_depth;
$hadfirst = true;
}
}
$toc_html .= str_repeat('</li></ol>', ($old_depth + 1));
あなたはすでにこれを解決したかもしれませんか?私は dompdf を使用したことはありませんが、Zend_Pdf で同様のことを行いました。目次用に空白のページを作成し、その後のすべてのページを作成し、page_number => title の配列を保持しました。最後に戻って、以前に保存した参照を使用して目次ページを更新しました...
ここでのヴィッキー・シュレスタの答えの拡張として、複数のページを展開する目次について私が持っているものがあります。
36 は、デザインに収まるアイテムの任意の数です。
foreach ($GLOBALS['entity_page'] as $key => $val) {
$GLOBALS["entity_y"] = 88;
$GLOBALS["entity_val"] = 0;
$GLOBALS["entity_per_page"] = 36;
if($val) {
$canvas->page_script('
if(isset($GLOBALS["entity_page"][$GLOBALS["entity_val"]])) {
if($PAGE_NUM == $GLOBALS["entity_page_number"]){
$x = 505;
$y = $GLOBALS["entity_y"];
$font = $fontMetrics->get_font("Open Sans", "Helvetica Neue", "Helvetica, Arial, sans-serif");
$pdf->text($x, $y, $GLOBALS["entity_page"][$GLOBALS["entity_val"]]."", $font, 7, array(0, 0, 0, 1));
$GLOBALS["entity_y"] = $GLOBALS["entity_y"] + 19;
$GLOBALS["entity_val"] = $GLOBALS["entity_val"] + 1;
if (($GLOBALS["entity_val"] + 1) % $GLOBALS["entity_per_page"] == 0 ) {
$GLOBALS["entity_page_number"] = $GLOBALS["entity_page_number"] + 1;
$GLOBALS["entity_y"] = 31;
}
}
}');
}
}
isset は重要です。何らかの理由で foreach がさらに 1 回ループし、最後に範囲外の例外がスローされるためです。