「技術」カテゴリーアーカイブ

【Linux】【Laravel】コントローラーからデータベースにアクセスする。

今回はLaravelでコントローラーからモデルを介してデータベースにアクセスするところまでを作ります。

https://github.com/takishita2nd/hotel-mng

まずは、モデルにアクセスして、アレコレするクラスを作成します。

ここでは、repositoryとしていますが、特に名前に決まりはありません。

<?php

namespace App\Repository;

use App\Model\ReserveManagement;

class RegisterManagementRepository
{
    // 予約一覧を取得する
    public function getList()
    {
        return ReserveManagement::all();
    }
}

今回はリスト取得だけの機能だけ実装します。

これをコントローラーで使用します。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Repository\RegisterManagementRepository;

class RegisterManagementController extends Controller
{
    protected $registerManagement;

    /**
     * Create a new controller instance.
     *
     * @return void
     */
    public function __construct()
    {
        $this->middleware('auth');
        $this->registerManagement = new RegisterManagementRepository();
    }

    /**
     * Show the Register.
     *
     * @return \Illuminate\Http\Response
     */
    public function index()
    {
        return view('register.index', ['registerLists' => $this->registerManagement->getList()]);
    }
}

Laravelにはサービスコンテナという機能があるようですが、今回はシンプルにコントローラーのコンストラクタでrepositoryをインスタンス化します。

Viewはシンプルに名前を一覧表示するだけです。

@extends('layouts.app')

@section('content')
<div class="container">
    <div class="row">
        <div class="col-md-8 col-md-offset-2">
            <div class="panel panel-default">
                <div class="panel-heading">予約一覧</div>

                <div class="panel-body">
                    <table>
                    @foreach ($registerLists as $list)
                        <tr>
                            <td>これは {{ $list->name }} ユーザーです。</td>
                        </tr>
                    @endforeach
                    </table>
                </div>
            </div>
        </div>
    </div>
</div>
@endsection

最後にルーティングを追加します。

Route::get('/', function () {
    return view('welcome');
});

Auth::routes();

Route::get('/home', 'HomeController@index')->name('home');
Route::get('/management', 'RegisterManagementController@index');

これで、ログイン状態で

http://localhost:8000/management

にアクセスすると、こんな感じで表示されました。

これでモデル・コントローラー・ビュー間のやり取りができるようになりました。

次は、CURD機能を一通り作成してみようと思います。

【Linux】【Laravel】テーブル作成とリレーション

最新ソースはこちら

https://github.com/takishita2nd/hotel-mng

TechCommitの課題で、予約管理を行うツールを作成すえうということで、Laravelで作成してみようと思いまして。

まずはデータベースの作成から着手。

イメージはこんな感じ。

使用する部屋は1つという条件があるので、そんなに複雑にしなくてもいい。

だが、予約が空いている日、埋まっている日が簡単にわかるように、予約が入っている日を管理できるテーブルも追加する。

Laravelでデータベースを作成するマイグレーションファイルを作成する。

$ php artisan make:migration create_reserve_management

中身はこんな感じ。

<?php

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;

class CreateReserveManagement extends Migration
{
    /**
     * Run the migrations.
     *
     * @return void
     */
    public function up()
    {
        Schema::create('reserve_managements', function (Blueprint $table) {
            $table->increments('id');
            $table->string('name');
            $table->string('address');
            $table->string('phone');
            $table->integer('days');
            $table->date('start_day');
            $table->timestamps();
            $table->engine = 'InnoDB';
            $table->charset = 'utf8mb4';
            $table->collation = 'utf8mb4_unicode_ci';
        });

        Schema::create('reserve_day_lists', function (Blueprint $table) {
            $table->increments('id');
            $table->date('day');
            $table->timestamps();
            $table->engine = 'InnoDB';
            $table->charset = 'utf8mb4';
            $table->collation = 'utf8mb4_unicode_ci';
        });

        Schema::create('reserve_day_lists_reserve_managements', function (Blueprint $table) {
            $table->increments('id');
            $table->integer('reserve_managements_id')
                  ->foreign('reserve_managements_id')
                  ->references('id')->on('reserve_managements')
                  ->onDelete('cascade');
            $table->integer('reserve_day_lists_id')
                  ->foreign('reserve_day_lists_id')
                  ->references('id')->on('reserve_day_lists')
                  ->onDelete('cascade');
            $table->timestamps();
            $table->engine = 'InnoDB';
            $table->charset = 'utf8mb4';
            $table->collation = 'utf8mb4_unicode_ci';
        });
    }

