かきスタンプ

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

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 を取り外す、というやり方。

<input type="number"> は、凄く変な動きをするので、結局使わなかった話

※ 2020年 3月 9日時点の内容です
 
<ブラウザ>
Chrome : バージョン 80.0.3987.122

HTML5 で追加された、<input type="number"> の挙動が物凄い微妙だったので、結局使わなかった。
 
こういうの。
f:id:kakisoft:20200309014949p:plain

<input type="number">

数値のみを許可し、数値を上下させるボタンが付いている。

以下、その理由。

アルファベットの「e」が入力可能

パッと触ってみた感じ、数字しか入力できないように制御されているかと思いきや、アルファベットの e が入力できる。
指数の入力に対応したという事なのかもしれないが、嬉しい場面あるのか? これ。
ブラウザを使う大多数の人間は数学とは無縁の人だし、指数入力をする場面が多く存在するとは全く思えん。

つーか、「数値の入力のみを許可する」という仕様に対し、「e」が入力できたとしたら 99.9% バグ扱いされると思う。
「指数の入力に対応してます!」と言ったところで、「いや、そんなの使わねーから!」と却下されるんじゃないのか。

pattern が使えない

というわけで、アルファベットの「e」の入力を不許可にするべく、pattern で制御してしまおう。

<input type="number" pattern="^\d+$">

これで「e」の入力制限ができる・・・かと思いきや、input type="number" の時は、pattern はサポートされないらしい。
公式にもちゃんと書いてある。

何てこった。
という事で、こんな感じで対処。

<input type=number oninput="value=value.replace(/^\d/g, '')">

この時点でテンションがダダ下がり。
というか何でわざわざ正規表現を使って制御しなければならんのだ。開発者サイドでこういう気を回したく無いから使ってるのに。

小数の扱いが微妙

小数点がかなり適当に打ててしまう。
f:id:kakisoft:20200309015032p:plain
こんな感じで、先頭に小数点を入れたり、小数点を連続で入力できたり、末尾に数字を入れずに入力できたりする。
submit で弾けるとはいえ、こういう入力できるのはあんまりだ。
 
という事で、onchange で value を評価して、不正な値だったら整形・・・とやりたかったが、うまく動かない。
value をトレースすると、入力が「3.」なら valueは「3」となってたり、入力が「3..4」なら value は空白だったりと、小数点を取ることができなかったりする。
もう何を意図してそんな値にしたのか、さっぱり分からない。
 
解決するにはDOM操作でやらないといけないの? いやいや、そこまでして使いたく無いよ。

FireFox での挙動ががが

FireFox : バージョン 73.0.1
 
何と、全角数字の入力ができちゃうぜ! 数値だけじゃなくて日本語も入力可能だ!
一応、値はちゃんと取れるが、例のごとく pattern での入力制限ができない。

結論

<input type="number"> は、挙動が微妙すぎるんで、使わない方がいいんじゃないかな。

GitHub:【Windows】git config を編集したのに、別の人の名前で pushされる問題の解決方法

現在使っている端末にて、以前に使っている方の設定が残っていたので、自分用に git config を編集。

git config 変更

my-name、my-mailaddress@tekitou.com を、適当に読み替えてください。

git config --global user.name my-name
git config --global user.email my-mailaddress@tekitou.com

config内容確認

git config --list

設定変更OK。

が、push すると、なぜか以前のオーナーの名前で pushされている。
設定は変更済みなのに、何故?

そんな場合、Windowsに登録済みの資格情報が反映されている可能性があります。

コントロールパネル→資格情報マネージャーにて、「Web資格情報」もしくは「Windows資格情報」を確認してください。
f:id:kakisoft:20190905005516p:plain

f:id:kakisoft:20190905005544p:plain

前オーナーの資格情報を削除し、自分の名前とパスワードを登録。

MkDocs:インストールから github pages へのデプロイまで

MkDocsという、静的ページをサクッと作る事が出来るツールがあります。
以下、インストールから、GitHub Pagesまでアップロードする手順です。
 
githubのアカウントを「kakisoft」、githubリポジトリを「sample01」という名称でやってます。
必要に応じて、適宜読み替えてください。  

MKDocs をインストール(Windows の場合)

Chocolatey(パッケージマネージャー) を使用しています。
Chocolateyのインストールはこんな感じです。

choco install pip
pip install mkdocs

power shellでは上手く行かなかったんで、他の適当なコンソースアプリを使用してください。
私は、Cmderを愛用しています。

MKDocs をインストール(Cent OS の場合)

sudo yum install python-pip
sudo pip install pip --upgrade
sudo pip install mkdocs

MKDocs をインストール(Mac の場合)

sudo easy_install pip
sudo pip install pip --upgrade
sudo pip install mkdocs

sudo pip install mkdocs-windmill

ひな形を作成

mkdocs new sample01
cd sample01
mkdocs build
mkdocs serve

http://127.0.0.1:8000/ にアクセスすると、こんなページが表示されます。
f:id:kakisoft:20190831153745p:plain  

コンテンツの追加

docs フォルダに、拡張子が「.md」のファイルを追加します。(それ以外の拡張子は対象外となるようです。)
ブラウザのリロード不要で、修正した内容がリアルタイムに反映されます。

GitHub リポジトリに登録

アカウント: kakisoft
リポジトリ: sample01
にアップしています。必要に応じて、読み替えて下さい。
以下では、リポジトリは既に作成済みの状態です。

git init
git add .
git commit -m "first commit"
git push -u origin mastergit remote add origin https://github.com/kakisoft/sample01.git
git pull origin master

デプロイ

mkdocs gh-deploy

URLは、こんな感じになります。
https://kakisoft.github.io/sample01/

アカウント名、リポジトリ名を、適宜読み替えてください。
 
「gh-page」ブランチが自動で作成され、そのブランチが公開用のリポジトリとなります。
うまく表示されない場合、リポジトリの Setting にて、「GitHub Pages」が published となっているか確認してください。
 
f:id:kakisoft:20190831153806p:plain
 

作ったもの

こんなの作ってます。

人狼ゲーム用語集(英語)

https://kakisoft.github.io/WerewolfGameInEnglish/  
 

調べものをして、メモとして残しておきたい事を記録したり。

https://kakisoft.github.io/MiscellaneousDocs/