PHPでHTTPリクエスト

PHPではfile_get_contentsという強力な関数があり、ローカルファイルでもWebサイトでも、その内容を簡単に取得することができます。

例えば、Livedoorの天気情報APIから東京の天気を取得するには、

<?php
$res = file_get_contents('http://weather.livedoor.com/forecast/webservice/json/v1?city=130010');
$weather = json_decode($res, true);

とするだけです。(JSON形式で返ってくるため、json_decodeでデシリアライズして連想配列に格納しています。)

一度利用するだけのスクリプトであればこれで十分かと思いますが、運用環境であればエラーハンドリングも必要になってくると思います。その点も踏まえながら、次にGETリクエストとPOSTリクエストについて、詳しい使い方をお伝えします。

GETリクエスト

file_get_contentsにURLを指定した場合、標準では、HTTPステータスコードが4xxや5xxの場合にWarningエラーが発生し、レスポンスボディを取得することができません。次のようにignore_errors属性を定義したcontextを作成し、第三引数に渡すことで、4xxや5xxの場合でも取得できるようになります。

<?php
$context = stream_context_create([
    'http' => [
        'ignore_errors' => true
    ]
]);
$res = file_get_contents('<URL>', false, $context);

次に、HTTPステータスコードに応じたエラー処理ですが、file_get_contentsを実行すると、$http_response_header変数にレスポンスヘッダが自動的にセットされるため、これを利用します。

HTTPステータスコードは1行目に含まれるので、
$http_response_header[0]の値に応じて、処理を切り分けると良いかと思います。値は「HTTP/1.1 200 OK」という形式になっていますので、下の例では、strpos関数を使ってステータスコード200が含まれるかチェックしています。

if (strpos($http_response_header[0], '200') !== false) {
    // HTTPステータスコードが200(正常)だった場合の処理
    // ...
} else {
    // それ以外の場合の処理
    // ...
}

ステータスコードを厳密に抽出したい場合は、正規表現を使います。

preg_match('/HTTP\/1\.[0|1|x] ([0-9]{3})/', $http_response_header[0], $matches);
$statusCode = $matches[1];

POSTリクエスト

file_get_contentsは標準でGETリクエストになりますが、上述したcontextのmethod属性にPOSTを指定することで、POSTリクエストを投げることもできます。

$headers = [
    'Content-Type: application/x-www-form-urlencoded'
];

$body = [
    'field1' => 'value1',
    'field2' => 'value2'
];

$context = stream_context_create([
    'http' => [
        'method' => 'POST',
        'header' => implode("\r\n", $headers),
        'content' => http_build_query($body, '', '&'),
        'ignore_errors' => true
    ]
]);
$res = file_get_contents('<URL>', false, $context);

HTTPリクエストヘッダはheader属性、リクエストボディはcontent属性に値を設定します。ここでは、それぞれ配列と連想配列でデータを準備し、implodeおよびhttp_build_query関数を利用して必要なフォーマットに整形した上で、各属性に割り当てています。

LaravelのMailableでコールバックを設定

LaravelではMailableクラスを使用することで、メールの組み立てと送信を簡単に行うことができます。

Mailableクラスを作成するには、artisanコマンドを使うと簡単です。

$ php artisan make:mail MyMailable

このコマンドを実行すると、app/Mail/MyMailable.phpというファイルが作成され、中身は次のようになります。

<?php

namespace App\Mail;

use Illuminate\Bus\Queueable;
use Illuminate\Mail\Mailable;
use Illuminate\Queue\SerializesModels;
use Illuminate\Contracts\Queue\ShouldQueue;

class MyMailable extends Mailable
{
    use Queueable, SerializesModels;

    /**
     * Create a new message instance.
     *
     * @return void
     */
    public function __construct()
    {
        //
    }

    /**
     * Build the message.
     *
     * @return $this
     */
    public function build()
    {
        return $this->view('view.name');
    }
}

buildメソッドの戻り値として、レンダリングされたテンプレートを返すことで、メッセージの送信が完了します。

メッセージの送信後に実行したい処理がある場合は、Mailableクラスのcallbacksプロパティ(配列)に関数をセットします。コールバック関数の引数には$message(Messageオブジェクト)が渡されるため、$message->getId()でメールサーバーから返されたMessage-IDを取得することもできます。

    public function build()
    {
        $this->callbacks[] = function($message) {
            // 送信後に実行したい処理
        };
        return $this->view('view.name');
    }

ユーザーを指定してcronを実行

Laravelでタスクスケジュールを利用する場合、cronに次のエントリを追加します。

* * * * * php /path-to-your-project/artisan schedule:run >> /dev/null 2>&1

タスク内でログ出力をする際には、Webと同様にLoggerが使用できますが、cronをrootユーザーで実行してしまうと、ログファイルの所有者がrootになってしまいます。

