# PHP

> Install textcontrol/textcontrol-reportingcloud with Composer, merge sample_invoice.tx to PDF with mergeDocument and send a DOCX template with the request.

- **Product:** ReportingCloud
- **Section:** Documentation
- **Kind:** Topic
- **Path:** ReportingCloud > Getting Started > PHP
- **2979 words**
- **Web URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/php/
- **LLMs URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/php/llms.txt
- **LLMs-Full URL:** https://docs.textcontrol.com/reporting-cloud/getting-started/php/llms-full.txt

---

PHP applications use ReportingCloud through the PHP SDK `textcontrol/textcontrol-reportingcloud`, which Text Control publishes on Packagist and which wraps the Web API in the class `ReportingCloud`. With Composer and one script, you merge the demo template `sample_invoice.tx` of your template storage with invoice data and save the result as a PDF file from the command line. A second variant of the script sends a template file from your disk with the request instead of naming a stored one.

### Prerequisites

- **A ReportingCloud account and an API key.** A trial account is enough, and it has `sample_invoice.tx` in its template storage. [Creating an Account](https://docs.textcontrol.com/reporting-cloud/installation/account/llms-full.txt) shows how to sign up, and [API Keys](https://docs.textcontrol.com/reporting-cloud/installation/api-keys/llms-full.txt) how to create a key in the ReportingCloud portal.
- **PHP 8.3 or later** with the extensions dom, json and libxml. The current version of the SDK, 4.0.5, requires them.
- **[Composer](https://getcomposer.org/)**, the dependency manager for PHP, which installs the SDK and the libraries it uses.

### Check Your PHP Version

Open a terminal and print the version of the PHP command-line interpreter:

```bash
php --version
```

The first line of the output names the version. With PHP 8.3 or higher, Composer installs the current version of the SDK. On PHP 8.1 or 8.2, it reports that it cannot use version 4.0.5 and installs version 4.0.2 instead, whose `mergeDocument` method takes the same parameters; on an older PHP version, the installation fails.

### Create the Project

1. Create a directory for the project and change to it:

    ```bash
    mkdir my-application && cd my-application
    ```
2. Install the SDK with Composer:

    ```bash
    composer require textcontrol/textcontrol-reportingcloud
    ```

Composer creates *composer.json* with the requirement `^4.0` and downloads the SDK and its dependencies, among them the HTTP client Guzzle, into the *vendor* directory. It also writes *vendor/autoload.php*, the file that loads their classes.

### Set the API Key

The script reads the API key from the environment variable `REPORTINGCLOUD_API_KEY`, which keeps it out of your source code. Set it in the terminal in which you run the script:

```bash
export REPORTINGCLOUD_API_KEY="<API key>"
```

In PowerShell, the command is `$env:REPORTINGCLOUD_API_KEY = "<API key>"`. Replace `<API key>` with a key from the **Manage Account** page of the portal.

### Write the Script

Create a file *merge.php* in the project directory with the following code:

```php
<?php
declare(strict_types=1);

require_once __DIR__ . '/vendor/autoload.php';

use TextControl\ReportingCloud\ReportingCloud;

// Read the API key from the environment, never from source code
$apiKey = getenv('REPORTINGCLOUD_API_KEY');

if (!is_string($apiKey) || '' === $apiKey) {
    exit("Set the environment variable REPORTINGCLOUD_API_KEY.\n");
}

$reportingCloud = new ReportingCloud([
    'api_key' => $apiKey,
]);

// One record: the fields of the invoice and the line items of the item block
$mergeData = [
    [
        'yourcompany_companyname' => 'Text Control, LLC',
        'invoice_no'              => '778723',
        'billto_name'             => 'Joey Montana',
        'billto_companyname'      => 'Montana, LLC',
        'billto_street'           => '1 Washington Dr',
        'billto_zip'              => '27878',
        'billto_city'             => 'Charlotte',
        'payment_due'             => '20/1/2016',
        'item'                    => [
            [
                'qty'              => '1',
                'item_no'          => '1',
                'item_description' => 'Item description 1',
                'item_unitprice'   => '2663',
                'item_discount'    => '20',
                'item_total'       => '2130.40',
            ],
            [
                'qty'              => '1',
                'item_no'          => '2',
                'item_description' => 'Item description 2',
                'item_unitprice'   => '5543',
                'item_discount'    => '0',
                'item_total'       => '5543',
            ],
        ],
        'total_sub'               => '7673.4',
        'total_tax'               => '537.138',
        'total'                   => '8210.538',
    ],
];

// Merge the template of the template storage and receive one PDF per record
$documents = $reportingCloud->mergeDocument(
    $mergeData,
    ReportingCloud::FILE_FORMAT_PDF,
    'sample_invoice.tx'
);

file_put_contents(__DIR__ . '/invoice.pdf', $documents[0]);

echo "Written to invoice.pdf\n";
```

#### What the Code Does

- **`declare(strict_types=1)`** makes PHP enforce the parameter types of the SDK's methods, and *vendor/autoload.php* loads the classes that Composer installed.
- **`ReportingCloud`**, in the namespace `TextControl\ReportingCloud`, has a method for each endpoint of the Web API except `GET /v1/document/share`. The constructor takes an array of options: `api_key` is sent with every request in the header `Authorization: ReportingCloud-APIKey <key>`. Other options set the request timeout in seconds (`timeout`, 120 by default) and test mode (`test`), whose documents carry a "TEST MODE" watermark and which a Free account can't use. The options for user name and password still exist but are deprecated in favor of API keys.
- **`$mergeData`** is a list of *records*, the data of one document each. The keys of a record are the names of the *merge fields* in the template, placeholders such as `invoice_no`, and the list `item` fills the *merge block* `item`, which repeats a table row for each line item. The SDK sends the arrays as JSON. Merge fields without data are removed from the document, the default of the merge setting `removeEmptyFields`.
- **`mergeDocument`** sends the request `POST /v1/document/merge` and returns an array with one string of binary data per created document, already decoded from Base64. Its parameters are the data, the return format, the name of a stored template, the file name of a template on your disk, whether to append all records into one document and the merge settings.
- **`ReportingCloud::FILE_FORMAT_PDF`** is the return format `PDF`. The merge endpoint also returns `FILE_FORMAT_PDFA`, `FILE_FORMAT_RTF`, `FILE_FORMAT_DOC`, `FILE_FORMAT_DOCX`, `FILE_FORMAT_HTML`, `FILE_FORMAT_TX` and `FILE_FORMAT_TXT`; a trial account creates no PDF/A.
- **`file_put_contents`** writes the first and only document to *invoice.pdf*.

### Run the Script

Run the script in the terminal in which you set the API key:

```bash
php merge.php
```

The script prints `Written to invoice.pdf`. Open the file in a PDF viewer to see the merged invoice; a trial account adds the ReportingCloud logo to every document. Each run is a merge request and counts 1 against the monthly document quota of your plan.

### Send the Template With the Request

A template doesn't have to be in your storage. `mergeDocument` also takes the file name of a template on your disk, reads the file and sends it Base64-encoded in the `template` property of the request, which the Web API merges without storing it. The SDK accepts the extensions *.doc*, *.docx*, *.rtf* and *.tx*.

The SDK comes with a small Word template, *test\_template.docx*, whose merge fields are `name` and `age`. In *merge.php*, replace everything from the line `// One record: ...` to the end with:

```php
// A template with the merge fields name and age, shipped with the SDK
$templateFilename = __DIR__ . '/vendor/textcontrol/textcontrol-reportingcloud/resource/test_template.docx';

$mergeData = [
    [
        'name' => 'Jemima Puddle-Duck',
        'age'  => 7,
    ],
];

// Send the template with the data instead of naming a stored template
$documents = $reportingCloud->mergeDocument(
    $mergeData,
    ReportingCloud::FILE_FORMAT_PDF,
    '',
    $templateFilename
);

file_put_contents(__DIR__ . '/test_template_merged.pdf', $documents[0]);

echo "Written to test_template_merged.pdf\n";
```

The empty string in place of the template name says that no stored template is used. The parameter is a string: passing `null`, as samples for older versions of the SDK do, stops the script with a `TypeError`. Run `php merge.php` again and open *test\_template\_merged.pdf*.

### Troubleshooting

The SDK reports an error of the Web API as a `TextControl\ReportingCloud\Exception\RuntimeException` whose message names the request and the status code, followed by the response body, cut off after 120 characters:

```text
PHP Fatal error:  Uncaught TextControl\ReportingCloud\Exception\RuntimeException: Client error: `POST https://api.reporting.cloud/v1/document/merge?returnFormat=PDF&templateName=sample_invoice.tx` resulted in a `403 Forbidden` response:
```

- **403 Forbidden.** The API key is wrong or deleted, the document quota of the month is used up or more than two requests of your account arrived at the same time. Compare the key with the list on **Manage Account** in the portal and check the quota on the dashboard.
- **400 Bad Request.** The template is not in your template storage, or the request holds no data. Check the template name on the **My Templates** page of the portal.
- **TypeError for `$templateName`.** The script passes `null` as the third argument of `mergeDocument`. Pass an empty string `''` instead.
- **Composer cannot install the SDK.** Your PHP version is older than 8.1, the oldest version that SDK 4.0 supports. Install PHP 8.3 or later; [Check Your PHP Version](#check-your-php-version) shows which version of the SDK each PHP version gets.

### Next Steps

- [Web API](https://docs.textcontrol.com/reporting-cloud/getting-started/web-api/llms-full.txt): the request of this script with curl, with the complete invoice data.
- [Merge Data](https://docs.textcontrol.com/reporting-cloud/mail-merge/data-sources/llms-full.txt): how arrays and objects map to merge fields and merge blocks.
- [Merge Settings](https://docs.textcontrol.com/reporting-cloud/mail-merge/settings/llms-full.txt): the settings that the last parameter of `mergeDocument` passes.
- [PHP](https://docs.textcontrol.com/reporting-cloud/sdks/php/llms-full.txt): every method of the PHP SDK and the demo scripts in its *demo* directory.

---

## Nearby

- **Previous:** [.NET Framework](https://docs.textcontrol.com/reporting-cloud/getting-started/dotnet/dotnet-framework/llms-full.txt)
- **Next:** [Java](https://docs.textcontrol.com/reporting-cloud/getting-started/java/llms-full.txt)
