PHPでハマったことをPHPの落とし穴と題して逐次書いていきたいと思います。

問題

ログインができない!動いている環境とPHPのバージョンも合わせたのになぜ!?

$_REQUEST$_COOKIEの値が入ってないぞ。

原因

$_REQUESTの中身はphp.iniのrequest_orderディレクティブの値に依存する。デフォルトではCookieのCが含まれてない。

PHP: コア php.ini ディレクティブに関する説明 - Manual

解決策

php.iniのrequest-orderディレクティブにCを追加する?

そうではなくCookieを使いたい場合はこういった環境依存のある$_REQUESTではなく$_COOKIEを使うべき。コードの意図も伝わりやすい。

しかし、一度大量に混入したcookie用途の$_REQUEST利用を全て修正するのは難しそうだ。単純にreplaceはできないので$_REQUESTでgrepして、文脈から判断するしかなさそうだ。

明確な理由がない限り$_REQUESTはおすすめできない。$_GET, $_POST, $_COOKIEを使うべきだ。

PHPのスーパーグローバル変数($_から始まるやつ)の扱いは名前が表す通り注意が必要だと思いました。

関連:レガシーPHP改善日記シリーズ

以前書いた下記を使ってport forwardしといてhttp://foo.lvh.me:8080/とかにアクセスする。

Macに複数サイトに対応したPHP環境を簡単に作る - komagata

virtualboxでprivate networkを使うとスマホ確認ができないし、public networkだとboxのポータビリティが下がるし、port forwardだとsslの確認ができないし(rootで起動して443で立ち上げらればいいけど非推奨だし)痛し痒しな感じ。

synced folder遅い問題も、docker使った場合も同じだけどみんなどうしてるんだろう?

週1日のペースで出社して作業してるんですが、なかなか手強いですね。

サイトが沢山問題

でかいレガシーシステム一個と戦うのではなく、30個ぐらいのサイトがあって、それをメンテしなきゃいけないので大変です。

システム的には殆ど同じなので、大元があってそれをコピーして使っています。コピーしたあとはそれぞれのサイトでカスタマイズが入るので分岐していきます。

これは壮大なコピペと同じことなのでメンテ対象のコード行数が増大していきます。一刻も早くこれをしないですむように設計しなおさないといけません。

共通開発環境問題

社内サーバー上に共通開発環境が一つあって、そこに上記の30近くのサイトが並んでます。そこをみんなでいじって、誰かが代表としてsvnにコミットします。

共通開発環境には、誰か一人が開発環境を作ればいいという利点がありますが、二つの問題点があります。

  1. 誰が変更したのかわからないのでレビューできない。一つ一つの変更がいい加減になり、いらないファイルが放置されて散らかりっぱなしになる。(スラム化)
  2. 複数人が同時に作業していると変更点が衝突する、壊れる。

進捗

とにかくまずはテストを書かないことには変更もできないのでテスト環境の作成を進めています。しかし、固定のパス設定などポータブルになっていないのでローカルやCircleCIで動くようにするまでが一苦労。

最近のPHPだと動かない機能を使っていたら修正。最近のMySQLだと動かない書き方を修正。結局、まずは共通開発環境と全く同じOSをVirtualBox上に用意して動作させることにしました。

これでphpunit + seleniumのテストはなんとか動きそうです。

悩んでいること

テストが動き、コードレビューを機能させるには各自が自分の環境を持つ必要があります。Windowsでは動かない機能も使っているのでVirtualBoxに環境を作ってそこで各自が上記の30超のサイトを開発しなければなりません。

VirtualBoxのSynced Folersは遅いのでWindowsの場合はsmb、Macの場合はnfsを使って・・・など、僕は構わないですが結構敷居が高くて、

「みんなホントにこれで開発してるのかな?」

と不安になってきます。

共通開発環境問題の問題点を解決しつつ、環境構築の手間を少なくする方法は何かないもんでしょうか・・・。

みんなどうしてるのか気になって仕方ないので次回のPHP勉強会東京に参加登録しました。

第88回 PHP勉強会@東京 - PHP勉強会@東京 | Doorkeeper

関連:レガシーPHP改善日記シリーズ

下記でVirtualDocumentRootを使ってPHP環境を作りましたが、apacheの環境変数的には変わってないようで、デフォルトの値が入ってしまいます。(CentOS 6.6に入っているapache 2.2.15で確認しているので新しいのでは治ってるかも)

Macに複数サイトに対応したPHP環境を簡単に作る - komagata

すごく困るんですが、下記のようにPHPで無理やり書き換えればOK。

<virtualhost *:80>
    VirtualDocumentRoot /srv/%0

    # Ref: http://joshbenner.me/blog/quick-tip-get-proper-document-root-when-using-mod-vhost-alias/
    php_admin_value auto_prepend_file /srv/set_docroot_hack.php