    /**
     * Reverse the migrations.
     *
     * @return void
     */
    public function down()
    {
        Schema::dropIfExists('reserve_day_lists_reserve_managements');
        Schema::dropIfExists('reserve_day_lists');
        Schema::dropIfExists('reserve_managements');
    }
}

あとで微調整はする。

コメント無くてすまぬ。

これらは色々試行錯誤した結果なので、あとで直すかもしれない。

最新のコードはgitを参照していただきたい。

Schema::create()を使って、3つのテーブルを作成している。

1つめが予約管理、その次が予約日管理、最後に中間テーブル。

中間テーブルからは各管理テーブルを紐付けるように外部参照キーを設定している。

で、このテーブルを扱うために、モデルを作成する。

$ php artisan make:model reserve_management

これでモデルのベースが作成される。

整理のためにディレクトリは移動しているが、一個作ればそれをベースにして複製すればよい。

各管理テーブルからは以下のような関数を追加する。

    public function hasDayListAndManagement()
    {
        return $this->belongsTo('App\Model\reserve_day_lists_reserve_managements', 'id', 'reserve_managements_id');
    }

これで、管理テーブルから中間テーブルをリレーションすることができる。

逆に、中間テーブルから管理テーブルには、

    public function hasManagement()
    {
        return $this->hasMany('App\Model\reserve_management', 'id', 'reserve_managements_id');
    }

    public function hasDayList()
    {
        return $this->hasMany('App\Model\reserve_day_list', 'id', 'reserve_day_lists_id');
    }

と、すれば、参照できるようになる。

試しに、以下のコマンドを実行する。

$ php artisan tinker

$test = App\Model\reserve_day_list::first()
       => App\Model\reserve_day_list {#2912
            id: 1,
            day: "2019-10-10",
            created_at: "2019-11-20 00:52:20",
            updated_at: "2019-11-20 00:52:20",
          }
