お知らせ

現在サイトのリニューアル作業中のため、全体的にページの表示が乱れています。

VSCodeでは出来たことがPhpStormだと上手く出来なかったので、その解消法です
Remote Developmentに慣れてるとハマりやすいと思います
PhpStormに類似の機能は多分ないです

PhpStorm編

確認環境

一応Apacheの上に乗っかったLaravelで確認してますがそこらへんの環境情報は端折ってます

Env Ver
Windows 11 Pro
PhpStorm 2021.3.2
Docker 20.10.11
docker-compose 1.29.2
PHP 8.1.1
Xdebug 3.1.3

Dockerfile

PHPが入ってるDockerfileに以下を追記
出来ることならヒアドキュメントで書きたい

RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.client_host=host.docker.internal" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

Dockerの設定

適当にDockerを追加してコンテナとローカルのパスをマッピング

20220412031939.png

PHPインタプリタの設定

CLIインタプリタをDockerに向けて設定します
パスマッピングは勝手にやってくれた気がする

20220412031948.png

デバッグ

HTTPリクエスト

受話器みたいなところを押してcurlなりPOSTMANなりブラウザなりにXDEBUG_TRIGGER=StartProfileForMeというCookieを刺してリクエストするとブレークにかかります
初回だけパスマッピングを構成するダイアログが出てくるのでよしなに処理します

20220412031956.png

PHPUnit

デバッグ構成を作ってデバッグするだけ

20220412032006.png

おまけのVSCode編

VSCodeだとネイティブに動くのでDockerの存在を考えなくて済むのは楽ですが、IDEとしての性能はPHP Intelephenseに課金してもPhpStormには劣るので微妙なところ(静的解析に問題がある

確認環境

PhpStormと被る部分は端折ってます

Env Ver
VSCode 1.64.2
ms-vscode-remote.remote-containers 0.217.4
robberphex.php-debug 1.14.0

Dockerfile

PHPが入ってるDockerfileに以下を追記
PhpStormとの違いはxdebug.client_hostが不要なところです
(PhpStormでもCLI Debugだとなくていけるっぽいのでややこしい)

RUN pecl install xdebug
RUN docker-php-ext-enable xdebug
RUN echo "zend_extension=xdebug" > /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.mode=develop,coverage,debug,trace" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.start_with_request=trigger" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini
RUN echo "xdebug.trigger_value=StartProfileForMe" >> /usr/local/etc/php/conf.d/docker-php-ext-xdebug.ini

launch.json

  • Listen for Xdebug
    • HTTPリクエスト用
  • PHPUnit
    • PHPUnit用
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003
        },
        {
            "name": "PHPUnit",
            "type": "php",
            "request": "launch",
            "program": "${workspaceFolder}/vendor/phpunit/phpunit/phpunit",
            "args": ["${file}"],
            "env": {
                "XDEBUG_TRIGGER": "StartProfileForMe"
            },
            "port": 9003
        }
    ]
}

デバッグ

PHPのいるコンテナにAttach Visual Studio CodeしてF5押せばデバッグできます

あとがき

個人的に操作感はVSCodeの方が好みなので使えるならVSCodeでいきたいのですが、今の所PhpStormには敵わないという感じなのが悲しい
まぁJS/TS用のエディタみたいなもんだし仕方がないですね…
ただGitのGUI周りはVSCodeが圧倒的に好みなので、Git操作するときだけVSCode使ってたりはします
しかしPhpStormとVSCodeを共存させるのはxdebug.client_hostの向きの関係で微妙な感じですね…

投稿日:
言語::TypeScriptジャンル::調査

TypeScriptをぼちぼちやってきた中で、型推論が素直に決まらないみたいな所が出てきたので書き置きとして残しておきます
具体的には何かしらの関数を通して処理を隠蔽すると上手くいかなくなるケースがあります

型が推論されないケース

検査関数的なものを通した場合に、後続処理で期待通り型が推論されなくなるケースです

その1

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
};

const required = (val: string) => {
  return val === '';
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
};

if (required(input.value)) {
  input.error = 'ERR';
  console.error(input.error);
} else {
  // ここでは input.value は 'hoge' | 'piyo' となるはずだが
  // TSC は 'hoge' | 'piyo' | '' と解釈する
  registerHogePiyo(input.value);
}

その 2

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
  hasError: boolean;
};

const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
  if (obj.value === '') {
    return { value: '', error: '必須入力です', hasError: true };
  } else {
    return { value: obj.value, error: '', hasError: false };
  }
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
  hasError: false,
};

const result = required(input);
if (result.hasError) {
  console.error(result.error);
} else {
  // ここでは input.value は 'hoge' | 'piyo' となるはずだが
  // TSC は 'hoge' | 'piyo' | '' と解釈する
  registerHogePiyo(result.value);
}

export {};

型を推論されるようにしたケース

オブジェクトに型判定用のプロパティを生やしasで型を明示することでクリアしています

type HogePiyo = 'hoge' | 'piyo';

type InputProps<ValueT> = {
  value: ValueT;
  error: string;
  hasError: boolean;
};

const required = <ValueT>(obj: InputProps<ValueT | ''>) => {
  if (obj.value === '') {
    return { value: '', error: '必須入力です', hasError: true } as {
      value: '';
      error: string;
      hasError: true;
    };
  } else {
    return { value: obj.value, error: '', hasError: false } as {
      value: ValueT;
      error: string;
      hasError: false;
    };
  }
};

const registerHogePiyo = (value: HogePiyo) => {
  console.log('register', value);
};

const input: InputProps<HogePiyo | ''> = {
  value: '',
  error: '',
  hasError: false,
};

const result = required(input);
if (result.hasError) {
  console.error(input.error);
} else {
  registerHogePiyo(result.value);
}

export {};

あとがき

  • Assertion Functionsを使う方法もあると思いますが、何も考えずAssertion Functionsを書くと次のような弊害があり、積極的に採用しづらいと考えています
    • 何もしていなければ基本的にバンドル後のソースコードに出てくる
      • 要するにバンドルサイズが大きくなります
    • throwを書く必要性があり、バンドル後に残っている以上、このthrowcatchする必要性がある
      • 無意味な実装工数が生まれる
    • そもそも論としてAssertion Functionsを書く工数が生まれる
    • Assertion Functionsの振る舞いを見ている限り、asに限りなく近く、ぶっちゃけasで書いたほうが楽
  • 絶対にasを使わず現実的な工数で開発するというのは、割と非現実ではないかという感触があります
    • 個人的に型推論はIDEが勝手にやってくれるおかげで楽ができるシステムだと考えているので、型推論の補佐をする仕組みに工数をかけるというのは本末転倒な気がしています
  • 品質は大切なことですが、反面で少なくないビジネスには期限もあります
    • 品質に寄せすぎた過剰に冗長なコードも、納期に寄せすぎた脆弱性不具合山盛りスパゲティコードもどちらも考えものであり、その辺のバランスが上手くとれるやり方がなんかないかなーと考えることはしばしばあります
投稿日:
言語::PHP::XdebugOS::Windowsソフトウェア::VSCode

環境

Windows 10

Env Ver
PHP 8.0.2
Xdebug 3.0.2

php.ini

zend_extension="xdebug-3.0.2-8.0-vs16-nts-x86_64"
xdebug.start_with_request=yes
xdebug.mode=debug

settings.json

別になくてもデバッグは出来る

"php.validate.executablePath": "C:/path/to/php.exe",

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Listen for Xdebug",
            "type": "php",
            "request": "launch",
            "port": 9003
        }
    ]
}