</virtualhost>
<directory /srv/*>
    Order allow,deny
    Allow from all
</directory>

/srv/set_docroot_hack.php:


<?php
$_SERVER['DOCUMENT_ROOT'] = str_replace($_SERVER['SCRIPT_NAME'], '', $_SERVER['SCRIPT_FILENAME']);

なんか危ういですね。

TL;DR

ApacheのVirtualDocumentRootlvh.meを使うと簡単。

ApacheのVirtualDocumentRootを使う

Yosemiteデフォルトを想定。

$ sudo vi /etc/apache2/extra/httpd-vhosts.conf
<virtualhost *:80>
  VirtualDocumentRoot /Users/komagata/Sites/%0
</virtualhost>
<directory /Users/komagata/Sites/*>
  Require all granted
</directory>

上記設定で~/Sitesにドメイン名の名前のディクレクトリを作れば動くようになる。(phpとvhostを有効化する設定は各自やっておいてください。)

そのディレクトリ名ですが、foo.lvh.meunk.lvh.meなどlvh.meのサブドメインにすればOK。

lvh.meを使う

VirtualDocumentRootだけだと/etc/hostsにサイトを追加するごとに追記する必要があります。hostsファイルはワイルドカードに対応してないので辛い。

# /etc/hosts
127.0.0.1    *.localhost

こんな風にかければよかったんだけどねぇ。かといってローカルにDnsmasqのようなDNSサーバーを入れるのも億劫です。

ところが127.0.0.1にlvh.meというドメインを割り当ててる傑物がいるとの情報を入手。(名前のLevi cookの略でlvhなのかな?)

% host lvh.me    
lvh.me has address 127.0.0.1
% host foo.lvh.me
foo.lvh.me has address 127.0.0.1

Levi神のお陰で適当にlvh.meのサブドメインを使えばOKになりました!

~/Sites/foo.lvh.me~/Sites/unk.lvh.meのようなディレクトリを作るだけで追加の設定なしにPHPアプリがどんどん作れます。

$ vi ~/Sites/foo.lvh.me/index.php
Hello, <?= $_SERVER['HTTP_HOST'] ?>
$ vi ~/Sites/unk.lvh.me/index.php
Hello, <?= $_SERVER['HTTP_HOST'] ?>

pow併用兄貴の場合

公式Wikiで懇切丁寧に書いてあります。

Running Pow with Apache · basecamp/pow Wiki

チームでのやりとりはSlackですが、仕事の依頼とか外部との仕事関係でのやりとりってFacebook Messengerが多いです。多くないですか?

しかしFacebook Messengerってちょくちょくチェックするにはとても不便で、何故かというとチェックするたびにFacebookのTimelineが目に入って、

「この動画おもしろいな。知り合いにURLを送って置こう。・・・そういえば俺は何をしてたんだっけ?」

となることが頻繁にあるからです。

なのでMacでFacebook Messenger専用のクライアントを色々探してたんですがgoofyが自分の中で決定版で文句無しです。

$ brew cask install goofy

見た目もかわいいし、複数人チャットできるし、無料だし。

あと秋元さんがPHPプログラマー探してるそうなのでご存知の方はぜひ。(ついで感)

追記:

https://www.messenger.com がまさかのスピンオフしたのでブラウザでこのサイトを見るのが一番ですね。

「おい、Nexus6あくしろよ。」

しょっちゅうチェックしてると仕事に影響が出るので書いた。

hurry_up_nexus6/clock.rb at master · komagata/hurry_up_nexus6:

require 'open-uri'
require 'mail'
require 'css_selector'
require 'clockwork'
include Clockwork

NEXUS6_URL = 'https://play.google.com/store/devices/details/Nexus_6_64_GB_%E3%82%AF%E3%83%A9%E3%82%A6%E3%83%89_%E3%83%9B%E3%83%AF%E3%82%A4%E3%83%88?id=nexus_6_white_64gb&hl=ja'

Mail.defaults do
  delivery_method :smtp, {
    address:              'smtp.sendgrid.net',
    port:                 '587',
    domain:               'heroku.com',
    user_name:            ENV['SENDGRID_USERNAME'],
    password:             ENV['SENDGRID_PASSWORD'],
    authentication:       :plain,
    enable_starttls_auto: true
  }
end

handler do |job, time|
  html = open(NEXUS6_URL) { |f| f.read }
  status = CssSelector.new.parse(html, '.shipping-status').strip
  if status != '現在在庫切れです。しばらくしてからもう一度ご確認ください。'
    Mail.deliver do
      from     'komagata@gmail.com'
      to       ENV['MAIL_SEND_TO']
      subject  'Nexus6 is now available!'
      body     "Go fast! #{NEXUS6_URL}"
    end
  else
    puts 'Not available...'
  end
end

every(1.minute, 'check_nexus6')

「FRINGE/フリンジ」の J.J. エイブラムスと「ダークナイト」の脚本家ジョナサン・ノーランが贈るわけではない、IT業界のタブーに切り込んだサスペンス実話。

(私本人は真剣にレガシーPHPに取り組んでおります。)

  1. シーズン1
    1. エピソード1
    2. エピソード2
    3. 特別編1 レガシーPHPプロジェクトあるある
    4. エピソード3
    5. 特別編2 phpプログラマーの募集
    6. エピソード4
    7. エピソード5
    8. エピソード6
    9. エピソード7
    10. エピソード8
    11. 特別編3 PHPMatsuri2012
    12. エピソードLAST
  2. シーズン2
    1. エピソード0
    2. エピソード1
    3. エピソード2
    4. エピソード3
    5. 番外編1 ピクルス原理を誤用(応用)する
    6. エピソード4
    7. エピソード5
    8. エピソード6
  3. PHPの落とし穴
    1. PHPの落とし穴1

ツール

レガシーPHP改善・コンサルティングはこちらから承っております。お気軽にどうぞ。

お問い合わせ | 合同会社フィヨルド

レガシーPHP診断を作りました。

回答結果はこちらで見られます。

レガシーPHP診断 - みんなの診断結果

基本的に選択肢の上の方がよりおすすめという感じです。まずは自社の環境がどのような状態か把握するチェックリストとして使っていただければいいかなと思いました。

改善に関してはPHP: The Right Wayが参考になると思います。

関連:レガシーPHP改善日記シリーズ

デデドン!

「Adobeのバカ!(Case sensitiveなファイルシステムを恐れるなんて)いくじなし!」

PDFの編集、文字とかだったらPreviewで行けるんですが、画像を追加とかできないですよね。何か良いソフトありますかねぇ?