Yii 2 PDF Report
TCPDF Third Party Component
Controller

Setup report action in your controller. Eg: [app]/controllers/CustomerController

namespace app\controllers;
 
use Yii;
use app\models\Customer;
use app\models\CustomerSearch;
use yii\web\Response;
use yii\filters\AccessControl;
use yii\filters\VerbFilter;
//...
 
class CustomerController extends Controller
{
    public function behaviors()
    {
        return [
            'access' => [
                'class' => AccessControl::className(),
                'rules' => [
                    [
                        'actions' => ['index', 'create', 'view', 'update', 'delete', /*...*/ 'report'],
                        'allow' => true,
                        'roles' => ['@'],  // @ = Authenticated users
                    ],
                ],
            ],
            'verbs' => [
                'class' => VerbFilter::className(),
                'actions' => [
                    'delete' => ['post'],
                ],
            ],
        ];
    }
 
    /**
     * Prints report of all existing Items.
     * @param none
     * @return mixed
     */
    public function actionReport($title='')
    {
        date_default_timezone_set('America/New_York');
 
        $searchModel = new CustomerSearch();
        $dataProvider = $searchModel->search(Yii::$app->request->queryParams);
 
        $rows = $dataProvider->query->All();
 
        Yii::$app->response->format = yii\web\Response::FORMAT_RAW;  // Raw for PDF output
        return $this->render('report', [
            'data'  => $rows,
            'title' => $title,
        ]);
    }
}    
View

Create corresponding report view for the controller action. Eg: [app]/views/customer/report

<?php
use app\models\Customer;
 
//###---- User Modifiable Variables ----###
//#
$leftmargin     = 5;   // mm
$topmargin      = 15;  // mm
$rightmargin    = 5;   // mm
$bottommargin   = 15;  // mm
$intercolmargin = 3;   // mm
$interrowmargin = 1;   // mm
$colsperpage    = 3;   // label columns
$rowsperpage    = 15;  // lines per page
 
// Load Component Yii2 TCPDF 
\Yii::$app->get('tcpdf');
 
// create new PDF document
$pdf = new TCPDF('P' /* Page orientation (P=portrait, L=landscape) */, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false);
 
// set document information
$pdf->SetCreator(PDF_CREATOR);
$pdf->SetAuthor(Yii::$app->params['companyWebsite']);
$pdf->SetTitle('Customer Report');
$pdf->SetSubject('');
$pdf->SetKeywords('');
 
// set header and footer fonts
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
 
// set default header data
$pdf->SetHeaderData(
    K_BLANK_IMAGE, //PDF_HEADER_LOGO, 
    0, //PDF_HEADER_LOGO_WIDTH, 
    'Customer Report', 
    Yii::$app->params['companyName'], 
    array(0,64,255), 
    array(0,64,128)
);
$pdf->setFooterData(array(0,64,0), array(0,64,128));
 
// set default monospaced font
$pdf->SetDefaultMonospacedFont(PDF_FONT_MONOSPACED);
 
// set margins
//$pdf->SetMargins(PDF_MARGIN_LEFT, PDF_MARGIN_TOP, PDF_MARGIN_RIGHT);
$pdf->SetMargins($leftmargin, $topmargin, $rightmargin);
$pdf->SetHeaderMargin(PDF_MARGIN_HEADER + 2);
$pdf->SetFooterMargin(PDF_MARGIN_FOOTER);
 
// set auto page breaks
$pdf->SetAutoPageBreak(FALSE, PDF_MARGIN_BOTTOM);
 
// set image scale factor
$pdf->setImageScale(PDF_IMAGE_SCALE_RATIO);
 
// ---------------------------------------------------------
 
// set default font subsetting mode
$pdf->setFontSubsetting(true);
 
