WordPressでTCPDFを使用した出力3パターン

WordPressでTCPDFを使用した出力3パターン

TCPDFについての記事は2回目で前回はTCPDFとFPDIを使用してテンプレートファイルに出力する方法について紹介しました。

前回記事⇒【TCPDF+FPFI】PHPでpdf帳票を作成する方法【グラフも】

今回は出力部分にフォーカスした説明をしていきます。

タイトルにWordPressでとしていますが、WordPressでなくても十分使用できるのではないかと思います。

今回紹介する出力の形は以下です。

  • 非同期でダウンロード
  • 非同期で取得して別タブで表示
  • メールにpdf添付

TCPDFの出力一覧

まず、出力形を紹介する前にTCPDFの「Output」関数についておさらいしておきます。

$pdf->Output( $name, $option );

第一引数の「$name」にはpdfの名前を入れてあげます。

そして第二引数にはどのような形のアウトプットを望むのかアルファベットの大文字を当ててあげます。

使用できるのは以下です。

  • 「I」・・・表示
  • 「D」・・・ダウンロード
  • 「F」「FI」「FD」・・・ファイル作成 「FI」は表示も 「FD」はダウンロードも
  • 「E」・・・メール用文字列を返却
  • 「S」・・・文字列を返却

ってことは「I」や「D」、「E」を使えばできそうだとなるのですが、そういうわけにもいかなかいようなので今回記事にしてみた次第です。

ただ、私のやり方が悪かった可能性もあります。。。

非同期でダウンロード

最初はダウンロードする方法を紹介します。

上記の「D」で確かにダウンロードはできるのですが、非同期で処理する場合には不向きです。

上記の「D」はリンク先のphpで処理させるような場合に向いています。

PHP側

// wp_create_nonce( 'download_pdf' );
add_action( 'wp_ajax_nopriv_donwload_pdf', function () {
    check_ajax_referer( 'download_pdf', 'nonce' );

    $pdf = new TCPDF( PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false );
    // 処理
  header( 'Content-type: application/pdf' );
    echo $pdf->Output( 'test.pdf', 'S' );
    exit;
} );

ログインユーザーでないことを想定して「wp_ajax_nopriv」を使用しています。

あらかじめ「wp_create_nonce」によって作成されたnonceを「check_ajax_referrer」で確認しています。

第二引数を「nonce」としています。これはリクエストURLのパラメーターの「nonce」の値を使用しますという意味になります。

認証が終わったら、pdfを作成して出力します。

出力のオプションは文字列の「S」を指定します。

headerでcontent-typeを指定しておかないとスマホ利用時に生の文字列が表示されてしまったりするので注意が必要です。

JS側

window.addEventListener( 'DOMContentLoaded', () => {
    downloadPdf();
} );
// front['ajax'] ajaxurl
// front['nonce'] nonce
const downloadPdf = () => {
    const downloadButton = document.querySelector( '#download' );
    if ( ! downloadButton ) return false;

    const requestUrl = front['ajax'] + '?action=download_pdf&nonce=' + front['nonce'];

    const requestArgs = {
        method: 'POST',
    };

    fetch( requestUrl, requestArgs )
        .then( response => response.blob() )
        .then( blob => {
            const url = URL.createObjectURL( blob );
            const a = document.createElement( 'a' );
            document.body.appendChild(a);
            a.href = url;

            let filename = 'sample.pdf';
            a.download = filename;
            a.click();
            a.remove();
        } )
};

リクエストURLには「アクション名」「nonce」を付与してあげます。今回「ajaxurl」「nonce」はフロント側から「wp_localize_script」等で送られてきているものとしています。

fetchでphp側にアクセスして「pdf」の文字列状態のものを送ってもらいます。

送られてきたら「.blob()」によりBlobの形へ変換します。

次に「<a href=”” download=””>」の形を作成してます。hrefへのURLはBlobへアクセスするためのURLを「URL.createObjectURL」によって生成しています。

作成したaタグをbody末尾に追加し、クリックイベントを発火させるとダウンロードが開始されます。

ダウンロードし、不要になったaタグを最後に削除して終了です。

