2019-06-13 23:48 時点で lorempixel.com が落ちてるので、fzaninotto/Faker で image() を使ってて $faker->image() が false になるので代替サビースを強引に使ってみるよ

## lorempixel.com さん再び使えなくなる

前回の [2019-06-11 時点では fzaninotto/Faker で image() を使ってて $faker->image() が false になるよ](https://qiita.com/hokutoasari/items/b2f3dc7325e0c3b0e296) に続き、 2019-06-13 23:48 現在 lorempixel.com さんが落ちています。

前回は https://github.com/fzaninotto/Faker/issues/1710 にある通り、 SSL Certs の期限切れでのエラーでした。

で、ちょっとしたら Let's encrypt の証明証を更新されたようで、もとに戻っていました。(時刻は記録してなのですが、実際に手元で Seeder を走らせて問題なく動いていた。)

で、今は https://github.com/fzaninotto/Faker/issues/1712 にある通り、 2019-06-13 15:00 JST あたりですでに `And it seems down now.` と。

## とりあえずの対応方法：結論

/vendor/fzaninotto/faker/src/Faker/Provider/Image.php

```diff
    public static function imageUrl($width = 640, $height = 480, $category = null, $randomize = true, $word = null, $gray = false)
    {
- $baseUrl = "https://lorempixel.com/";
+         // $baseUrl = "https://lorempixel.com/";
+         $baseUrl = "https://picsum.photos/";
```

```diff
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FILE, $fp);
-           $success = curl_exec($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
+ //            $success = curl_exec($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
+             $success = curl_exec($ch) && (curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200 or curl_getinfo($ch, CURLINFO_HTTP_CODE) === 302 or curl_getinfo($ch, CURLINFO_HTTP_CODE) === 301);
```

なお、 vendor 以下を直接書き換えるのは望ましくないですね。

できれば Fork してから対応し、 Fork した方を composer から利用するようにするのが望ましいと思います。

## どうしよう

lorempixel.com さんダウンで、どうしよう。

自前で imagemgak か gd で頑張るのも、まぁありといえばありなのですが、面倒です。

とう言うわけで、楽に終わる代替サービスを探してみました。

で、 https://picsum.photos/ これ。

やった！同じやん！これは URL 部分を差し替えれば良いだけだね！

## URL を差し替えてみた

`lorempixel` で検索したところ、 `/vendor/fzaninotto/faker/src/Faker/Provider/Image.php` に `$baseUrl = "https://lorempixel.com/";` といった具合に lorempixel.com がハードコーディングされてることが確認できました。

これを差し替えればおしまいですね！

というわけで早速以下のように変更。

```diff
- $baseUrl = "https://lorempixel.com/";
+ // $baseUrl = "https://lorempixel.com/";
+ $baseUrl = "https://picsum.photos/";
```

で、動かしてみるものの、 `$fakeImage = $faker->image(...);` の結果は false 。

## 調査

xdebug を使えるように仕込んだ Docker Container なので、 `# export XDEBUG_CONFIG="idekey=PHPSTORM"` として、環境変数を設定してから PhpStorm で以下のメソッドのそれっぽい箇所に BreakPoint を仕込んで再度 Seeder を走らせてみました。

```php
    public static function image($dir = null, $width = 640, $height = 480, $category = null, $fullPath = true, $randomize = true, $word = null)
    {
        $dir = is_null($dir) ? sys_get_temp_dir() : $dir; // GNU/Linux / OS X / Windows compatible
        // Validate directory path
        if (!is_dir($dir) || !is_writable($dir)) {
            throw new \InvalidArgumentException(sprintf('Cannot write to directory "%s"', $dir));
        }

        // Generate a random filename. Use the server address so that a file
        // generated at the same time on a different server won't have a collision.
        $name = md5(uniqid(empty($_SERVER['SERVER_ADDR']) ? '' : $_SERVER['SERVER_ADDR'], true));
        $filename = $name .'.jpg';
        $filepath = $dir . DIRECTORY_SEPARATOR . $filename;

        $url = static::imageUrl($width, $height, $category, $randomize, $word);

        // save file
        if (function_exists('curl_exec')) {
            // use cURL
            $fp = fopen($filepath, 'w');
            $ch = curl_init($url);
            curl_setopt($ch, CURLOPT_FILE, $fp);
            $success = curl_exec($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
            fclose($fp);
            curl_close($ch);

            if (!$success) {
                unlink($filepath);

                // could not contact the distant URL or HTTP error - fail silently.
                return false;
            }
        } elseif (ini_get('allow_url_fopen')) {
            // use remote fopen() via copy()
            $success = copy($url, $filepath);
        } else {
            return new \RuntimeException('The image formatter downloads an image from a remote HTTP server. Therefore, it requires that PHP can request remote hosts, either via cURL or fopen()');
        }

        return $fullPath ? $filepath : $filename;
    }
```

で、その結果、以下の if 節で false となっていることが判明しました。

```php
            if (!$success) {
                unlink($filepath);

                // could not contact the distant URL or HTTP error - fail silently.
                return false;
            }
```

つまり怪しいのは 、ここ。

```php
            $success = curl_exec($ch) && curl_getinfo($ch, CURLINFO_HTTP_CODE) === 200;
```

とりあえず、どんな URL に実際にリクエストを出しているのか理解するため Debugger から Variables を確認したところ、 `$url = https://picsum.photos/1200/300/?82828` となっていることを確認しました。

うん、正しいっぽい。

とりあえず、この URL にブラウザからアクセスしてみましょう。

https://picsum.photos/1200/300/?82828 → https://picsum.photos/id/430/1200/300

はい、 URL が書き換わっておりました。

これはおそらくリダイレクトレスポンスか何かを出してますね。

というわけで、 Chrome の dev tool の network タブあたりから確認してみましょう。

やっぱり、 301, 302 ですね！

このあたりをフォローしたら大丈夫そうです。

というわけで、前述の記述に至りました。

あくまで、暫定対応です。