Search code examples
phparraysassociative-arrayfpdf

How to add FPDF totals to the last row of tables?


I have a set of tables categorized by their source e.g: "Client", "Stock", "Floorstock". They look like this:

List of Floor Stock orders

Each contain lists of prices, which need to be added up and totaled on the last row of the tables.

I'm having problems linking a "totals" array to the "tables" array - specifically displaying each total at the end of each table

So far, the totals of each table are generated in another function, where sourceTotals is an instance array:

public function setSourceTotalsArray($data)
{
    $this->sourceTotals = $data["source_totals"];
    return $this->sourceTotals;
}

This returns an array that looks like this:

array(4) { ["Floorstock"]=> int(0) ["Stock"]=> int(0) ["Client"]=> float(32.18)  } 

Here's where I define my $pdf object:

if($_SERVER["REQUEST_METHOD"] == "POST"){
$data = json_decode($_POST["printData"],true);
$pdf = new PDF();
// Column headings
$month = $pdf->getMonth($data['month']);
$year = $data['year'];
$pdf->SetFont('Arial','',10);
$pdf->AddPage();
$pdf>title(array('month'=>$month,'year'=>$year,'showroom'=>ucfirst($data['showroom_name'])));
$pdf->tableBody($data);

if(!empty($data["order_detail"])){
    $customerOrders = array();
    $stockOrders = array();
    $floorstockOrders = array();
    $otherOrders = array();

    foreach($data["order_detail"] as $o){
        switch($o["orderSource"]){
            case 'Client':
                $customerOrders[] = $o;
                break;
            case 'Stock':
                $stockOrders[] = $o;
                break;
            case 'Floorstock':
                $floorstockOrders[] = $o;
                break;

            default:
                $otherOrders[] = $o;
                break;
        }
    }

    if (!empty($customerOrders)) {
        $pdf->orderDetail($customerOrders, $data['currency'], 'Client');
    }

    if (!empty($stockOrders)) {
        $pdf->orderDetail($stockOrders, $data['currency'], 'Stock');
    }

    if (!empty($floorstockOrders)) {
        $pdf->orderDetail($floorstockOrders, $data['currency'], 'Floor Stock');
    }

    if (!empty($otherOrders)) {
        $pdf->orderDetail($otherOrders, $data['currency'], 'Client');
    }
}
$pdf->Output();

The orderDetail function is what structures the table within the $pdf object so that the table has cells that correspond to the correct column name:

function orderDetail($data,$currencyShortCode, $type){
    $this->orderType = $type;
    list($currencySymbol, $w_symbol, $cellHight) = $this->getOrderDetailHeader($currencyShortCode, $type);

    foreach ($data as $d){
        $commaValue = $this->addComma((float)$d['value']);
        $this->Cell(15,$cellHight,$d['order_no'],'LTB',0,'L');
        $this->Cell(20,$cellHight,substr($d['customer'],0,13),'TB',0,'L');
        $this->Cell(20,$cellHight,substr($d['company'],0,13),'TB',0,'L');
        $this->Cell(20,$cellHight,substr($d['ref'],0,13),'TB',0,'L');           
        $this->Cell(2,$cellHight,'','TB',0,'R');
        $this->Cell($w_symbol,$cellHight,$currencySymbol,'TB',0,'R');
        $this->Cell(16-$w_symbol,$cellHight,$commaValue,'TB',0,'R');
        $this->Cell(2,$cellHight,'','TB',0,'R');
        $this->Cell(10,$cellHight,$d['cat'],'TB',0,'L');
        $this->Cell(84,$cellHight,$d['description'],'RTB',0,'L');
        $this->Ln($cellHight);
    }
    //BOTTOM TOTAL
    $this->Cell(13,$cellHight,'TOTAL','LRTB',0,'L');
    $this->Cell(22,$cellHight,'','TB',0,'L');
    $this->Cell(20,$cellHight,'','TB',0,'L');
    $this->Cell(20,$cellHight,'','TB',0,'L');
    $this->Cell(4,$cellHight,$currencySymbol,'TB',0,'R');
    $this->Cell(14,$cellHight,$this->setSourceTotalsArray($data),'TB',0,'R'); //HERE
    $this->Cell(2,$cellHight,'','TB',0,'R');
    $this->Cell(10,$cellHight,'','TB',0,'L');
    $this->Cell(84,$cellHight,'','RTB',0,'L');
}

I'm just not sure how to pass setSourceTotalsArray into orderDetail, as my current attempt only returns null.


Solution

  • Your setSourceTotalsArray method doesn't really do anything, so if it returns null that means $data does not have a source_totals node. (Suggestion/sidenote: set error reporting to E_ALL so PHP will warn you about this; then for live environments turn display_errors off and enable log_errors so you'll see the errors in the log but your visitors won't see them on the screen.) The reason source_totals does not exist in $data is that the $datavariable insideorderDetailis only a subset of$data` in the full script.

    What I would do is add a $total argument to orderDetail. You the get something like this:

    function orderDetail($data,$currencyShortCode, $type, $total) {
        ...
        $this->Cell(14,$cellHight, $total,'TB',0,'R'); //HERE
        ...
    }
    

    And

    if (!empty($customerOrders)) {
        $pdf->orderDetail($customerOrders, $data['currency'], 'Client', $data['source_totals']['Client']);
    }
    // Also add the 4th argument for stock orders, floor orders and others.