エンジニアのひよこ_level10

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

【PHP】フレームワーク使わずルーティングしたかった【144日目】

前提・ゴール

nginx等で、強制的にindex.phpを読み込ませる

index.phpから、URIに合わせて、別ファイルを読み込ませるのをゴール

手順

URIを取得

②クエリと分ける

URIに合わせてinclueするファイル分ける

書いたコード

index.php(①と②を担当)

<?php
$uri = $_SERVER['REQUEST_URI'];
$query = $_SERVER['QUERY_STRING'];
$uri = str_replace('?' . $query, '', $uri);

include 'route/route.php';

route.php

<?php
if ($uri === '/hogehoge') {
    include 'answer/hogehoge.php';
} else if ($uri === '/hugahuga') {
    include 'answer/hugahuga.php';
} else {
    include 'answer/other.php';
}

悩み

includeでファイル見つからなかった時の対応書けてない

そもそもinclude、require以外でルーティング実装する方法思いつかなかった

どなたかアドバイスいただけたら嬉しいです。
こんなものなのかなぁ・・・

laravelの環境構築で参考にしたサイト一覧【125日目】

基本形

qiita.com

Nginx + php-fpmの環境を作ろうとしたらPHPファイルがダウンロードされる

utano.jp

mcryptをphp7.2でもインストールする方法

blog.apar.jp

ぼやき

とりあえずわからないところは極力削って環境構築。

わからないままコピペよくない。

一応手元でLaravelの基本ページを表示出来るとこまでいけました。

さて、切りが良いので次はGoの勉強に戻ります。また落ち着いたらLaravelでてきとーなサイトをECS使いながら公開するとこまで行きたいところ。

動作が落ち着いたらgithubで公開しますね。

php7.2でmcryptがインストールできない問題【124日目】

Dockerやってたらmcryptがインストールできない

なんでだーってなった。

コマンド間違えてないはずなのに、

/usr/src/php/ext/mcrypt does not exist

って出る。なぜだ。

でもきっと私の記述が間違ってるんだ・・・

そう思ってた

mcryptはPHP7.1で非推奨、7.2で消えました

PHP: はじめに - Manual

This feature was DEPRECATED in PHP 7.1.0, and REMOVED in PHP 7.2.0.

あっ・・・
ってことで、php7.2ではmcrypt消されてるやつですね。

この拡張モジュールは » PECL レポジトリに移動 されており

ってことで、必要な方はPECL使ってインストールしてくださいとのこと。

一応非推奨ですが。

オモイコミ、ダメ、ゼッタイ

完全に私の記述がきっと間違えてるんだろうって思いながら検索ワード入れてたから、
全然見つかりませんでした・・・

エラーメッセージで検索しても、コマンドの順番違うよとか書いてて、
いや、間違えてないはずなのに・・・って思いながら書いてました。
こんなのに2時間かけるとか・・・

ってことで、オモイコミ、ダメ、ゼッタイ。

おまけ:初心者がDockerを勉強した本

■対象の人:環境構築わからない・・・インフラ用語わからない・・・

プログラム書けるけど、インフラ用語わからない、環境構築してみたいけどできない。

私がそうでしたが、以下の本で勉強しました。

インフラの用語を一から説明してくれて、その後にDockerの話をしてくれるので初心者向けです。
Laravelの環境くらいなら、一人で書けるようになりました。