ポイント

$pdf->OutPutは「S」で文字列に、jsでダウンロード処理を行う。

非同期で取得して別タブで表示

別タブで表示するのは「I」オプションで出来ますが、ダウンロードと同様に非同期時にはうまく機能してくれません。

そこで、先の「非同期でダウンロード」の内容を少し変更して、別タブで開くにしたいと思います。

変更するのはJSの部分です。

php側は変更せずにそのままでOKです。

window.addEventListener( 'DOMContentLoaded', () => {
    downloadPdf();
} );
// front['ajax'] ajaxurl
// front['nonce'] nonce
const downloadPdf = () => {
    const downloadButton = document.querySelector( '#download' );
    if ( ! downloadButton ) return false;

    const requestUrl = front['ajax'] + '?action=download_pdf&nonce=' + front['nonce'];

    const requestArgs = {
        method: 'POST',
    };

    fetch( requestUrl, requestArgs )
        .then( response => response.blob() )
        .then( blob => {
            const url = URL.createObjectURL( blob );
            const a = document.createElement( 'a' );
            document.body.appendChild(a);
            a.href = url;
            a.target = '_blank'; ←ここ追記
            a.click();
            a.remove();
        } )
};

変更するのはダウンロード属性をしていた部分です。

ダウンロード属性を削除し、そこに「target=”_blank”」となるように設定しています。

こうすることでクリックとともにpdfファイルが別タブで開かれます。

メールにPDF添付

続いてメールに添付する方法を紹介します。

ダウンロードほどではないと思いますが、よく使われるのではないかと思います。

こちらはオプションの「E」を使用することで対応できそうですね。

しかし、メールについての知識が乏しいとこの「E」を選択するとやや大変かもしれません。

私はイマイチ理解していなく、使いこなせなかったです。

そのため、これから紹介する方法は少し切り口を変えた方法になります。

まずは、コードから見てみましょう。

$upload_dir = wp_upload_dir();
$file_name = 'test.pdf';
$file = '';
if( wp_mkdir_p( $upload_dir['path'] ) ) {
    $file_name = wp_unique_filename( $upload_dir['path'], $file_name );
    $file = $upload_dir['path']. '/'. $file_name;
} else {
    $file_name = wp_unique_filename( $upload_dir['basedir'], $file_name );
    $file = $upload_dir['basedir']. '/'. $file_name;
}

$pdf = new TCPDF( PDF_PAGE_ORIENTATION, PDF_UNIT, PDF_PAGE_FORMAT, true, 'UTF-8', false );
// 処理
$pdf->Output( $file, 'F' );

$to      = 'to@kumatech-lab.com';
$subject = 'TCPDF メール添付テスト';
$content = 'PDFが添付されてるよ';
$headers[] = 'From: WordPress&TCPDF <from@kumatech-lab.com>';
wp_mail( $to, $subject, $content, $headers, $file );
unlink( $file );

wp_upload_dir」を使用してアップロードファイルの場所を取得しています。(例:wp-content/uploads/2021/01)

pdfファイルを入れた形を「$file」としてOutPutの第一引数にし、第二引数には「F」を指定します。

そうすることで第一引数の場所にPDFファイルが作成されます。

あとは「wp_mail」の第五引数「attachment」にそのファイルを指定してあげるだけで送信ができます。

最後に作成したファイルは「unlink」削除しておきます。

ポイント

$pdf->OutPutは「F」を指定し、ファイルを作成、そのファイルを添付する。

$pdf->Outputで「E」を指定した場合は$contentに統合する形になると思います。

headerを「application/mixed」にしてとすれば出来ると思います。

ただし、純粋に「wp_mail」ではおそらくできないです。

wp_mailの中を参考に「PHPMailer」を利用するクラスを作成する必要がありそうです。

まとめ

以上、3つの出力方法の紹介でした。

デフォルトで「I」「D」など便利なものがあるけれどどうしても非同期の形で実装したい場合に利用してみてください。

メール添付のところはなかなか心が折れかけました。今度しっかりメールの仕組みについて勉強したいと思います。