Php 在TCPDF中使用占位符

Php 在TCPDF中使用占位符,php,replace,tcpdf,placeholder,Php,Replace,Tcpdf,Placeholder,我对creditnote进行了一些复杂的计算,第一页是总金额的摘要。 我不想做的是遍历所有条款以计算摘要,然后再次遍历它们以呈现详细视图。 那么,是否可以定义自定义占位符,以便在添加详图视图后替换? 或者,您知道不需要运行两次计算就能获得所需结果的另一种方法吗 编辑: 以下是渲染局部视图的方式: foreach($this->_creditNote->provisioningClient->customers as $customer) {

我对creditnote进行了一些复杂的计算,第一页是总金额的摘要。 我不想做的是遍历所有条款以计算摘要,然后再次遍历它们以呈现详细视图。 那么,是否可以定义自定义占位符,以便在添加详图视图后替换? 或者,您知道不需要运行两次计算就能获得所需结果的另一种方法吗

编辑:

以下是渲染局部视图的方式:

        foreach($this->_creditNote->provisioningClient->customers as $customer)
        {
            $provisions = $customer->getProvisionsByBillingPeriodSum($this->_creditNote->billingPeriod);
            if((count($provisions) >= 3 && $this->y > 230) || $this->y > 250)
            {
                $this->AddPage();
                $this->SetFillColor(240);
                $this->SetDrawColor(0);
                $this->SetFont('Helvetica', 'B', 10);
                $this->Cell(140, 6, 'Die Provisionen im Einzelnen', 'TB', 0, 'L', 1);
                $this->Cell(30, 6, "Beträge", 'TB', 1, 'R', 1);
                $this->SetXY(25, $this->y-11.5);
                $this->SetTextColor(170,170,170);
                $this->SetFont('Helvetica', '', 7);
                $this->Cell(175, 6, 'Seite ' . $this->getAliasNumPage() . ' von ' . $this->getAliasNbPages(), '', 2, 'R');
                $this->SetY($this->y+6);
                $this->SetFont('Helvetica', '', 9);
                $this->SetTextColor(0,0,0);
            }
            if(count($provisions) > 0)
            {
                $customerData = array();
                $this->SetXY(20, $this->y+1);
                $this->SetFont('Helvetica', 'B', 10);
                $this->Cell(140, 0, $customer->contact->name . " (" . $customer->customerNumber . ")");
                //add customer
                $amount = 0;
                $rows = array();
                foreach($provisions as $provision)
                {
                    $text = $provision->description;
                    $description = "";
                    if($provision->period != "onetime")
                    {
                        if($provision->isPartial($this->_creditNote->billingPeriod))
                            $text .= ", anteilig";
                        $description = $provision->periodName . ", " . $provision->getRuntime($this->_creditNote->billingPeriod);
                    }
                    if($description == "")
                        $description = null;
                    $temp = array($text, $provision->isPartial($this->_creditNote->billingPeriod) ? round($provision->getPartialAmount($this->_creditNote->billingPeriod)/100, 2) : $provision->amount / 100, $description);
                    $amount += $temp[1];
                    $rows[] = $temp;
                }
                $this->Cell(30, 0, number_format($amount, 2, ",", ".") . " €", 0, 1, 'R');
                foreach($rows as $row)
                {
                    $this->SetXY(23, $this->y+1);
                    $this->SetFont('Helvetica', '', 8);
                    $this->Cell(137, 0, $row[0]);
                    $this->Cell(30, 0, number_format($row[1], 2, ",", ".") . " €", 0, 1, 'R');
                    if($row[2])
                    {
                        $this->SetXY(26, $this->y + 1);
                        $this->SetFont('Helvetica', 'I', 8);
                        $this->MultiCell(140, 0, $row[2], 0, 'L');
                    }
                }
            }
        }
提前感谢,,
Tobias

据我所知,您当前的代码如下所示:

// this will contain the computation for every orders
$orders_infos = array();

// you need $orders_infos to be already filled here, but it is done after
$total = 0;
foreach ($orders_infos as $info) {
  $total += $info['total'];
}
$html = "html for the overview page: ".$total; // $total is wrong !
$pdf->writeHTML($html);

// compute infos for every order and display
foreach ($orders as $k => $order) {
  $orders_infos[$k] = compute_order_infos();
  $html = "html for this order page ".$orders_infos[$k]['total'];
  $pdf->writeHTML($html);
}
您的问题是概览页面中的总数不正确,因为您是在事后进行计算的。更改它的简单方法是运行所有计算,然后生成结果PDF,但您说出于某种原因您不希望这样做

实现您想要的第二个最好的方法是进行一些欺骗,并跟踪要作为运行的命令列表,然后在最后运行它们,这样您可以保留当前的大部分代码组织,但之后仍会执行所有显示

$commands = array();

// this will contain the computation for every orders
$orders_infos = array();

// you need $orders_infos to be already filled here, but it is done after
$total = 0;
$commands[] = function($pdf, $orders_infos) {
  foreach ($orders_infos as $info) {
    $total += $info['total'];
  }
  $html = "html for the overview page: ".$total;
  $pdf->writeHTML($html);
};

// compute infos for every order and display
foreach ($orders as $k => $order) {
  $orders_infos[$k] = compute_order_infos();
  $commands[] = function($pdf, $orders_infos) use ($k) {
    $html = "html for this order page ".$orders_infos[$k]['total'];
    $pdf->writeHTML($html);
  };
}

// now run all the commands
foreach ($commands as $command) {
  $command($pdf, $orders_infos);
}
所有的PDF编写命令,包括概述,都将在每次计算完成后在最后执行

一个类似但更简单的示例,以便您更好地了解其工作原理:

$arr = array();
for ($i = 0; $i < 5; $i++) {
  $arr[$i] = $i;
}
$funcs = array();
foreach ($arr as $k => $v) {
  $funcs[] = function($arr) use($k) {
    echo $arr[$k]."\n";
  };
}

foreach ($funcs as $func) {
  echo "func: ";
  $func($arr);
}

不久前我不得不做一个类似的任务,因此我知道重复多次是不好的

我已经创建了一个类,它将首先执行所有计算。让我们称之为“回报”类。这将迭代上个月以来收到的所有订单。然后,它将为用户创建信息

  • 每份订单(删除税费等)
  • 总体视图(项目数量/总税额/等)
所以它可能看起来像这样

$payoffInfo=new Payoff($arrayWithOrderInfos);

// do creation of tcpdf object include header/footer/ ...
$pdf = new TCPDF();
$pdf->setPDFVersion('1.4');

$pdf->setPrintHeader(FALSE);
$pdf->setPrintFooter(TRUE);

// create first page and set 'overall' like this ...

$pdf->SetFont('Helvetica', '', 12);
$pdf->Cell(0, 0, "Overall amount ".$payoffInfo->getItemCount() , 0, 1, 'L');
$pdf->Ln();

$pdf->SetFont('Helvetica', '', 12);
$pdf->Cell(0, 0,"Overall amount ".$payoffInfo->getOverallAmount() , 0, 1, 'L');
$pdf->Ln();

// include more Overview Informations ...
// Iterate over all single orders ...

foreach($payoffInfo->getOrders() as $item){
    $html = "<p><ul>";
    $html .= "<li>Item ID: ".$item['order_id']."</li>";
    $html .= "<li>Item Price ".$item['price']."</li>";
    $html .= "<li>Item Clear Amount ".$item['price_without_tax']."</li>";
    $html .= "</ul></p>";
    $pdf->writeHTML($html, TRUE, FALSE, TRUE, FALSE, 'L');
}
// Mark Items as billed or sth. else so we don't include them again next month
$payoffInfo->setItemsToStatus("billed"); 

$pdf->Output($yourDesiredLocation, 'F');
$payoffInfo=新的支付($arrayWithOrderInfos);
//tcpdf对象的创建是否包括页眉/页脚/。。。
$pdf=新的TCPDF();
$pdf->setPDFVersion('1.4');
$pdf->setPrintHeader(假);
$pdf->setPrintFooter(TRUE);
//创建第一页并像这样设置“总体”。。。
$pdf->SetFont('Helvetica','',12);
$pdf->Cell(0,0,“总金额”。$payoffInfo->getItemCount(),0,1,'L');
$pdf->Ln();
$pdf->SetFont('Helvetica','',12);
$pdf->Cell(0,0,“总金额”。$payoffInfo->getOverallAmount(),0,1,'L');
$pdf->Ln();
//包括更多概述信息。。。
//迭代所有单个订单。。。
foreach($payoffInfo->getOrders()作为$item){
$html=“
    ”; $html.=“
  • 项目ID:”.$Item['order\u ID']。“
  • ”; $html.=“
  • 商品价格”。$Item['Price']。”
  • ; $html.=“
  • 项目净金额”。$Item['price\u without\u tax'”
  • ”; $html.=“

”; $pdf->writeHTML($html,TRUE,FALSE,TRUE,FALSE,'L'); } //将项目标记为账单或其他内容,以便我们下个月不再包括它们 $payoffInfo->setItemsToStatus(“账单”); $pdf->输出($yourDesiredLocation,'F');
为了减少时间并防止在服务器有高负载时生成pdf,我将其移动到“任务”(或其他任何内容)中。这个任务是每月一次(取决于你需要什么时间)的午夜工作。

此解决方案每月可处理约40万份订单,可能还可以处理更多订单

如果你想要时尚的pdf格式,可以完全按照你想要的样式设计,我今天会使用某种乳胶“界面”。因为对整个内容(包括页眉和页脚)进行样式设置要容易得多


希望这能帮助您反思您的任务。

谢谢您的回答。我将在我的问题中粘贴一些代码。每个月,我都必须生成一些creditnotes,以便为有时有大量广告客户的客户提供服务。所以我不想做的是计算总结,然后把它呈现出来,然后把所有的条款都详细地呈现出来。因此,我想我可以使用占位符,就像aliasnbpages等。我也有这样的想法,即运行它并将所有需要的数据保存在数组中,以便在最后呈现它们,但我认为可能会有一种更舒适的方法:最后,我按照你的方式来做。我计算了总数,并在循环浏览这些条款时存储了它们,以便在渲染时稍后访问。太多了!虽然很遗憾,但在tcpdf中无法使用自定义占位符:(
$payoffInfo=new Payoff($arrayWithOrderInfos);

// do creation of tcpdf object include header/footer/ ...
$pdf = new TCPDF();
$pdf->setPDFVersion('1.4');

$pdf->setPrintHeader(FALSE);
$pdf->setPrintFooter(TRUE);

// create first page and set 'overall' like this ...

$pdf->SetFont('Helvetica', '', 12);
$pdf->Cell(0, 0, "Overall amount ".$payoffInfo->getItemCount() , 0, 1, 'L');
$pdf->Ln();

$pdf->SetFont('Helvetica', '', 12);
$pdf->Cell(0, 0,"Overall amount ".$payoffInfo->getOverallAmount() , 0, 1, 'L');
$pdf->Ln();

// include more Overview Informations ...
// Iterate over all single orders ...

foreach($payoffInfo->getOrders() as $item){
    $html = "<p><ul>";
    $html .= "<li>Item ID: ".$item['order_id']."</li>";
    $html .= "<li>Item Price ".$item['price']."</li>";
    $html .= "<li>Item Clear Amount ".$item['price_without_tax']."</li>";
    $html .= "</ul></p>";
    $pdf->writeHTML($html, TRUE, FALSE, TRUE, FALSE, 'L');
}
// Mark Items as billed or sth. else so we don't include them again next month
$payoffInfo->setItemsToStatus("billed"); 

$pdf->Output($yourDesiredLocation, 'F');