かきスタンプ

福岡でフリーランスの物流系のエンジニアやってます。

NVM for Windows を使ったけど Node.js のバージョンが切り替わらない! そんな時は、環境変数を見てみよう。

NVM for Windows を使うと、Windows 上で Node.js のバージョン管理ができるのですが、バージョンが切り替わらない現象に遭遇しました。
以下、その対策です。

NVM for Windows のインストール

Chocolatey(パッケージマネージャー)を使用しています。Chocolateyのインストール方法は、こちらでも。
ちなみに公式サイトはこちら

choco install nvm

別バージョンの Node.js をインストール

例:v13.7.0

nvm install v13.7.0

Node.js のバージョンを切り替え

例:v13.7.0

nvm use 13.7.0

これで Node.js のバージョンが切り替わってるはずが

λ node -v
v14.4.0

こんな感じで、マシンにインストールされている Node.js のバージョンが表示されました。

対策

環境変数が正常に設定されていない可能性があるので、設定し直します。

まず、コマンドプロンプトで「where nvm」と入力し、nvm のパスを調べます。
PowerShell には where コマンドは無いみたい)

C:\>where nvm
C:\ProgramData\nvm\nvm.exe

今回のケースの場合、「C:\ProgramData\nvm」を使用します。

システムの環境変数に、以下を追加します。

変数名 : NVM_HOME
変数値 : C:\ProgramData\nvm

続いて、コマンドプロンプトで「where node」と入力し、node.js のパスを調べます。

C:\>where node
C:\Program Files\nodejs\node.exe

今回のケースでは、「C:\Program Files\nodejs」を使用します。

システム環境変数に、以下を設定します。

変数名 : NVM_SYMLINK
変数値 : C:\Program Files\nodejs

こんな感じになります。
f:id:kakisoft:20200607113304j:plain

その後、環境変数の設定内容を反映させます。
(コンソールのウィンドウを開きなおす)

それでもバージョンが切り替わらない場合

公式サイトから配布されているインストーラを使用してください。
https://github.com/coreybutler/nvm-windows/releases/

nvm-setup.zip を選択し、「nvm-setup.exe」を起動してインストール。

f:id:kakisoft:20200607113316j:plain

こんなメッセージが出た場合は「はい」を選択します。
多分、この時に Node.js と上手い事やってくれてるんじゃないかと思います。

Laravel : $this->validate にて、カスタムメッセージを使用する

Laravel でバリデーションをする時、FormRequest を継承したクラスを定義しなくても、コントローラに以下のように書く事でバリデーションができます。

FormRequest を使うほどの汎用性もボリュームもない場合は、この方法でも良いのではないでしょうか。

    $this->validate(
        $request,
        [
            'title' => 'required|min:3',
            'body'  => 'required'
        ],
    );

エラーメッセージをカスタマイズしたい場合、フォームリクエストを使用したときは messages() メソッドにその内容を書いていくけど、この場合はどうすれば?
と思って調べてみた。

単に、validate の第2引数に、メッセージの内容を渡すだけでOKです。

    $this->validate(
        $request,
        [
            'title' => 'required|min:3',
            'body'  => 'required'
        ],
        [
            'title.required' => 'please enter title.',
            'body.required'  => 'please enter body.'
        ]
    );

Validatorファサードを使用する場合、こんな感じ。

      \Validator::make($request->all(),
          [
              'title' => 'required|min:3',
              'body' => 'required',
          ],
          [
              'title.required' => 'please enter title.',
              'body.required'  => 'please enter body.'
          ]
      )->validate();

PHP:JSON エンコードした時に「/」が「\/」になる挙動を回避

通常、json_encode した場合、「/」は「\/」にエスケープされます。

$array_data = [
    'message' => 'Please register as /regist_users',
];

echo json_encode($array_data);
//=> {"message":"Please register as \/regist_users"}

エスケープさせず、そのまま「/」を表示したい場合、JSON_UNESCAPED_SLASHES オプションを使います。

$array_data = [
    'message' => 'Please register as /regist_users',
];


echo json_encode($array_data, JSON_UNESCAPED_SLASHES);
//=> {"message":"Please register as /regist_users"}

 
 


<参考>
https://www.php.net/manual/ja/function.json-encode.php
https://www.php.net/manual/ja/json.constants.php

PHP:ファイルを読み込む関数の使い分け(file, fopen, readfile, file_get_contents)

PHP:ファイルを読み込む関数の使い分け(file, fopen, readfile, file_get_contents)

