エンジニアのひよこ_level10

毎日更新してた人。たまに記事書きます。

【PHP】クラスに定義した定数名と値を全て取得したいとき【766日目】

定数を全て確認したい

class Items
{
  const MAX_COUNT = 5;
  const ITEM_NAME = 'Hoge';
}

こんなふうにクラスがあって、

php > var_dump(Items::MAX_COUNT);
int(5)

こんなふうに値が取れる。

でも、『どんな定数名が存在するか』とか、『全部定数がほしい』ってときにどうするか

ReflectionClassとgetConstantsを使う

php > $item = new ReflectionClass(Items::class);
php > var_dump($item->getConstants());
array(2) {
  ["MAX_COUNT"]=>
  int(5)
  ["ITEM_NAME"]=>
  string(4) "Hoge"
}

ReflectionClass経由で、getConstantsを起動すると、このようにキーと値が出てきます。

公式ドキュメント

https://www.php.net/manual/ja/reflectionclass.getconstants.php

【うっかり】'', "", 文字列の罠【763日目】

うっかり

うっかり簡単なミスをしてしまう。

誤字、かっこの数、閉じタグ忘れ等々・・・

ケアレスミスこそ、間違いに気が付きにくい。
故に修正に時間がかかる。

そんなケアレスミスも、パターンを覚えておくと、比較的気づきやすい。

ってことで、ケアレスミスの共有をしようという記事です。

うっかり文字列

func_name('ClassName::PARAM');

お気づきでしょうか。

これ、定数を取得ができません。

func_name(ClassName::PARAM);

''がついて、文字列として扱われていましたね( ;∀;)

エディタで色が変わってるのに、焦っている私は気が付きませんでした・・・( ;∀;)

【PHP】constの定数名を動的に変更して取得したい【761日目】

定数を定義した

class ClassName
{
    const PARAM_1 = 'a';
    const PARAM_2 = 'b';
}

でも、こんなふうに数値だけ差がある定数。

for ($i = 1;  $i <= 2; $i++) {
    $array[] = ClassName::PARAM_.$i;
}

みたいに定数を動的に取得をしたい。でも、この書き方は動かない。
どうするか。

constant関数を使う

定数を取得する関数constantを使う。

引数は文字列なので、文字列結合した結果を渡してやると良い。

for ($i = 1;  $i <= 2; $i++) {
    $array[] = constant('ClassName::PARAM_' . $i);
}

こんな感じ。

公式ドキュメント

https://www.php.net/manual/ja/function.constant.php

if ($x == 3 || $x == 7 ||... のような特定の値の条件分岐を短く書く【753日目】

特定の数値だけ条件分岐したい

if ($x === 3
    ||  $x === 5
    ||  $x === 10
    ||  $x === 12
    ||  $x === 17
    ||  $x === 21
    ||  $x === 22
    ||  $x === 28
) {

}

こんなふうに、特定の条件で分岐したい。

ただ、見づらい。配列使って書き換えてみる

in_arrayを使ってみる

$array = [3, 5, 10, 12, 17, 21, 22, 28];

if (in_array($x, $array, true)) {

}

少し見やすくなった。

速度は不明

ただ、速度とかは不明です。

正直、もっといいやり方もあるかもです。あったら、教えていただけると嬉しいです。

【phpunit】xdebugじゃ重いテストコードを、早くする【752日目】

テストコードが遅い

テストコードが重い、遅い、辛い(´・ω・`)

xdebugを使ってテストコードを走らせると、遅い、重いと感じるときがあります。

でも、カバレッジを取りたい。そんなとき

phpdbgを経由して動かす

(xdebugは切っても大丈夫です)

phpdbg -qrr vendor/bin/phpunit tests/Unit/App/Services/ --coverage-html coverage_html

これで、phpdbgを経由してテストコードを動かしてカバレッジが取れます。

難点:メモリ

難点としては、メモリをめっちゃ食います。

全テストを回すとかだと、メモリが圧迫して動かないときもあるので、少しのテストコードを回すとかに使うと良さそうです。

【phpunit】テストコードを書いていないクラスを特定する【750日目】

テストコードを新しく導入したい

テストコードを今まで書いてなかった。
なので、テストコードを少しずつ導入していった。

すると気になってくる。『どこまで書いたっけ』

なので、テストコードをどこまで書いたかを特定したい。

カバレッジ取る

単純にカバレッジを取ることで解決する。
コードを書いていないファイルは、0%と書かれているはずなので、特定出来ますね。

phpunit --coverage-html path/to/output

path/to/outputディレクトリの中にhtmlファイルやcss等がいっぱい生成される。

なので、好きなパスに変えて実行させてください。

注意点

1. 実行遅くなるよ
2. 動かしたテストコードの範囲だけで判定するよ
3. xdebug、pcov、phpdbgなどがないと動かないよ

ただ、一度確認するだけだから、遅いのはここぞというときに動かすという対応でいいと思いますφ(・

phpunitで、factoryが動かない時があった話(環境や運で変わった)【741日目】

phpunitでテスト書いてた

いい感じに動いてるので、CircleCIで自動的にテストをチェックしようってことになった。

すると、動かない。動くんだけど、たまに動かない。

調べていくと、factoryがたまにうまく初期値を設定してくれてないっぽい。
毎回じゃなく、たまになので再現できず困った。

<?php

$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
    return [
        'id'                  => $faker->randomNumber(),
    ];
});

こんなときに、idのデータがないと言われるやつ。

何があったか

複数定義してた

<?php

$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
    return [
        'id'                  => $faker->randomNumber(),
    ];
});

<?php

$factory->define(App\Models\User::class, function (Faker\Generator $faker) {
    return [
    ];
});

たまに下が動いて、初期値がないクラスが作成されていた。

多重定義には気をつけようねってお話でした。

phpunitが凄く遅い→xdebugが動いていた【740日目】

自動テストが遅い

vendor/bin/phpunit tests/Unit/App

いつもどおり、自動テストを走らせてました。

いつも一個のテスト辺り1秒くらいかかっている。全部走らせると30分くらいかかる。
これはおかしいなと思った。

結論

xdebugが動いていた

xdebug、今回使っていないので消します。

xdebugの位置

php.iniファイルの該当する記述を消しましょう

php --ini

でパスを検索。見つけたので、書き換え。 vi /usr/local/etc/php/php-cli.ini。環境によってパスが違うので注意。

zend_extension=xdebug.so

この項目が邪魔なのでコメントアウト(左にセミコロン)

;zend_extension=xdebug.so

結果

30倍くらい早くなりました。1分で全部のテスト通った・・・

あまりに遅すぎる場合は、xdebug疑ってみてくださいな。