そのため、WebサーバーにApacheを利用している場合、Web側がログを出力する際にパーミッションエラーが発生する場合があります。

これを避けるためには、apacheユーザーとしてcronジョブを設定するのが良いと思います。

$ crontab -u apache -e

各言語で組み込みWebサーバーを利用する

前回、IntelliJの組み込みWebサーバーをご紹介しましたが、今回は、各プログラミング言語に含まれているWebサーバーをご紹介したいと思います。

IntelliJの場合は、プロジェクト名のサブフォルダがパスに含まれてしまうため、画像等を「/img/xxxxx.png」のようにドキュメントルートからのパスで指定している場合は、こちらの方法の方が良いかもしれません。

各言語とも、コンソール上でコマンドを実行することでサーバーを立ち上げることができます。

PHP

$ php -S <Host>:<Port>

「<Host>:<Port>」には例えば「localhost:80」を指定します。 コマンドの実行場所がドキュメントルートになります。

Python3

$ python -m http.server [<Port>]

<Port>を省略すると80が選択されます。 コマンドの実行場所がドキュメントルートになります。

Ruby

$ ruby -run -e httpd <DocumentRoot> -p <Port>

コマンドの実行場所をドキュメントルートにするには、<DocumentRoot>に「.」を指定します。

Node.js

Nodeには標準でWebサーバーは含まれていませんが、モジュールとして簡単に組み込むことができます。今回は、一番有名なhttp-serverをご紹介します。

まずはnpmでhttp-serverをインストール。

$ npm i -g http-server

http-serverを実行。

$ http-server [-p <Port>]

<Port>を省略すると80が選択されます。 コマンドの実行場所がドキュメントルートになります。

LaravelでSSL certificate problem

LaravelでFacebookOAuth認証を行おうとしたところ、以下のようなエラーが発生しました。

RequestException in CurlFactory.php line 187:
cURL error 60: SSL certificate problem: unable to get local issuer certificate (see http://curl.haxx.se/libcurl/c/libcurl-errors.html)

調査の結果、CA証明書がphp.iniで正しく設定されていないことが原因であると分かりました。

http://curl.haxx.se/ca/cacert.pem

をダウンロードして、「C:\php\cacert.pem」として保存し、php.iniに以下の記述を加えることで、エラーが解消されました。

[curl]
; A default value for the CURLOPT_CAINFO option. This is required to be an
; absolute path.
curl.cainfo=C:\php\cacert.pem

LaravelのmigrateでPDOException

Laravelでmigrateコマンドを使用したところ、PDOException(could no find driver)が発生しました。

$ php artisan migrate
**************************************
*     Application In Production!     *
**************************************

 Do you really wish to run this command? [y/N] (yes/no) [no]:
 > yes



  [PDOException]
  could not find driver

調査の結果、php.iniのMySQL拡張がコメントされているという凡ミスでした。「;」を外して、再度実行すると正しく処理されました。

$ vi php.ini

...
;extension=php_pdo_mysql.dll
...

LaravelでCouldn’t find preset “es2015″エラー

Laravelプロジェクトを新しく作成し、gulpを通じてelixirを実行したところ、以下のようなエラーが出ました。

これを解決するには、以下の二つのパッケージをインストールする必要があるようです。

$ npm install babel-preset-es2015 --save
$ npm install babel-preset-react --save

こちらの議論では、npmをアップグレードすれば解決するとの発言もありますが、私の環境ではうまくいきませんでした。

Laravelコマンドのまとめ

最近、PHPのフレームワークの中で一番勢いがあるLaravelで使用するコマンドのまとめです。

Webサーバーを起動

開発用のWebサーバーを起動します。デフォルトのURLはhttp://localhost:8000になります。

$ php artisan serve

データベースのマイグレート

database/migrations以下のマイグレーションスクリプトに従って、データベースに変更を加えます。

$ php artisan migrate

 

WindowsにComposerをインストール

Windows10にPHPのパッケージマネージャであるComposerをインストールした際のメモです。

まず、ComposerのWebサイトからインストーラーをダウンロードします。「Download」リンクをクリックしてDownloadページに進み、「Composer-Setup.exe」のリンクをクリックするとダウンロードが開始します。

ダウンロードしたComposer-Setup.exeを実行すると、インストールのためのウィザードが開始します。「Next >」で次に進みます。

次に、PHPの実行ファイルのパスを指定します。Pathが通っていれば自動的に選択されると思います。

php.iniファイルでopenssl拡張が有効化されていないと、次の警告がでます。

php.iniの「extension=php_openssl.dll」のコメント(;)を外し、一旦「< Back」して「Next >」をクリックします。

警告が消え、プロキシ設定の画面に進みます。特に設定の必要がなければ、そのまま「Next >」ボタンをクリックします。

準備が整ったので、「Install」ボタンをクリックしてインストールを開始します。

注意書きを確認の上、「Next >」「Finish」と続けて、インストールは完了です。

Top