// Set font
// dejavusans is a UTF-8 Unicode font, if you only need to
// print standard ASCII chars, you can use core fonts like
// helvetica or times to reduce file size.
$defaultFont = 'dejavusans';
$pdf->SetFont($defaultFont, '', 10, '', true);
// set text shadow effect
//$pdf->setTextShadow(array('enabled'=>true, 'depth_w'=>0.2, 'depth_h'=>0.2, 'color'=>array(196,196,196), 'opacity'=>1, 'blend_mode'=>'Normal'));
 
// Add a page
// This method has several options, check the source code documentation for more information.
$pdf->AddPage();
 
// Set some content to print
$title = (!empty($title) ? $title : 'Current Customers');
$html = "<h1>{$title}</h1>";
$pdf->writeHTMLCell(0, 0, '', '', $html, 0, 1, 0, true, '', true); // Print text using writeHTMLCell()
 
$pdf->SetFont($defaultFont, '', 8);
 
$tbl = GenTableHeader();
 
$versions_used = array();
 
$lineCount = 1;
foreach ($data as $row) {
    // Add new page after configured rows-per-page
    if (($lineCount > 1) && (($lineCount % $rowsperpage) == 1)) { 
        // End page
        $tbl .= '</table>';
        $pdf->writeHTML($tbl, true /* newline */, false /* fill */, false /* reset height */, false /* add padding */, '' /* alignment */);
 
        // New page
        $tbl = GenTableHeader();
        $pdf->AddPage(); 
    }
 
    $tbl .= GenTableRow($lineCount, 
        $row['id'], 
        $row['account_number'],
        $row['contact'],
        $row['company_name'],
        $row['address1'],
        $row['address2'],
        $row['city'],
        $row['state_prov'],
        $row['postal_code'],
        $row['country'],
        $row['phone'],
        $row['phone_ext'],
        $row['email'],
        $row['website'],
        $row['ship_address_id'],
        $row['notes'],
        $row['status']
    );
 
    $lineCount++;
}
 
$tbl .= '</table>';
$pdf->writeHTML($tbl, true /* newline */, false /* fill */, false /* reset height */, false /* add padding */, '' /* alignment */);
 
$line = '<p>Report generated: '.date('Y-m-d H:i:s').'</p>';
$pdf->writeHTML($line, true /* newline */, false /* fill */, false /* reset height */, false /* add padding */, '' /* alignment */);
 
// ---------------------------------------------------------
 
// Close and output PDF document
// This method has several options, check the source code documentation for more information.
$pdf->Output('Shipping-Inventory-Report-' . date('Ymd-His') .'.pdf', 'I');
 
//============================================================+
// END OF FILE
//============================================================+
 
// Close Yii2
\Yii::$app->end();
 
function GenTableHeader()
{
    $tbl = '<table cellspacing="0" cellpadding="2" border="1">';
    $tbl .= '<tr>';
    $tbl .= '    <th width="03%" style="background-color:lightgray">#</th>';
    //$tbl .= '    <th width="05%" style="background-color:lightgray">ID</th>';
    $tbl .= '    <th width="07%" style="background-color:lightgray">Account</th>';
    $tbl .= '    <th width="08%" style="background-color:lightgray">Contact</th>';
    $tbl .= '    <th width="08%" style="background-color:lightgray">Company</th>';
    //$tbl .= '    <th width="08%" style="background-color:lightgray">Address1</th>';
    //$tbl .= '    <th width="05%" style="background-color:lightgray">Address2</th>';
    $tbl .= '    <th width="05%" style="background-color:lightgray">City</th>';
    $tbl .= '    <th width="05%" style="background-color:lightgray">State/Prov</th>';
    $tbl .= '    <th width="05%" style="background-color:lightgray">Postal Code</th>';
    $tbl .= '    <th width="10%" style="background-color:lightgray">Country</th>';
    $tbl .= '    <th width="10%" style="background-color:lightgray">Phone</th>';
    //$tbl .= '    <th width="05%" style="background-color:lightgray">Phone Ext</th>';
    $tbl .= '    <th width="20%" style="background-color:lightgray">Email</th>';
    //$tbl .= '    <th width="10%" style="background-color:lightgray">Website</th>';
    //$tbl .= '    <th width="10%" style="background-color:lightgray">Ship To</th>';
    $tbl .= '    <th width="20%" style="background-color:lightgray">Notes</th>';
    //$tbl .= '    <th width="10%" style="background-color:lightgray">Status</th>';
    $tbl .= '</tr>';
 
    return $tbl;
}
 
