PHPで総数がわからない標準入力を受け取るやり方

総数が分からない標準入力を受け取るときどうすればよいのか調べた。
whileの条件にfgetsを書くやり方ができないか調べたが、
現時点では見当たらなかったので、このやり方を使おうと思う。

PHP 5.6.28で確認。

$line = trim(fgets(STDIN));

while ($line) {
    $array[] = $line;
    $line = trim(fgets(STDIN));
}
var_dump($array);

PHPで標準入力から改行を取り除くのは、trimで十分だった

PHPの標準入力を使っていた時、以下のようにしていた。

preg_replace('/\r\n|\r|\n/', '', fgets(STDIN));

しかし、ネット上を見ていると、trimを使っていた。
PHPのマニュアルを調べると、trimには以下のように書いてあった。

この関数は str の最初および最後から空白文字を取り除き、 取り除かれた文字列を返します。2番目のパラメータを指定しない場合、 trim()は以下の文字を削除します。

” ” (ASCII 32 (0x20)), 通常の空白。
“\t” (ASCII 9 (0x09)), タブ。
“\n” (ASCII 10 (0x0A)), リターン。
“\r” (ASCII 13 (0x0D)), 改行。
“\0” (ASCII 0 (0x00)), NULバイト
“\x0B” (ASCII 11 (0x0B)), 垂直タブ

実際に試してみると、改行が取り除かれていることがわかる。
PHP 5.6.28で確認した。

$test = fgets(STDIN);
var_dump($test);
// 結果
// string(3) "3
// "

$test = trim(fgets(STDIN));
var_dump($test);
// 結果
// 3
// string(1) "3"

$test = preg_replace('/\r\n|\r|\n/', '', fgets(STDIN));
var_dump($test);
// 結果
// 3
// string(1) "3"

ショートカットキーでブラウザのタブを移動する

たまたま、ネット検索をしていて、発見したショートカットキー。
Ctrl + 数字(1~9)

Ctrl + 1~8は、左からn番目のタブに移動する。
例えば、Ctrl + 4なら左から4番目のタブに移動する。
Ctrl + 9は、9番目ではなくて、一番右のタブに移動する。

なお、Ctrl + Tabで右タブに1つ移動。Ctrl + Shift + Tabで左タブに1つ移動。

以下のバージョンで確認した。
Chrome:58.0.3029.110
Internet Explorer:11.0.9600.18666
Firefox:53.0.2

CakePHP3のチュートリアルでパスワードのハッシュ設定をおこなう

CakePHP3のチュートリアルの続きを進めようとしたら、パスワードハッシュの設定をしていないとだめということがわかった。
以前実施したチュートリアルのファイルを使って、パスワードのハッシュ設定を行う。
パスワードハッシュを追加

パスワードハッシュの設定を行わないときは、データベースのパスワードカラムは、入力したままになる。

+---------+
| password|
+---------+
| hogehoge|

チュートリアルに従って、src/Model/Entity/User.phpを修正する。

use Cake\Auth\DefaultPasswordHasher;    // 追加
class User extends Entity
{
    // _setPasswordを追加
    protected function _setPassword($value)
    {
        $hasher = new DefaultPasswordHasher();
        return $hasher->hash($value);
    }
}

追加した後、パスワードの変更を実施すると、passwordカラムのデータベースの値が以下のようにハッシュ化されていることがわかる。

| password                                                                                                 |
| $2y$10$/s64/11iCVMNjI62i1RZfOhgfYdIvNCTFvUcXhABxoRplH1dtVZwq | 2017-05-14 10:21:49 | 2017-05-14 10:44:16 |

CakePHPのバージョン3.3.16で確認した。

PHPで大文字、小文字が混在するときがある場合の比較

大文字、小文字が混在するときがある場合の比較に関して残しておく。
以下の例だと、最初のif文ではJとjに差異があるためfalseになってしまう。

そこで、すべて小文字にするstrtolowerか、すべて大文字にするstrtoupperを用いる。
そうすることで、文字列を小文字か大文字に統一することができるので、大文字小文字を意識しないで済む。

$str = 'Jpg';

if($str == 'jpg') {
    echo 'jpg is true' . PHP_EOL;
}

if(strtolower($str) == 'jpg') {
    echo 'jpg is true' . PHP_EOL;
}

if(strtoupper($str) == 'JPG') {
    echo 'JPG is true' . PHP_EOL;
}

バージョン:5.6.28で確認。

PHPの小数点の扱い方

小数点の計算をするときに失敗してしまったので、残しておく。
除算と剰余、round、floor、ceil関数を使ったときの結果は以下の通り。

// 除算
echo 17 / 3 . PHP_EOL;              // 5.6666666666667
// 剰余
echo 17 % 3 . PHP_EOL;              // 2
// round
echo round(17 / 3, 0) . PHP_EOL;    // 6
echo round(17 / 3, 2) . PHP_EOL;    // 5.67
// floor
echo floor(17 / 3) . PHP_EOL;       // 5
// ceil
echo ceil(17 / 3) . PHP_EOL;        // 6

