PHP」タグアーカイブ

PHPをWindows 10上のVisual Studio Codeを使って「Webサーバなしで」デバッグする方法

Windows 10でPHPをサーバサイド開発ではなく、VBScriptやPowerShellと同じようにローカルで実行するスクリプトとして使っている。

MicrosoftのVisual Studio Codeを使えばIntellisenseの自動補完でコーディングもできて便利だが、どうすればデバッグでステップ実行ができるのか、ネットで調べ始めた。

とりえあずXdebugというPHPの拡張機能(DLLファイル)が必要なことは分かった。

Xdebug – Debugger and Profiler Tool for PHP

ところが、Xdebugの使い方について、リモートのWebサーバやローカルにApacheかIISで構築したWebサーバでPHPを動かす前提の記事ばかりで参考にならない。

試行錯誤してようやくWebサーバなしでデバッグする方法が分かった。

すでにPHPスクリプトは実行できる状態になっているとする。

(1) XdebugのDLLのダウンロード

上記リンク先からXdebugのDLLファイルをダウンロードし、PHPのインストールフォルダ配下の「ext」フォルダ内に保存する。長いファイル名のままでいい。

ただしダウンロードするDLLファイルのバージョンを間違えないこと。

正しいバージョンをダウンロードするには、Windowsのコマンドラインで「php.exe -i」を実行、出力結果部分だけをコピーし、Xdebugの下記ページに貼り付け、「Analyse my phpinfo() output」ボタンをクリックする。

Xdebug: Support; Tailored Installation Instructions

すると正しいバージョンのダウンロードリンクが自動的に表示される。

(2) php.iniファイルの編集

php.iniファイルの冒頭に以下の内容を追記する。

zend_extension = C:\php\ext\php_xdebug-2.7.2-7.3-vc15-x86_64.dll
xdebug.remote_enable = 1
xdebug.remote_autostart = 1
xdebug.remote_host = 127.0.0.1
xdebug.remote_port = 9000

「zend_extension」の後のDLLファイルのフルパスは、自分がダウンロードしたDLLファイルのフルパスに適宜変更すること。その他はこのままコピペすればよい。

Webサーバなしでなのに、どうしてremote_hostやremote_portの指定が必要なのかと思うが、これらの記述がないとXdebugが動いてくれないので、何も考えずに記述すること。

ここまででXdebugが正しく動くかどうかは、コマンドラインプロンプトで先ほどの「php.exe -i」を再度実行し、以下のメッセージが表示されないことを確認すればよい。

Failed loading C:\php\ext\php_xdebug-2.x.x-x.x-vc15-x86_64.dll

(3) Visual Studio Codeに拡張機能 PHP Debug をインストール

Visual Studio Codeを起動、メニューの「表示>拡張機能」をクリック。

画面左上に「Marketplace で拡張機能を検索する」という入力欄が出てくるので「PHP Debug」と入力。緑色の「インストール」ボタンをクリックする。

ついでに「PHP IntelliSense」がインストールされていなければ、「PHP IntelliSense」と入力。同様に緑色の「インストール」ボタンをクリックしてインストールする。

(4) 編集するPHPファイルのあるフォルダを Visual Studio Codeで開く

筆者はここでつまずいた。PHPファイルを編集するんだから、そのPHPファイルを開けばいいと普通は思う。

しかしXdebugでデバッグするには、PHPファイルのあるフォルダを開く必要がある

Visual Studio Codeを起動したら、メニュー「ファイル>フォルダーを開く…」をクリックする。

そして編集したいPHPファイルのあるフォルダを開いて「フォルダーの選択」ボタンをクリックする。

その後、メニュー「表示>エクスプローラー」をクリックし、左側に選択したフォルダ内のファイル一覧が出てきたらOK。

本来、Visual Studio Codeはフォルダ単位(プロジェクト単位)でPHPをコーディングするもので、PHPファイルを単体でコーディングするものではないので、ファイルではなくフォルダーを開くのが正しい。

(5) 編集したいPHPファイルを開く

左に表示されたフォルダ内のファイル一覧で、編集したいPHPファイルをクリックすると、右側のエディター部分にPHPファイルの中身が表示される。

(6) launch.json ファイルを作成する

このlaunch.jsonファイルをどうやって作成すればいいのかが、どの記事にも書かれていなかった。

メニュー「デバッグ>構成を開く」をクリックすればいい。

すると開いているフォルダ内に「.vscode」というフォルダが自動作成され、その中にlaunch.jsonファイルが自動作成される。

そして自動作成されたlaunch.jsonがエディター画面に自動的に開く。

中身はだいたい以下のようになっているはず。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for XDebug",
            "type": "php",
            "request": "launch",
            "port": 9000
        },
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
        }
    ]
}

このうち後半の「Launch currently open script」の設定部分の「”port”: 9000」という行の直下に、次のような行を追加する。

"runtimeExecutable": "c:\\php\\php.exe"

runtimeExecutableというパラメータに、php.exeのフルパスを指定する。フルパスは自分の環境に合わせて正しく指定すること。

さらに、前半の「Listen for XDebug」のパラメータ設定部分をまるごと削除してしまう。

