Generating PDFs in Yii2 using the calcinai/xero-php Extension

For anyone looking how to pull an Invoice/Bill as a PDF, not as XML or JSON, from a Xero account via yii2 it is quite simple at the end of the day!

Here’s the gist of it:
 

/**
 * Action: Download Invoice PDF
 *
 * Retrieves an invoice from Xero using its GUID and streams the PDF
 * directly to the browser for inline viewing.
 *
 * Library:
 * calcinai/xero-php
 *
 * Route Example:
 * /controller/download-invoice?xeroInvoiceId={GUID}
 *
 * Expected Output:
 * application/pdf
 *
 * @param string $xeroInvoiceId Xero invoice unique identifier.
 * @return string PDF binary response.
 * @throws \yii\web\ServerErrorHttpException
 */
public function actionDownloadInvoice($xeroInvoiceId)
{
    $xero = null;
	
    // Get your $xero instance
    // *****
	
    if (isset($xero)) {
        try {
		
            $invoice = $xero->loadByGUID(
                Invoice::class,
                $xeroInvoiceId,
                ['Accept' => 'application/pdf']
            );
			
            $pdfContent = $invoice->getPDF();
			
            Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
            Yii::$app->response->headers
                ->set('Content-Type', 'application/pdf')
                ->set('Content-Disposition', 'inline; filename="invoice-' . $xeroInvoiceId. '.pdf"');
			
            return $pdfContent;

        } catch (\Exception $e) {
            throw new \yii\web\ServerErrorHttpException($e->getMessage());
        }
    }
}

or, an alternate more robust version might look like:

/**
 * Action: Download Invoice PDF
 *
 * Retrieves an invoice from Xero using its GUID and streams the PDF
 * directly to the browser for inline viewing.
 *
 * Library:
 * calcinai/xero-php
 *
 * Route Example:
 * /controller/download-invoice?xeroInvoiceId={GUID}
 *
 * Expected Output:
 * application/pdf
 *
 * @param string $xeroInvoiceId Xero invoice unique identifier.
 * @return string PDF binary response.
 * @throws \yii\web\ServerErrorHttpException
 */
public function actionDownloadInvoice(string $xeroInvoiceId): string
{
    $xero = null;
	
    // Get your $xero instance
    // *****

    if ($xero === null) {
        throw new \yii\web\ServerErrorHttpException('Xero client is not available.');
    }

    try {
        $invoice = $xero->loadByGUID(
            Invoice::class,
            $xeroInvoiceId,
            ['Accept' => 'application/pdf']
        );

        if ($invoice === null) {
            throw new \yii\web\NotFoundHttpException('Invoice not found.');
        }

        Yii::$app->response->format = \yii\web\Response::FORMAT_RAW;
        Yii::$app->response->headers
            ->set('Content-Type', 'application/pdf')
            ->set(
                'Content-Disposition',
                'inline; filename="invoice-' . $xeroInvoiceId . '.pdf"'
            );

        return $invoice->getPDF();

    } catch (\yii\web\HttpException $e) {
        throw $e;

    } catch (\Throwable $e) {
        Yii::error($e->getMessage(), __METHOD__);

        throw new \yii\web\ServerErrorHttpException(
            'Unable to download invoice.'
        );
    }
}

Taking it further, you can give the PDF output a custom filename by customizing the following portion of the code:

filename="invoice-' . $xeroInvoiceId . '.pdf"'

Instead of just using the raw $xeroInvoiceId, which isn’t meaningful for end users. Consider incorporating the invoice date, client’s name and invoice number for clarity, though the exact format depends on your specific business requirements.