除算だけだと、数値によって小数点が発生する。
剰余は、除算したときの余りを求める。
round関数は、第二引数に丸める対象の小数点第n位を指定する。
floor関数は、小数点以下を切り捨てる。
ceil関数は、小数点以下を切り上げる。

バージョン:5.6.28で確認。

連想配列であとで要素を追加する

条件によって、連想配列のデータに共通部分、異なる部分があるとき。
以下の場合、Key1からKey4が共通で、$fooがtrueの時のみKey5,Key6も含めたい。

if($foo == true) {
    $array = [
        'Key11' => 'Value1',
        'Key12' => 'Value2',
        'Key13' => 'Value3',
        'Key14' => 'Value4',
        'Key15' => 'Value5',
        'Key16' => 'Value6',
    ];
} else {
    $array = [
        'Key11' => 'Value1',
        'Key12' => 'Value2',
        'Key13' => 'Value3',
        'Key14' => 'Value4',
    ];
}

そのとき、以下のように書いてしまうと、上書きされてしまう。

if($foo == true) {
    $array = [
        'Key15' => 'Value5',
        'Key16' => 'Value6',
    ];
}
$array = [
    'Key11' => 'Value1',
    'Key12' => 'Value2',
    'Key13' => 'Value3',
    'Key14' => 'Value4',
];
// $arrayのvar_dump出力結果
// array(4) {
//   ["Key11"]=>
//   string(6) "Value1"
//   ["Key12"]=>
//   string(6) "Value2"
//   ["Key13"]=>
//   string(6) "Value3"
//   ["Key14"]=>
//   string(6) "Value4"
// }

そこで、array_merge関数を使ってマージを行うことにより、上書きしないで追記ができる。
バージョン:5.6.28で確認。

if($foo == true) {
    $array = [
        'Key15' => 'Value5',
        'Key16' => 'Value6',
    ];
}
$array = array_merge($array, [
    'Key11' => 'Value1',
    'Key12' => 'Value2',
    'Key13' => 'Value3',
    'Key14' => 'Value4',
]);
// $arrayのvar_dump出力結果
// array(6) {
//   ["Key15"]=>
//   string(6) "Value5"
//   ["Key16"]=>
//   string(6) "Value6"
//   ["Key11"]=>
//   string(6) "Value1"
//   ["Key12"]=>
//   string(6) "Value2"
//   ["Key13"]=>
//   string(6) "Value3"
//   ["Key14"]=>
//   string(6) "Value4"
// }

PHPで配列を[ ]括弧で渡せることを知らなかった

PHPのコードを見ていた時に、

hoge([$foo]);

というコードを見つけた。
バグかと思ったら、配列として渡しているので問題なかった。
たまたま、配列として受け取る関数に、1つだけ渡していたため認識できなかった。

以下のコードで確認したところ、正常に動くことを確認した。
確認したバージョン:5.6.28

echoTest(array('Oda', 'Toyotomi', 'Tokugawa'));
echoTest(['Oda', 'Toyotomi', 'Tokugawa']);

function echoTest($array)
{
    foreach($array as $value){
        echo $value . PHP_EOL;
    }
}
// 出力結果はどちらも以下になる。
// Oda
// Toyotomi
// Tokugawa

PHPのisset()の結果は、true/falseと比較するのか、しないのか

戻り値がbooleanで返ってくる関数をif文で判定するときに、
true/falseと比較するのが良いのか、比較しないのが良いのかわからなくなってきた。

最初は、booleanで返ってくるのだからtrue/falseと比較する必要はないと考えていた。
しかし、比較する方にもメリットがあるように感じるようになった。

予想としては、以下だと思う。
比較するメリット
trueかfalseとの比較が書いてあるので、ソースコードを読むときにわかりやすい。

// true/falseと比較する
if(isset($hoge) == true){
if(isset($hoge) == false){

比較しないメリット
余計なコードを書かなくて良い。

// true/falseと比較しない
if(isset($hoge)){
if(!isset($hoge)){

そこで、色々調べてみた結果、比較しない方コードが多かった。
なので、比較しないコードを書く方が良いようだ。

PHPのマニュアル:isset関数のページを見たところ、比較していないコードで書かれていた。
stackoverflow:検索した結果、多くが比較していないコードで書かれていた。
XAMPP内のPHPライブラリ:grepした結果、比較していないコードで書かれていた。

PHPで配列から最大値、最小値を取得する。

PHPで配列に入っている数値から最大値、最小値を取得する。
max関数、min関数を使う。

確認に使用したバージョン
PHP:5.6.28

$numbers = array(1, 3, 5, 7, 11, 13, 17);
echo max($numbers) . PHP_EOL; // 最大値は、17
echo min($numbers) . PHP_EOL; // 最小値は、1