function GenTableRow($aRowNum, $id, 
        $account_number,
        $contact,
        $company_name,
        $address1,       
        $address2,
        $city,
        $state_prov,
        $postal_code,
        $country,
        $phone,
        $phone_ext,
        $email,
        $website,
        $ship_address_id,
        $notes,
        $status)
{
    $tbl = '<tr>';
    $tbl .= '<td width="03%">'.$aRowNum.'</td>';
    //$tbl .= '<td width="05%">'.$id.'</td>';
    $tbl .= '<td width="07%">'.$account_number.'</td>';
    $tbl .= '<td width="08%">'.$contact.'</td>';
    $tbl .= '<td width="08%">'.$company_name.'</td>';
    //$tbl .= '<td width="08%">'.$address1.'</td>';
    //$tbl .= '<td width="05%">'.$address2.'</td>';
    $tbl .= '<td width="05%">'.$city.'</td>';
    $tbl .= '<td width="05%">'.$state_prov.'</td>';
    $tbl .= '<td width="05%">'.$postal_code.'</td>';
    $tbl .= '<td width="10%">'.$country.'</td>';
    $tbl .= '<td width="10%">'.$phone.'</td>';
    $tbl .= '<td width="20%">'.$email.'</td>';
    //$tbl .= '<td width="05%">'.$website.'</td>';
    //$tbl .= '<td width="05%">'.$ship_address_id.'</td>';
    $tbl .= '<td width="20%">'.$notes.'</td>';
    //$tbl .= '<td width="10%">'.$status.'</td>';
    $tbl .= '</tr>';
 
    return $tbl;
} 
?>

Output Modes

The output can be saved in different ways:

// dest = 'I' to send file inline to browser (default).
$pdf->Output('Report-' . date('Ymd-His') .'.pdf', 'I' /* dest */); 

@param $dest (string) Destination where to send the document. It can take one of the following values:

Destination Description
I Send the file inline to the browser (default). The plug-in is used if available. The name given by name is used when one selects the “Save as” option on the link generating the PDF.
D Send to the browser and force a file download with the name given by name.
F Save to a local server file with the name given by name.
S Return the document as a string (name is ignored).
FI Equivalent to F + I option
FD Equivalent to F + D option
E Return the document as base64 mime multi-part email attachment (RFC 2045)

Example as email attachment:

// Close and output PDF document
$basepath = Yii::getAlias('@webroot')."/tmp/";  // [app]/web/tmp folder
$filename = 'Report-' . date('Ymd-His') .'.pdf';
if ($email_document) {
    $pdf->Output($filename, 'I');                     // only print preview file in browser
    //$pdf->Output("{$basepath}{$filename}", 'F');    // only download file to server
    //$pdf->Output("{$basepath}{$filename}", 'FI');   // download file to server & print preview file in browser
 
    // Attach as MIME multipart
    $attachment = $pdf->Output("{$filename}", 'S');    // document as a string
    Yii::$app->mailer->compose()
        ->attachContent($attachment, [
            'fileName'    => $filename,
            'contentType' => 'application/pdf'
        ])
        ->setFrom([Yii::$app->params['adminEmail'] => Yii::$app->params['companyName']])
        ->setTo($model->customer->email)
        ->setBcc([
            Yii::$app->params['adminEmail'] => Yii::$app->params['companyNameShort'] . ' Support', 
            Yii::$app->params['debugEmail'] => 'Debug Email'
        ])
        ->setSubject('Report-' . date('Y-m-d') . ")")
        ->setTextBody('Report included as attachment')
        ->send();
 
} else {
    //$pdf->Output($filename, 'D');    // only download file to client
    $pdf->Output($filename, 'I');      // only print preview file in browser
}