PHPでファイルを読み込むビルトイン関数は、結構色々あります。

  • file
  • fopen
  • readfile
  • file_get_contents

等。

以下の条件によって、使い分けをしていけばよいのではないでしょうか。

  • テキストか、バイナリか
  • ファイルサイズ
  • どんな使い方をするのか

という訳で、以下、各関数について。

file

https://www.php.net/manual/en/function.file.php

テキストファイル限定。(改行コードを区切り文字として使うため。)
すべてを変数(メモリ)に一旦貯めるので、あまりにも大きいファイルの使用には向かない。

ファイルの中身が配列になる。
改行区切りのテキストファイルを扱うのに適している。

使用例
// ファイルの内容を配列に取り込みます。
$file = file(__FILE__);

// 行単位で出力
foreach ($file as $lines => $line) {
    echo "Line #{$line_num} : " . htmlspecialchars($line);
}

fopen

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

テキスト・バイナリどちらでも使える。
ファイルの大小に関係なく使用可。

自身で色々制御する際に使う。

使用例
// ファイルを開く(戻り値は、FilePointer と呼ばれる特殊な変数)
$handle = fopen(__FILE__, "r");  // readonly

// ファイル内容を出力
while ($line = fgets($handle)) {
  echo $line;
}
// ファイルポインタをクローズ
fclose($handle);

readfile

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

テキスト・バイナリどちらでも使える。
巨大なファイルでも使用可。(詳細は上記リンクを参照)

ファイルの中身をそのまま表示する。
何かしらの制御を加えたいなら、別のを使った方がいいかも。

使用例
readfile(__FILE__);     // コンソールに、このファイルの内容が出てくる

file_get_contens

https://www.php.net/manual/ja/function.file-get-contents.php

テキスト・バイナリどちらでも使える。
file と同じ理由で、あまりにも大きいファイルの使用には向かない。

使用例
$current = file_get_contents(__FILE__);

print_r($current);

引数に URLを使用すると、GETリクエストとして使用可。
というか、そっちの使い方しかしてない人も多いかもしんない。
パラメータ次第で PUTにする・パラメータを渡す・SSLエラーを無視する、といった HTTPリクエストライブラリと同様に使う事が出来なくはない。

その他

xml ファイルを読むときは simplexml_load_file を、
ini ファイルを読むとき parse_ini_file を使えばいいんじゃないかと思います。

間違ってたら、ご指摘いただけると助かります。

VSCode、Laravel : Undefined type 'Route' のエラーメッセージを消す方法

Visual Studio CodePHP IntelliSense プラグインを入れて Laravel を触ってると、下部に赤線が入って、こんなエラーメッセージが発生する。
(2020年 4月時点)

f:id:kakisoft:20200502214230p:plain

Undefined type 'Route' . Intephense

設定変更でエラーメッセージを消す事ができます。

ー1ー

プラグインPHP IntelliSense」表示し、「Extention Setting」 を選択。
f:id:kakisoft:20200502214319p:plain

ー2ー

入力欄に、「 intelephense.diagnostics.undefinedTypes 」と入力。
チェックを OFF にする。
f:id:kakisoft:20200502214340p:plain

ー3ー

Visual Studio Code を再起動。
こんな感じで、エラーメッセージが消えます。
f:id:kakisoft:20200502214355p:plain


<参考サイト>
https://github.com/bmewburn/vscode-intelephense/issues/780

PHP:エルビス演算子【(expr1) ? (expr2) : (expr3) 】と、Null合体演算子【(expr1) ?? (expr2)】は、「??」を使った方が無難かも。

とてもよく似ている以下の2つの演算子

主な違いは以下の点でしょうか。

  • ? は、「0」「"0"」「空の配列」を false と判定し、右辺の値を返す
  • ?? は、「0」「"0"」「空の配列」を true と判定し、その値を返す

0 や "0" を、「値がセットされていない状態」として扱うかどうかはシステムによって変わってくると思うので、これらを初期値に置き換えない Null合体演算子(??)を使った方が、予期せぬ不具合を起こしにくいのでは?
という話。
 
以下、構文の説明と実行結果。
PHP ver 7.1.32 で実行しています。

エルビス演算子

https://www.php.net/manual/ja/language.operators.comparison.php#language.operators.comparison.ternary

(expr1) ? (expr2) : (expr3)
 
expr1 が TRUE の場合に expr2 を、 expr1 が FALSE の場合に expr3 を値とする。
 