$test2 = $test->hasDayListAndManagement()
       => Illuminate\Database\Eloquent\Relations\BelongsTo {#2904}
$test2->get()
       => Illuminate\Database\Eloquent\Collection {#2897
            all: [
              App\Model\reserve_day_lists_reserve_managements {#2911
                id: 1,
                reserve_managements_id: 1,
                reserve_day_lists_id: 1,
                created_at: "2019-11-20 00:52:56",
                updated_at: "2019-11-20 00:52:56",
              },
            ],
          }
$test2->first()->hasManagement()->get()
       => Illuminate\Database\Eloquent\Collection {#2923
            all: [
              App\Model\reserve_management {#2915
                id: 1,
                name: "aaa",
                address: "bbb",
                phone: "ccc",
                days: 2,
                start_day: "2019-10-10",
                created_at: "2019-11-20 00:51:46",
                updated_at: "2019-11-20 00:51:46",
              },
            ],
          }

これで、予約日管理テーブルから予約管理テーブルを参照することができた。

逆に、予約管理テーブルから予約日管理テーブルを参照する。

$test = App\Model\reserve_management::first()
       => App\Model\reserve_management {#2912
            id: 1,
            name: "aaa",
            address: "bbb",
            phone: "ccc",
            days: 2,
            start_day: "2019-10-10",
            created_at: "2019-11-20 00:51:46",
            updated_at: "2019-11-20 00:51:46",
          }
$test2 = $test->hasDayListAndManagement()
       => Illuminate\Database\Eloquent\Relations\BelongsTo {#2904}
$test2->first()->hasDayList()->get()
       => Illuminate\Database\Eloquent\Collection {#2899
            all: [
              App\Model\reserve_day_list {#2911
                id: 1,
                day: "2019-10-10",
                created_at: "2019-11-20 00:52:20",
                updated_at: "2019-11-20 00:52:20",
              },
            ],
          }

できました。

Laravelはこれら、データベースへのアクセスが簡単だからいいよね。

【自作PC】配線問題はこれで終わりにしよう。

前回の配線汚い問題。

まずはCPU電源が短すぎるので、これを買いました。

CPU電源の延長ケーブル。

これで、マザーボードの裏側を通すことができます。

さらに、これも買いました。

マジックテープの結束バンド。

マジックテープだから、何度でも取り付け・取り外しができるんです。

これは便利。

こんな感じでファンの電源とまとめました。

使っていないPCI-Expressの電源もまとめてしまっておきます。

どうです。だいぶスッキリしたでしょう。

PCケースがアクリルで中身がスケスケになっているモデルなので、これでやっと人様に見せられるレベルかと。

【自作PC】いろんなベンチマークソフトを動かしてみる。

前回までに、FF14でのベンチマークの計測結果を載せましたが、世の中には様々なゲームがそれぞれベンチマークソフトを提供していて、ゲーム毎に動作できるかどうかを確認できます。

まぁ、ゲーム毎に必要とされているスペックが違うと言うわけですね。

重たいゲームもあれば、軽いゲームもあるということです。

ということで、いくつかゲームをピックアップして、ベンチマークソフトを動かしてみました。

ちなみに、前回FF14のベンチマーク結果はこちら。

FF15ベンチマーク

紹介ページでの説明では、おそらく最もスペックを必要とするゲームらしい。

少なくともハイスペックのグラボを組み込まないと無理って言うことですね。

PSO2ベンチマーク

DQ10ベンチマーク

たぶん、FF15>FF14>PSO2>DQ10で重たいゲームになっているようです。

後々、グラボを増設してその前後で結果がどうなるか見て見たいので、これはとりあえず参考値ということで。

・・・DQ10やってみようかな。

暇だし。

【Linux】【Laravel】Auth機能を実装する。

LaravelにAuth機能(要はログイン機能)を実装します。

Laravelって便利なもので、デフォルトで簡単に実装できる機能があるんですよ。

まず、データベースなんですが、Laravel初期像体で、すでにmigrateの記述が出来上がっているので、migrateするだけでデータベースの準備はOKです。

ログインページですが、以下のコマンドを実行します。

$ php artisan make:auth

これだけで実装完了です。

Laravelを起動してブラウザからアクセスしてみましょう。

右上にRegisterとLoginのリンクがありますので、まずはRegisterでユーザー登録を行います。

名前、メールアドレス、パスワードを入力してボタン押下。

ログインした状態です。

一回ログアウトして、ログインページへ行ってみましょう。

ログインページです。

ユーザー登録した内容を入力すると、先程のログイン後のページが表示されるはずです。

本当は、パスワードを忘れたときのためにパスワードリセット機能もあるのですが、メールでリセットするため、SMTPの設定がないと動作しません。

なので、この機能は後々削除する予定。

【Linux】【Laravel】Laravelからデータベースにアクセスする。

Laravelからmysqlにアクセスできるところまでやりました。

mysqlのインストール

$ sudo apt-get install mysql-server

mysqlの初期設定

$ sudo mysql_secure_installation

基本的にyを選択すれば良い。

rootでログイン

$ sudo mysql -u root -p

データベースの作成

mysql> create database <データベース名>;

ユーザーの追加

mysql> create user <ユーザー名> identified by '<パスワード>';

ユーザーに権限を付与

mysql> grant all on . to <ユーザー名>;

Laravelにデータベースの設定を記入

database.phpの設定を変更。

        'mysql' => [
            'driver' => 'mysql',
            'host' => env('DB_HOST', '127.0.0.1'),
            'port' => env('DB_PORT', '3306'),
            'database' => env('DB_DATABASE', '<データベース名>'),
            'username' => env('DB_USERNAME', '<ユーザー名>'),
            'password' => env('DB_PASSWORD', '<パスワード>'),
            'unix_socket' => env('DB_SOCKET', ''),
            'charset' => 'utf8mb4',
            'collation' => 'utf8mb4_unicode_ci',
            'prefix' => '',
            'strict' => true,
            'engine' => null,
        ],

migrateの実行

$ php artisan migrate

エラーが出た。

could not find driver

PHPに、データベースにアクセスするPDOがない、ということなので、mysqlにアクセスするモジュールを追加。

$ sudo apt-get install php7.2-mysql

これでmigrateが成功すればOK。

適当なテーブルを追加する

$ php artisan make:migration create_test_table

CreateTestTableクラスが出来上がるので、以下のように書き換える。

    public function up()
    {
        Schema::create('test', function (Blueprint $table) {
            $table->increments('id');
            $table->text('text');
            $table->timestamps();
        });
    }
$ php artisan migrate

Laravelからデータベースにアクセス

$ php artisan tinker
>>> DB::table('test')->get();
DB::table('test')->insert(['test' => 'insert'])
DB::table('test')->get();

データが表示されれればOK。

【Linux】【Laravel】Laravel5.5をインストールする。

オイラのLinux PCにLaravel5.5をインストールしました。

使用ディストリビューションはUbuntu18.04です。

composerのインストール

$ sudo apt-get install composer

Laravelのインストール

$ composer global require "laravel/installer"

プロジェクトの作成

$ composer create-project --prefer-dist laravel/laravel <プロジェクト名> "5.5.*"

実行すると

You can also run php --ini inside terminal to see which files are used by PHP in CLI mode.

というエラーが出たので、PHPのモジュールを追加。

$ sudo apt-get install php7.2-mbstring
$ sudo apt-get install php7.2-xml

Laravelの実行

$ php artisan serve

を実行した状態で、ブラウザから

http://localhost:8000

にアクセスする。

この画面が表示されればOK。

パーミッション変更

これをやらないとダメらしい。

$ chmod 777 storage/
$ chmod 777 bootstrap/cache/

【プログラミング】勇者と魔王の戦い

Tech commitの課題で、面白そうなテーマだったので、挑戦してみました。

https://github.com/takishita2nd/battle_rpg

  • 勇者と魔王が交互に攻撃する
  • 一定確率で攻撃を回避する
  • 一定確率でクリティカルヒット(ダメージ1.5倍)になる
  • どっちが勝利したかを表示する
using System;

namespace battle_rpg
{
    public static class Common
    {
        public static bool roleJudge(int rate)
        {
            bool judge = false;
            Random r = new Random();
            int value = r.Next(0, 100);
            if(value < rate) {
                judge = true;
            }
            return judge;
        }
    }
}

これは乱数を使って、命中やクリティカル判定などの確率判定を行うメソッドです。

引数に確率(%)を受け取り、乱数を0〜100の範囲で発生させて、その値が確率以下ならばtrueを返します。

using System;

namespace battle_rpg
{
    public class Charactor
    {
        private const String Statusformat = "{0}:HP{1} 攻撃力{2}";
        private const String AttackFormat = "{0}の攻撃!{1}に{2}のダメージ";
        private const String CriticalAttackFormat = "{0}の攻撃!クリティカルヒット!{1}に{2}のダメージ";
        private const String EvasionFormat = "{0}の攻撃!{1}は攻撃をかわした";
        public string Name {get;}
        public int Hp {get; set;}
        public int Attack {get;}
        public int evasionRate { get;}
        public int criticalRate { get;}

        public Charactor(string _name, int _hp, int _attack)
        {
            this.Name = _name;
            this.Hp = _hp;
            this.Attack = _attack;
            this.evasionRate = 5;
            this.criticalRate = 5;
        }

        /**
         * ターゲットを攻撃
         * <param>  _target 攻撃対象
         * <return> 与えたダメージ
         */
        public String doAttack(Charactor _target)
        {
            String message = String.Empty;
            if(isHit(_target)) {
                int damage = this.Attack;
                if(isCritical()) {
                    damage = (int)(damage * 1.5);
                    message = String.Format(CriticalAttackFormat, this.Name, _target.Name, damage);
                } else {
                    message = String.Format(AttackFormat, this.Name, _target.Name, damage);
                }
                _target.Hp -= damage;
            } else {
                message = String.Format(EvasionFormat, this.Name, _target.Name);
            }

            return message;
        }

        /**
         * 命中判定
         * <param>  _target 攻撃対象
         * <return> true:命中
         */
        private bool isHit(Charactor _target)
        {
            bool hit = true;
            if(Common.roleJudge(_target.evasionRate)) {
                hit = false;
            }
            return hit;
        }

        /**
         * クリティカル判定
         * <return> true:クリティカル
         */
        private bool isCritical()
        {
            bool critical = false;
            if(Common.roleJudge(this.criticalRate)) {
                critical = true;
            }
            return critical;
        }

        /**
         * 死亡判定
         * <return> true:死亡
         */
        public bool isDie()
        {
            bool die = false;
            if(this.Hp <= 0) {
                die = true;
            }
            return die;
        }

        public String showStatus()
        {
            return String.Format(Statusformat, this.Name, this.Hp, this.Attack);
        }
    }
}

勇者や魔王を扱うクラスです。

このクラスの中でHPや攻撃力などを保持します。

メインはdoAttack()メソッド。この中で命中判定やクリティカル判定をおこない、攻撃対象(引数)のHPを減らしていきます。

using System;

namespace battle_rpg
{
    public class Battle
    {
        private Charactor yusha;
        private Charactor maou;
        private const String DieFormat = "{0}は倒れた。";
        public Battle()
        {
            yusha = new Charactor("勇者", 300, 15);
            maou = new Charactor("魔王", 400, 9);
        }

        public void execute()
        {
            bool nowBattle = true;
            while(nowBattle) {
                // HP表示
                Console.WriteLine(yusha.showStatus());
                Console.WriteLine(maou.showStatus());
                Console.WriteLine();

                // 勇者の攻撃
                Console.WriteLine(yusha.doAttack(maou));

                // 魔王死亡判定
                if(maou.isDie()) {
                    Console.WriteLine();
                    Console.WriteLine(DieFormat, maou.Name);
                    nowBattle = false;
                    Console.WriteLine("世界に平和が訪れた。");
                }

                if(nowBattle == false) {
                    return;
                }

                // 魔王の攻撃
                Console.WriteLine(maou.doAttack(yusha));

                // 勇者死亡判定
                if(yusha.isDie()) {
                    Console.WriteLine();
                    Console.WriteLine(DieFormat, yusha.Name);
                    nowBattle = false;
                    Console.WriteLine("世界は征服された。");
                }
                Console.WriteLine();
            }
        }
    } 
}

実際にバトルを行うクラスです。

コンストラクタで勇者と魔王のステータスを設定、execute()でどちらかが負けるまでループを行います。

using System;

namespace battle_rpg
{
    class Program
    {
        static void Main(string[] args)
        {
            Battle battle = new Battle();
            battle.execute();
        }
    }
}

メイン関数。Battleクラスをインスタンス化してexecute()を実行しているだけです。

とりあえず、こんな感じで要求されている処理はできました。

カスタマイズすれば色々と拡張できそうですね。

【自作PC】配線汚い問題

前々から感じてはいました。

配線が汚い。

特に問題なのは、電源ケーブルがPCIスロットの上を通っているので、PCIを装着するときに物理的に干渉するんじゃないかということ。

YouTubeの自作PCの動画を見ていると、電源ケーブルをマザーの裏側に通す、と言うことをやっていたので、オイラも実際にやってみようと思う。

電源から出ているケーブルを背面に持っていき、

ここから出す。

この周りごっちゃと見えるのは、ここにマザーの電源ピンがあるため。

ここにさらに各ドライブへの電源と、ケースファンの電源が伸びているので、仕方ありません。

背面のファンのケーブルもちょっと長くて、ファンに当たってしまいそうだったので、ケースに付いてきた結束バンドでまとめました。

全体を見るとこんな感じ。

CPUの電源ケーブル。。。

だいぶスッキリしましたが、CPUの電源ケーブルがまだ邪魔ですね。

あと、ケースファンの電源もブランブランしているのが気になります。

なにかうまい方法は無いでしょうか・・・

身近な物にも使われている相対性理論

再びこの本です。

いや、この本、物理について非常にわかりやすく説明されているので、読んでいて楽しいです。

そして、物理学の中でも難解なのが、相対性理論。

昔、授業で習ったことあるけど、当時は全く理解できなかったけど、今これを読んだら、どういう理屈なのかがわかったのです。

身近な物の応用例としてはGPS

ここまで正確に位置がわかるのは相対性理論の応用によって可能になっているです。

重力は時空の歪みによって発生している

ニュートンの万有引力の法則(質量がある物同士は引きつけあうという物理法則)がありますが、この中では、なぜ重力が発生するのかについては明かされていない。

それを論理づけたのが相対性理論。

時空の歪みとは、この本では、トランポリンの上にボーリングの玉を乗せているようなイメージとしています。

ボーリングの玉が地球だとすれば、その重さによってトランポリンの面が沈んでいると思います。

これが時空の歪みのイメージです。

ここにもう一個トランポリンの上にボーリングの玉を置くと、その重さによって、二つのボーリングの玉が引き寄せられると思います。

これが万有引力のイメージです。

時空の歪みから離れるほど時間の流れが遅くなる

例えば、地球上の時間の流れる速度と、地球の周りを回っている人工衛星の時間の流れは少し異なります。

人工衛星のほうが時間の流れが少し遅い。

とはいっても、ほんの数ミリ秒にも満たない微妙な誤差ですが。

GPSの位置測定では、電波の送信時間と到着時間の差分で測定しているのですが、このとき、時間の誤差を計算に入れないと、位置情報の計算結果が狂ってしまうのです。

そう考えると、GPSってスゴイよね。

この本は本当にオススメ。

物理学って難しいと思われがちですが、身近な物を例に取ればわかりやすくなるんですね。