Help us understand the problem. What is going on with this article?

HerokuでPHPを使うときに気を付けるところ

More than 5 years have passed since last update.

HerokuでのPHPサポートが正式版になってたので、現時点でこんな感じで使っているよ、ということ。

reference

start

  • composer.jsonがあればPHPアプリケーションとしてdetectされる
  • しかし、package.jsonとかGemfileとかあるとPHPのアプリケーションとして認識されない
    • 今どきはこういうファイル、大抵ある
  • buildpackを明示的に指定することでPHPアプリケーションと認識させる
    • heroku config:set BUILDPACK_URL=https://github.com/heroku/heroku-buildpack-php
  • 必要ならタイムゾーン設定
    • heroku config:add TZ=Asia/Tokyo

runtime

  • PHPとHHVMが選べる
  • HHVMがサポートされてないフレームワークとかあるので注意
    • でも大概動く
  • どちらを選ぶかはcomposer.jsonに記述する

runtime settings

[PHP]
upload_max_filesize = "10M"

[Date]
date.timezone = "Asia/Tokyo"

[mbstring]
mbstring.language = Japanese
mbstring.internal_encoding = UTF-8
mbstring.encoding_translation = Off
mbstring.func_overload = 0

server

  • Apacheとnginxが選べる
    • Apacheはmod_proxy_fcgi経由のFastCGIで動く
    • nginxはphp-fpm経由で動く
  • Procfileで指定する
    • nginx: web: vendor/bin/heroku-php-nginx
    • nginxでdocument_rootを指定: web: vendor/bin/heroku-php-nginx web
    • nginxで設定ファイルも指定: web: vendor/bin/heroku-php-nginx -C nginx_app.conf web
    • nginxの場合にclient_max_body_sizeを指定できないぽいのでアップロードがある場合はApacheがよさそう
    • Apache(2.4): web: vendor/bin/heroku-php-apache2
    • Apacheでdocument_rootを指定: web: vendor/bin/heroku-php-apache2 web
    • 設定ファイルを指定することもできるが.htaccessを使った方が楽

nginx_app.conf

index.phpから起動する今どきなフレームワークの場合の設定。
ちなみにCSSとか画像をHerokuから配信するのであれば、ここでExpiresヘッダーを付加するヘッダーの追加が可能。

location / {
    # try to serve file directory, fallback to rewrite
    try_files $uri @rewriteapp;
}

location @rewriteapp {
    # rewrite all to index.php
    rewrite ^(.*)$ /index.php/$1 last;
}

location ~ .*\.(jpg|gif|png|ico|css|js|ttf|eot|svg|woff) {
    expires 5d;
}

location ~ ^/index\.php(/|$) {
    fastcgi_pass heroku-fcgi;
    fastcgi_split_path_info ^(.+\.php)(/.*)$;
    include fastcgi_params;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    fastcgi_param HTTPS off;
}

.htaccess(Apacheを使う場合)

index.phpから起動する今どきなフレームワークの場合の設定。
もちろんその他の設定もできますが、省略。

FallbackResource /index.php
LimitRequestBody 10485760

extension

  • Heroku側で結構用意されてるのでそれを使う
  • composer.jsonに使いたいextensionを記述すればOK
  • どうしても自分で入れたい場合はbuildpackをいじるしかない
    • 面倒なのでやるべきではない
    • そこまでやるなら素直にAWS使うべき

add-on

New Relic

  • add-onで有効にした後でdeployすると勝手にext-newrelicが入る
    • 有効にしただけだと当然入らないので注意。deployしよう
  • ライセンスキーなどは自分のものに差し替えるのがよさそう
    • アプリ名: heroku config:set NEW_RELIC_APP_NAME=<アプリ名>
    • ライセンスキー: heroku config:set NEW_RELIC_LICENSE_KEY=<自分のキー>

MongoLab

  • 有効にするとMONGOLAB_URIという環境変数に接続先情報がセットされる
  • Mongoクラスの接続文字列としてそのまま使える
  • セッションストレージで利用する場合など、DB名が必要な場合は最後のスラッシュ以降の文字列を取り出して利用する。
$mongolabUri = getenv('MONGOLAB_URI');
$mongolabDbName = substr($mongolabUri, strrpos($mongolabUri, '/') + 1);

Postgres

  • 有効にするとDATABASE_URLという環境変数に接続先情報がセットされる
    • 例: postgres://<ユーザー名>:<パスワード>@<ホスト名>:<ポート番号>/<DB名>
  • parse_url関数を使って必要な値に分解するのがよい
$dbUrl = parse_url(getenv('DATABASE_URL'));

$dbName = ltrim($dbUrl['path'], '/');
$dbHost = $dbUrl['host'];
$dbPort = $dbUrl['port'];
$dbUser = $dbUrl['user'];
$dbPass = $dbUrl['pass'];

SendGrid

  • 有効にするとSENDGRID_USERNAMESENDGRID_PASSWORDという環境変数がセットされる
    • 必要であれば自分でSendGridのサイトから登録、自分のユーザー名とパスワードを同環境変数に設定して使う
    • ユーザー名: heroku config:set SENDGRID_USERNAME=<自分のユーザー名>
    • パスワード: heroku config:set SENDGRID_PASSWORD=<自分のパスワード>
    • 取得はgetenv('SENDGRID_USERNAME')getenv('SENDGRID_PASSWORD')
  • 公式のライブラリ、Sendgrid-phpを使うのが便利

logging

  • ログ出力はローカルにするわけにいかない
  • 標準出力(php://stdout)もしくは標準エラー出力(php://stderr)に出力するのがよい
  • 必要に応じてPapertrailなどのアドオンを組み合わせるのがオススメ

limitation

  • サーバー側に何か保存するのはダメ
    • ファイルアップロードを一度受けるぐらいならOK
  • ファイルベースのセッション、使えない

etc.

switch environment

  • 環境変数を利用してローカルの開発環境とHeroku上の環境で設定とか切り替えるのがよさそう
    • heroku config:set PHP_ENV=heroku

こんな感じで切り替え

switch (getenv('PHP_ENV')) {
    case 'heroku':
        $app = require __DIR__ . '/bootstrap.heroku.php';
        break;
    default:
        $app = require __DIR__ . '/bootstrap.local.php';
        break;
}

Basic Authentication

  • Herokuの場合だけ読まれるファイルにPHPで書くのが早い
if (isset($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'])
        && $_SERVER['PHP_AUTH_USER'] === '<ユーザー名>'
        && $_SERVER['PHP_AUTH_PW'] === '<パスワード>') {
} else {
    header('WWW-Authenticate: Basic realm="<表示されるメッセージ>"');
    header('HTTP/1.0 401 Unauthorized');
    exit;
}

Hide versions of PHP and Apache

hiro_y
Web application developer using PHP/Node.js from 10mado, LLC
https://10mado.jp/
10mado
合同会社テンマドです。ビジネス支援事業として、社外CTOや技術顧問などのアドバイザー業と、いわゆる受託のお仕事をしています。さらにサービス開発事業として、mimemoやiruca、10plate、conasuなど、webサービスを中心に企画・開発・運営を行っています。
https://10mado.jp
Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
Comments
No comments
Sign up for free and join this conversation.
If you already have a Qiita account
Why do not you register as a user and use Qiita more conveniently?
You need to log in to use this function. Qiita can be used more conveniently after logging in.
You seem to be reading articles frequently this month. Qiita can be used more conveniently after logging in.
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
ユーザーは見つかりませんでした