LoginSignup
15
8

More than 5 years have passed since last update.

laravel 5.6にアップデートすると undefined function imagejpeg() と言われてテストが落ちる問題の解決

Posted at

これは何

以下のアップグレードガイドにしたがって laravel 5.5 => 5.6 のアップデートをやっていたら、ガイドに書いていない部分のテストが落ちたので困った話。
https://readouble.com/laravel/5.6/ja/upgrade.html

問題

手元のLaradockでphpunitを流すとテストが落ちないのだが、circleCI環境でテストを回すと落ちる。
エラーメッセージ

Call to undefined function Illuminate\Http\Testing\imagejpeg()

該当テストコードの例

    public function testAdd()
    {
        $this->post('/hoge/create', [
            'image' => UploadedFile::fake()->image('image.jpeg', 1400, 1400)->size(1000),
            'content' => '内容',
        ])->assertRedirect('/hoge');
    }

解決策

次の2ステップを行う

  • libjpeg-dev をパッケージマネージャでインストールする
  • gd のconfigure時に上記パッケージのパスを指定してあげるオプションを追加する --with-jpeg-dir=DIR

今回私はcircleCIにおけるファイルを編集したので参考として載せておきます。

       # Install Library 
       - run: sudo apt-get install -y libpng-dev libjpeg-dev 

       # Install PHP Extension 
       - run: sudo docker-php-ext-configure gd --with-png-dir=/usr/include --with-jpeg-dir=/usr/include
       - run: sudo docker-php-ext-install gd 

補足:なぜこの問題はlaravel updateのタイミングで起こったのか

Laravel 5.6においては
上記テストコードで呼んでいる image() メソッドは以下で、

    public function image($name, $width = 10, $height = 10)
    {
        return new File($name, $this->generateImage(
            $width, $height, Str::endsWith(Str::lower($name), ['.jpg', '.jpeg']) ? 'jpeg' : 'png'
        ));
    }

さらに呼ばれている generateImage() がもともと以下のようになっている。

    protected function generateImage($width, $height, $type)
    {
        return tap(tmpfile(), function ($temp) use ($width, $height, $type) {
            ob_start();

            $image = imagecreatetruecolor($width, $height);

            switch ($type) {
                case 'jpeg':
                    imagejpeg($image);
                    break;
                case 'png':
                    imagepng($image);
                    break;
            }

            fwrite($temp, ob_get_clean());
        });
    }

このファイルがlaravel 5.5では以下のようになっていた

    protected function generateImage($width, $height)
    {
        return tap(tmpfile(), function ($temp) use ($width, $height) {
            ob_start();

            imagepng(imagecreatetruecolor($width, $height));

            fwrite($temp, ob_get_clean());
        });
    }

つまり、imagejpeg() は呼ばれておらずimagepngだけが呼ばれていた。(我々のコードではおそらくこの仕様を知らず jpeg拡張子を指定していたが結局裏ではpngファイルが生成されていたと思われる。)
laravel 5.6においては分岐が追加されたことにより imagejpeg() が呼び出されることになり、今回のエラーが発生した。

15
8
1

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
15
8