LoginSignup
0
0

Laravelのdusk、tcpdf使用メモ

Last updated at Posted at 2023-11-20

はじめに

larvelでテストツール(dusk)を使用し画像ショット作成。
その画像が一つに収まらない時、複数ページを取り合えす取得。
それをtcpdfで1つのpdfにしている。
chromedriverが必要とかSelenumが必要とか忘れた。
すぐに忘れるので、まだ多少動くものがあるうちにメモだけでも残す。

大まかな手順

前提:dockerを使用している
以下の環境を元に作成

Laravel DuskをDocker環境でインストールするには、いくつかのステップを踏む必要があります。以下は、そのプロセスです。

  1. Laravel Duskのインストール: まず、Laravelプロジェクトのルートにあるコンテナ内でDuskをインストールします。

    docker-compose exec app composer require --dev laravel/dusk
    
  2. Duskのセットアップ: Duskをセットアップします。これには、Duskのサービスプロバイダーを登録するために、AppServiceProviderにコードを追加したり、Dusk専用の.env.dusk.local環境設定ファイルを作成したりすることが含まれます。

    docker-compose exec app php artisan dusk:install
    

    dusk:install コマンドは、Duskのテストを書くためのテンプレートファイルを生成し、必要な設定ファイルをセットアップします。

  3. Dockerfileの修正: DuskはデフォルトでGoogle Chromeを使用します。そのため、Dockerコンテナ内にChromeとChromeDriverをインストールする必要があります。Dockerfileに以下のようなコマンドを追加して、これらの依存関係をインストールします。

    # Chromeのインストール
    RUN apt-get update && apt-get install -y libnss3-dev libxss1 libasound2 libxrandr2 libatk-bridge2.0-0 libcups2 libgtk-3-0 libgbm1
    
    # ChromeDriverのダウンロードとインストール
    RUN LATEST_CHROMEDRIVER_VERSION=`curl -sS chromedriver.storage.googleapis.com/LATEST_RELEASE` && \
        curl -sS -o /tmp/chromedriver_linux64.zip https://chromedriver.storage.googleapis.com/$LATEST_CHROMEDRIVER_VERSION/chromedriver_linux64.zip && \
        unzip /tmp/chromedriver_linux64.zip -d /usr/local/bin/ && \
        chmod +x /usr/local/bin/chromedriver
    

    Dockerfileに変更を加えたら、Dockerイメージを再ビルドする必要があります。

    docker-compose up -d --build
    
  4. Duskの実行: 環境が整ったら、Duskテストを実行してみましょう。

    docker-compose exec app php artisan dusk
    

Duskのテスト実行時には、ブラウザがGUIモードで起動しようとするので、ヘッドレスモードで動作するように.env.dusk.local環境ファイルを設定することを忘れないでください。たとえば、以下のような設定を行います。

Seleniumサービスの確認

  1. docker-compose.ymlの確認: Seleniumサーバーをdocker-compose.ymlに追加しているか確認してください。もし追加していない場合は、以下のようにサービスを追加する必要があります。
version: '3'
services:
  # 既存のサービス(app, nginx, db, ...)

  selenium:
    image: selenium/standalone-chrome:latest
    ports:
      - "4444:4444"
    networks:
      - laravel
    # その他の必要なオプションがあれば追加する

networks:
  laravel:
    driver: bridge
  1. ネットワークの接続確認: Seleniumサーバーがlaravelネットワークに接続していることを確認します。docker-compose.yml内で他のサービスと同じネットワークに所属している必要があります。

  2. コンテナの再起動: 変更を適用するために、Dockerコンテナを再起動します。

docker-compose down
docker-compose up -d

Duskの設定の確認

  1. .env.dusk.localの確認: .env.dusk.local ファイルがプロジェクトのルートにあるか確認し、適切な設定がされているか確認してください。
APP_URL=http://localhost:8000
DUSK_DRIVER_URL=http://selenium:4444/wd/hub

Laravel Duskでテストを作成するには、artisanコマンドを使ってテストファイルを生成します。以下のコマンドをコンテナ内で実行して、新しいDuskテストファイルを作成します。

docker-compose exec app php artisan dusk:make NewExampleTest

このコマンドは、NewExampleTest という名前で新しいDuskテストクラスを作成します。このテストクラスは tests/Browser ディレクトリ内に配置されます。

<?php

namespace Tests\Browser;

use Illuminate\Foundation\Testing\DatabaseMigrations;
use Laravel\Dusk\Browser;
use Tests\DuskTestCase;