式 expr1 ?: expr3 の結果は、expr1 が TRUE と同等の場合は expr1、 それ以外の場合は expr3 となります。

実行結果

var_dump(     "a" ? "a"     : "not_exists" );  //=> "a"
var_dump(     "0" ? "0"     : "not_exists" );  //=> "not_exists"
var_dump(   "0.0" ? "0.0"   : "not_exists" );  //=> "0.0"
var_dump(  "0x00" ? "0x00"  : "not_exists" );  //=> "0x00"
var_dump(       0 ? 0       : "not_exists" );  //=> "not_exists"
var_dump(     0.0 ? 0.0     : "not_exists" );  //=> "not_exists"
var_dump(    0x00 ? 0x00    : "not_exists" );  //=> "not_exists"
var_dump( array() ? array() : "not_exists" );  //=> "not_exists"
var_dump(    NULL ? NULL    : "not_exists" );  //=> "not_exists"
var_dump(   FALSE ? FALSE   : "not_exists" );  //=> "not_exists"
var_dump( $undefined_variable ? $undefined_variable : 'not_exists' );  //=> "not_exists"  ※Noticeが出る

"0" は false で、"0.0" が true というのが、何だかややこしい。

Null 合体演算子(7~)

https://www.php.net/manual/ja/language.operators.comparison.php#language.operators.comparison.coalesce

式 (expr1) ?? (expr2) は、
expr1 が NULL である場合は expr2 と評価され、
それ以外の場合は expr1 と評価されます。

実行結果

var_dump(     "a" ?? "not_exists" );  //=> "a"
var_dump(     "0" ?? "not_exists" );  //=> "0"
var_dump(   "0.0" ?? "not_exists" );  //=> "0.0"
var_dump(  "0x00" ?? "not_exists" );  //=> "0x00"
var_dump(       0 ?? "not_exists" );  //=> 0
var_dump(     0.0 ?? "not_exists" );  //=> 0
var_dump(    0x00 ?? "not_exists" );  //=> 0
var_dump( array() ?? "not_exists" );  //=> array(0) {}
var_dump(    NULL ?? "not_exists" );  //=> "not_exists"
var_dump(   FALSE ?? "not_exists" );  //=> "not_exists"
var_dump( $undefined_variable  ?? "not_exists" );  //=> "not_exists"  ※Noticeが出ない

こっちは "0" も "0.0" も true。

jQuery:無効化したセレクトボックスの値を送信する方法

深淵な事情があり、

「セレクトボックスで表示している内容があるが、その項目はユーザから直接操作できないようにする。その部分をテキストボックス(ReadOnly)とかに置き換えると影響範囲がめっさ広がるんで、部品を変えずに何とかする。」

というロジックを入れる事になった。

セレクトボックスには ReadOnly属性が無いな。どうするべ。
と悩んで、取った手段がこんな感じ。

実装

「セレクトボックスのイベントを発生させない」という方法で対処しました。

HTML
<select id="my-select-01">
    <option>value01</option>
    <option>value02</option>
    <option>value03</option>
</select>

<input type="submit" id="my-submit-01">
JavaScript
jQuery(document).ready(function($) {

    $('#my-select-01').on('selectstart', false)
    $('#my-select-01').on('contextmenu', false)
    $('#my-select-01').on('keydown', false)
    $('#my-select-01').on('mousedown', false);

}

セレクトボックスを押しても選択内容を表示しないように、イベントをキャンセル。

上記のような問題を解決してくれるプラグインがあるみたいですが、やってる事は結局上記で書いてるような事なので、
「使うはどうせここだけだし、わざわざプラグインとして追加するほどの事でもなくね?」と思って、この方法にした。

<参考サイト>

セレクトボックスを変更できないよう固定してかつ値も送信するjQueryプラグイン
query-selection


没案

「セレクトボックスを無効化し、送信直前に有効化」
という方法を最初に考えたのですが、最終的には不採用となりました。
理由は、IE では上手く動かなかったため。
 
念のため、書いとく。

HTML
<select id="my-select-01" disabled>
    <option>value01</option>
    <option>value02</option>
    <option>value03</option>
</select>

<input type="submit" id="my-submit-01">
JavaScript
    // 送信時にセレクトボックスを有効化する
    $("#my-submit-01").on('click', function() {
        $("#my-select-01").prop("disabled", false);
    });

disabled にして操作を無効化。
そのままだと値が submit されないので、送信直前に disabled を取り外す、というやり方。