launch.jsonファイルの中身全体は以下のようになる。太字部分が追加した1行。

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Launch currently open script",
            "type": "php",
            "request": "launch",
            "program": "${file}",
            "cwd": "${fileDirname}",
            "port": 9000
            "runtimeExecutable": "c:\\php\\php.exe"
        }
    ]
}

編集したらメニュー「ファイル>保存」やCtrl + Sで保存し、このJSONファイルのタブは閉じてしまっていい。

(7) デバッグしてみる

以上で準備はととのったので、実際にデバッグしてみる。

何度も書くが、PHPファイルを単体で開くのではなく、あくまでメニュー「ファイル>フォルダを開く…」でフォルダを開くこと。

つまり左側に開いたフォルダ内のファイル一覧を表示できる状態にすること。(左上隅の書類のアイコンをクリックすると表示、非表示を切り替えられる)

そのファイル一覧からデバッグしたいPHPファイルを開く。

そして適当な場所にF9キーでブレークポイントを設定してみる。(行頭に赤丸が付く)

F5キーでデバッグ実行を開始する。(Ctrl + F5だとデバッグなしの単なる実行になる)

するとデバッグ実行の状態になり、F10やF11でステップ実行ができる。

上記で「launch.json」ファイルから「Listen for XDebug」のデバッグ構成部分を削除したのは、この構成ではステップ実行のデバッグができないため。

上記で削除しておいたので使えるデバッグ構成は「Launch currently open script」のみとなり、正しくステップ実行ができる。

ついにWebサーバなしでPHPのデバッグができるようになった。

(8) 他のフォルダにあるPHPファイルをデバッグする場合

ここまででお分かりのように、PHPファイルのあるフォルダ配下に「.vscode」というフォルダと、そのフォルダ内に上記の「launch.json」と同じ内容の「launch.json」ファイルが必要になる。

そのつど上記の手順で作成するのは面倒なので、「.vscode」フォルダごとコピペすればいい。

これでechoやログファイルへの書き出し結果を見ながらデバッグをする手間がなくなり、楽しくPHPをスクリプト言語として使える。

顔認識ウェブAPI「Face++」をPHPで使ってみる

無償で使える顔認識Webサービスがあることを最近知ったのでPHPの実装とともにメモ。

https://www.faceplusplus.com/

API KEY、API SECRETの取得方法はウェブで検索すれば見つかる。


define("REQUEST_URL", "https://api-us.faceplusplus.com/facepp/v3/detect");

// ローカルの画像をアップロードするためのパラメータに変換
$cfile = curl_file_create($local_imgpath, 'image/jpeg');

// return_attributesパラメータはカンマ区切りで複数指定できる。ここでは性別だけ。
// api_key, api_secretは自分で取得した文字列に置き換えること
$params = array(
'api_key' => 'xxxxxxxxxxxxxxxxxxxxxxxxxx',
'api_secret' => 'xxxxxxxxxxxxxxxxxxxxxxxxxxxx',
'image_file' => $cfile,
'return_attributes' => 'gender',
);

$curl = curl_init();
curl_setopt($curl, CURLOPT_POST, TRUE);
curl_setopt($curl, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data'));
curl_setopt($curl, CURLOPT_URL, REQUEST_URL);
curl_setopt($curl, CURLOPT_POSTFIELDS, $params);
curl_setopt($curl, CURLOPT_HEADER, 1);
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER , FALSE);
curl_setopt($curl, CURLOPT_RETURNTRANSFER , TRUE);
curl_setopt($curl, CURLOPT_TIMEOUT , 15);

$res1 = curl_exec($curl);
$res2 = curl_getinfo($curl);
curl_close($curl);

$json = substr($res1, $res2['header_size']);

// PHPの場合はJSONを連想配列に変換するとやりやすい
$face_data = json_decode($json, TRUE);

// これが検出された複数の顔のデータ
$faces = $face_data["faces"];

// 検出されたときだけ顔データを1つずつ見てみる
if (isset($faces)) {
foreach ($faces as $face) {

$gender = $face["attributes"]["gender"]["value"]; // 性別
$width = $face["face_rectangle"]["width"]; // 幅
$height = $face["face_rectangle"]["height"]; // 高さ
$top = $face["face_rectangle"]["top"]; // 上端
$left = $face["face_rectangle"]["left"]; // 左端

// デバッグのために検出された顔データを表示してみる
echo "DETECTED [$gender] $width x $height ($top, $left) ";

}
}

PHPでextensionなしの顔認識(処理速度はかなり遅め)

こちらの「Face detection in images using PHP」というページでPHPによるDLLなしの顔認識の方法が分かった

テキストデータを使ったPHP関数での顔認識なので処理速度は非常に遅いけれど、無いよりはまし、ということで、とりあえずダウンロード済みの大量のSNH48メンバーの中国ツイッター(新浪微博)のツイート画像の中から、人間の顔が大きめに写っているものを自動的に選別できるようになった。

しかしこの顔認識PHP関数、顔の認識は一つだけしかできない。

さらに、顔の位置をJSON形式ファイルで返すこともできるが、文字列が単引用符でくくられている。

PHPのjson_decode関数がデコードできるのは、文字列が二重引用符でくくられている「正しい」JSON形式ファイルだけなので、この顔認識PHP関数が返すJSON形式ファイルの単引用符を、わざわざ二重引用符に変換する必要があるという、ちょっと残念な仕様。

それでも手で一生懸命選別するよりは楽。