アフィリエイトリンク貼ると、胡散臭くなるけど、単純におすすめしたい本(`・ω・´)ゞ

疑似乱数を、再現可能な値にする方法【120日目】

何が嬉しいの?

擬似乱数を再現可能にすると、
バグとかの再現も出来る。

ドキュメント

PHP: mt_srand - Manual

PHP: mt_rand - Manual

結論

$seed = 10;
mt_srand($seed);
echo mt_rand(0, 255);
echo mt_rand(0, 255);
echo mt_rand(0, 255);

mt_srand($seed);
echo mt_rand(0, 255);
echo mt_rand(0, 255);
echo mt_rand(0, 255);

実行結果

php > $seed = 10;
php > mt_srand($seed);
php > echo mt_rand(0, 255);
9
php > echo mt_rand(0, 255);
125
php > echo mt_rand(0, 255);
228
php >
php > mt_srand($seed);
php > echo mt_rand(0, 255);
9
php > echo mt_rand(0, 255);
125
php > echo mt_rand(0, 255);
228

どういうこと?

mt_srandにシード値と呼ばれる値を入れると、
そのシード値に合わせた乱数のテーブルが出来上がる。

シード値が同じであれば、
乱数の出てくる順番が同じものになるわけです。

応用

暗号もどき。シード値を共有すれば暗号っぽくなるのかな。

<?php
    $seed = "20";

    $word = "ABCDEFGabcdefg";
    check_enc($word, $seed);

    $word = <<<EOF
    テストの文です。
    これではどうなるでしょうか。
EOF;
    check_enc($word, $seed);

    function check_enc($word, $seed)
    {
        $en = enc2($word, $seed);
        $de = dec2($en, $seed);

        echo "元の文字列:" . $word . PHP_EOL;
        echo "暗号化した文字列:" . $en . PHP_EOL;
        echo "複合した文字列:" . $de . PHP_EOL;

        if ($de === $word) {
            echo "OK!" . PHP_EOL;
        } else {
            echo "NG!" . PHP_EOL;
        }
    }

    //文字を配列に変えてforeach
    //ASCII文字に変換→1足してずらす→文字に戻す
    //配列を文字列に戻す
    function enc2($word, $seed)
    {
        mt_srand($seed, MT_RAND_MT19937);
        foreach(str_split($word) as $char) {
            $char_array[] = chr(ord($char) + mt_rand(0, 255));
        }
        $encripted = implode($char_array);
        return $encripted;
    }

    function dec2($encripted, $seed)
    {
        mt_srand($seed, MT_RAND_MT19937);
        foreach(str_split($encripted) as $char) {
            $char_array[] = chr(ord($char) - mt_rand(0, 255));
        }
        $word = implode($char_array);
        return $word;
    }

実行結果

元の文字列:ABCDEFGabcdefg
暗号化した文字列:�R#� ��y�F�
複合した文字列:ABCDEFGabcdefg
OK!
元の文字列:    テストの文です。
    これではどうなるでしょうか。
暗号化した文字列:��/�]w��*%hY���������gWs��&�^���L��h����l�.���O۬7��q�I�Y3�@���
複合した文字列:    テストの文です。
    これではどうなるでしょうか。
OK!

Laravel5.2以降で二重配列にバリデーションを入れる方法【117日目】

配列にバリデーションをかけたい

arrayX = [['key' => 10], ['key' => 'aaa']]

こんな感じのやつ。

arrayのkeyに対して、数値であるとバリデーションをかけたいやつですね。

公式ドキュメント

バリデーション 5.3 Laravel

配列形式のフィールドをバリデーションする場合は、*文字を使用し、各配列要素の全メッセージを取得できます。

結論

'arrayX.*.key' => 'integer'

なにこれ?

array(配列)
*(全てのキーの要素(一層目))
key(keyというキーの要素(二層目))

わかれば簡単!(わからなかった)

日記

はてなブログのエンジニアグループに入ってみました。

エンジニアの先輩、初心者エンジニア仲間を探したいですけど、なかなか難しいですね。

ひとまず少しずつ勉強していきましょー!

PHPで擬似乱数を作ってみよう【109日目】

擬似乱数を作ってみよう!

ってことで、すっごく簡単に作ってみよう。

アクセスする時間に応じて、数値を返せば実質乱数じゃね?ってことでプログラム。

<?php
    echo randsan();

    function randsan() {
        echo (microtime() * 100) % 101;
    }

はいかんせー!

でも問題が・・・

でもこれ、0.001秒より早いスピードでアクセスされると、同じ数値が出てしまう・・・

<?php
    for($i = 0; $i < 20; $i++) {
        echo randsan();
    }

    function randsan() {
        echo (microtime() * 100) % 101;
    }

これとかね。

なら、アクセス回数の要素も付け加えよう!

擬似乱数

<?php
    for($i = 0; $i < 20; $i++) {
        echo (randsan() . PHP_EOL);
    }

    //時間と回数の2変数で作る
    function randsan($count = 0) {
        if(isset($GLOBALS["randsan"])) {
            // 素数を足しただけで1でもいいです
            $GLOBALS["randsan"] += 13;
            $GLOBALS["randsan"] %= 100;
        } else {
            $GLOBALS["randsan"] = 0;
        }
        echo ((microtime() * 100) + $GLOBALS["randsan"]) % 101;
    }

これでアクセスする度に違うしバッチリだね!

でもこれにも問題が・・・

これ、同じプログラムを、同時に別のPCで実行したら同じ乱数の値が出るよね・・・

じゃあIPで制限する・・・?あれ・・・?これ無限に無理じゃね・・・?

だから擬似乱数

ってことで、ソフトウェアで完璧な乱数とか無理じゃねっていうお話。

だから擬似乱数って呼ばれるんですね。

ちなみに、先輩からハードウェア乱数生成器なるワードをいただきました。
気になる方は調べてみてくださいね。

日記

また1つ課題を消化。
いろんな学びあるの良いこと。

そして昨日の課題、なんでクラス化するの問題が。。。
オブジェクトにするなら、ハノイの塔の配列、移動、表示までのクラスにすればよかった。
ハノイの塔を解くのはまた別のお話ですね。

なんにしても、なぜクラス化するの?どんなオブジェクトを作るの?
っていうのは、いっぱい作っていかなきゃ、慣れない気がします。

1の課題でいろんな気付きをいただけるから、本当に先輩方には感謝なのです・・・!

PHPでハノイの塔のプログラム!【108日目】

苦節3日、無事に出来上がりました。

むしろ3日かかったのかお前っていう。

寝て起きてシャワーを浴びてを2回繰り返したらプログラム出来ました。

注意。

いないと思いますが、このプログラム出来が良くないので、これをコピーしてプログラミング課題の提出に使うのは、
やめておいた方がいいですよ\(^o^)/

まあ、学生感あふれるコードですが・・・w

コード

<?php
    if (count($argv) > 1 && $argv[1] > 0) {
        $max_tower_number = $argv[1];
    } else {
        $max_tower_number = 3;
    }
    $hanoi = new Hanoi($max_tower_number);
    $hanoi->showTower();
    //スタート位置を0、ゴールの位置を2とする
    $hanoi->solveHanoi($max_tower_number, 0, 2, 1);

    class Hanoi
    {
        //塔を格納する変数
        private $tower = [[], [], []];

        //塔を設定する
        public function __construct($max_tower_number = null)
        {
            if ($max_tower_number == null) {
                $this->tower = [[1,2,3], [], []];
            } else {
                for ($i = 1; $i <= $max_tower_number; $i++) {
                    array_push($this->tower[0], $i);
                }
            }
        }

        //ハノイの塔を解く
        public function solveHanoi($tower_height, $start, $goal, $temp)
        {
            if ($tower_height > 1) {
                //ベースの上の塔を、目的の場所から別な場所に避難させる
                $this->solveHanoi($tower_height - 1, $start, $temp, $goal);
            }
            //N+1のベースをゴールに移動する
            $this->move($start, $goal);
            if ($tower_height > 1) {
                //別な場所に避難した塔をゴールに戻す
                $this->solveHanoi($tower_height - 1, $temp, $goal, $start);
            }
        }

        //ブロックの移動
        public function move($start, $goal)
        {
            try {
                //入力値のチェック
                if ($start >= count($this->tower)) {
                    throw new Exception("移動元が不正な値です");
                }
                if ($goal >= count($this->tower)) {
                    throw new Exception("移動先が不正な値です");
                }

                //ブロックを取り出す
                if (count($this->tower[$start]) === 0) {
                    throw new Exception("移動元が空なので移動できません");
                }
                $item = array_shift($this->tower[$start]);

                //ブロックの移動(ルールを確認する)
                if (count($this->tower[$goal]) > 0) {
                    if ($this->tower[$goal][0] < $item) {
                        array_unshift($this->tower[$start], $item);
                        throw new Exception("移動先が" . $this->tower[$goal][0] . "なので" . $item . "は移動できません");
                    }
                }
                array_unshift($this->tower[$goal], $item);

                //動かしたブロックと、移動元移動先を表示
                //合わせて塔も表示
                print("number:" . $item .  " move:" . $start . "->" . $goal . PHP_EOL);
                $this->showTower();

            } catch (Exception $e) {
                print("例外キャッチ:" . $e->getMessage() . PHP_EOL);
                exit(1);
            }
        }

        //塔の表示
        public function showTower()
        {
            print('-----------------------' . PHP_EOL);
            foreach ($this->tower as $items) {
                foreach ($items as $item) {
                    print("[" . $item . "]");
                }
                print(PHP_EOL);
            }
            print('-----------------------' . PHP_EOL);
        }
    }

実行結果

f:id:willow710kut:20180129204957g:plain

補足

インスタンス化する時に数値を渡せば、コンストラクタで値に応じた塔を作ってくれます。

また、move()showTower()はpublicにしてあるので、エラーとか試したい方は、 テキトーにコードをいじっていただければ!

日記

めっちゃ時間かかりましたが、無事に作成完了!

久々に頭回しまくって楽しかったです!

ただ、シャワー浴びた瞬間にひらめく辺り、
私の頭には『キャッシュ』がたまって、パフォーマンスが落ちるという性質がある可能性が・・・w

この課題、明日〆切だったから、それまでに作成出来てよかった・・・!満足!

さあまた明日の課題頑張るぞー!

【PHP】参照渡しと破壊的な関数とは。【103日目】

クイズ

swapは2つの値を入れ替える関数です。
swapを実行した後の$x,$yの値は?

例のプログラム

$x = 1;
$y = 2;

swap($x, $y);
echo $x;
echo $y;

swap2($x, $y);
echo $x;
echo $y;

function swap($a, $b)
{
  $temp = $a;
  $a = $b;
  $b = $temp;
}

function swap2(&$a, &$b)
{
  $temp = $a;
  $a = $b;
  $b = $temp;
}

実行結果

f:id:willow710kut:20180124224742g:plain

どういうこと?

swap($x, $y);は、
function swap($a, $b)の$aに$x(=1)、$bに$y(=2)の値をコピーしているだけ。

だから、関数を実行した後も$xと$yの数値が変わらない。

swap2($x, $y);は、
function swap2(&$a, &$b)に変数そのものを渡している。 &$aは$xになり、&$bは$yになる。

従って、$xと$yの値がswap2の後に入れ替わっている。

&$aのような書き方を『参照渡し』と言い、 実行後に変数が書き換わるような関数を『破壊的な関数』と言う。

日記

シンボルテーブルについての説明は省略。

gifを使ってみましたが、見やすいでしょうか。

良さそうならこんな感じの記事を増やしたいところ。