class NewExampleTest extends DuskTestCase
{
    /**
     * A Dusk test example.
     */
    public function testExample(): void
    {
        // $this->browse(function (Browser $browser) {
        //     $browser->visit('https://www.yahoo.co.jp')
        //         ->assertSee('Yahoo');

        //     // JavaScriptを実行してページの最下部へスクロール
        //     $browser->script('window.scrollTo(0, document.body.scrollHeight);');

        //     // 少し待機してからスクリーンショットを撮影
        //     $browser->pause(1000) // 1000ミリ秒(1秒)待機
        //         ->screenshot('yahoo_homepage'); // スクリーンショットを撮影
        // });
        // $this->browse(function (Browser $browser) {
        //     $browser->visit('https://www.yahoo.co.jp')
        //         ->maximize()
        //         ->screenshot('yahoo_homepage'); // スクリーンショットを撮影

        // });
        $this->browse(function (Browser $browser) {
            // Yahoo Japanのページを開く
            $browser->visit('https://www.yahoo.co.jp');

            // スクロールする回数を決定する
            $scrolls = 3; // 例として3回スクロールする
            $scrollHeight = 1000; // 各スクロールで移動する高さ

            for ($i = 0; $i < $scrolls; $i++) {
                // ページをスクロールする
                $browser->script("window.scrollTo(0, $scrollHeight * $i);");

                // スクロール後に描画が完了するまで少し待機
                $browser->pause(1000); // 1秒間待機

                // スクリーンショットを撮影
                $browser->screenshot("page_part_{$i}");
            }
        });
    }
}


  1. Duskの実行: 上記の設定を行った後、Duskテストを再度実行します。
docker-compose exec app php artisan dusk

スクリーンショット 2023-11-20 22.03.15.png

上記のpngを一つにする

PdfController
<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use TCPDF;
use Illuminate\Support\Facades\File; // これを追加します


class PdfController extends Controller
{
    public function createPdfFromImages()
    {

        // 新しいPDFドキュメントを作成
        $pdf = new TCPDF();

        // ヘッダーとフッターを削除
        $pdf->setPrintHeader(false);
        $pdf->setPrintFooter(false);

        // 画像ファイルの配列
        // $images = [
        //     public_path('screenshots/page_part_0.png'),
        //     public_path('screenshots/page_part_1.png'),
        //     public_path('screenshots/page_part_2.png'),
        //     public_path('screenshots/yahoo_homepage.png'),
        // ];

        $images = [
            base_path('tests/Browser/screenshots/page_part_0.png'),
            base_path('tests/Browser/screenshots/page_part_1.png'),
            base_path('tests/Browser/screenshots/page_part_2.png'),
            base_path('tests/Browser/screenshots/yahoo_homepage.png'),
            base_path('tests/Browser/screenshots/peach-1.jpg'),

        ];

        // 各画像をPDFに追加
        // foreach ($images as $image) {
        //     $pdf->AddPage();

        //     // 画像をページに挿入
        //     $pdf->Image($image, 15, 25, 180, 0, 'PNG');
        // }
        foreach ($images as $image) {
            $pdf->AddPage();

            // ページ全体の背景色を変える場合
            $pdf->SetFillColor(0, 0, 255); // RGBで青色
            // ページ全体に背景色を適用
            $pdf->Rect(0, 0, $pdf->GetPageWidth(), $pdf->GetPageHeight(), 'F');

            // ファイルの拡張子に基づいて形式を設定
            $imageType = strtolower(pathinfo($image, PATHINFO_EXTENSION));
            if ($imageType == 'jpg' || $imageType == 'jpeg') {
                $imageType = 'JPG';
            } elseif ($imageType == 'png') {
                $imageType = 'PNG';
            } // 他の画像形式も同様に追加することができます

            // 画像をページに挿入
            $pdf->Image($image, 15, 25, 180, 0, $imageType);
        }

        // PDFをファイルとして出力
        $pdfFileName = public_path('screenshots/combined_images.pdf');
        // ディレクトリが存在しない場合は作成する
        if (!File::isDirectory(dirname($pdfFileName))) {
            File::makeDirectory(dirname($pdfFileName), 0755, true, true);
        }

        $pdf->Output($pdfFileName, 'F');

        return response()->download($pdfFileName);
    }
}


web.php

use App\Http\Controllers\PdfController;

Route::get('/create-pdf', [PdfController::class, 'createPdfFromImages']);

以下のような感じでダウンロードできる
スクリーンショット 2023-11-20 23.03.53.png

PDFのページ例
スクリーンショット 2023-11-20 23.06.28.png

追記
1ページに収めたい場合
ある特定の要素までスクロールさせて高さを取得。

            $browser->visit('あるアドレス')
                ->waitFor('特定の要素', 30)
                ->scrollTo('特定の要素');


            $height = $browser->driver->executeScript("return document.body.scrollHeight");
            echo "Height: " . $height . "\n";

            // ページのトップまでスクロールし直す
            $browser->driver->executeScript('window.scrollTo(0, 0);');
            sleep(1); // スクロール後にレンダリングを安定させるために少し待つ

            $browser->resize(1920, $height)
                ->screenshot('yahoo_screenshot');
0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0