2020/05/25

Homebrewとは

HomebrewはMacのパッケージ管理システムです。

 

MacはGit、PHP、Ruby、Pythonといったアプリケーションが標準インストールされてますが、Macで開発環境を構築する場合、異なるバージョンで利用するケースが発生します。
そこでHomebrewを利用すると、Gitで管理されたパッケージをダウンロードして、インストール、アンインストールなど管理することができます。


最近ではDockerやクラウド開発の登場で Macに直接インストールすることも減りつつありますが、Dockerだけでは賄えない部分も多々あるので、いまだ必須のツールになっています。

参考

Homebrew - インストール

インストール

以前の記事ではrubyでインストールしていましたが、公式をみるとシェルスクリプトでインストールしています。
実際はGitでパッケージをダウンロードし、Ruby の gem で実行しているのでやっていること自体は変わりません。

ターミナルを開き、以下のコマンドを実行します。


$ /bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install.sh)"

しばらくしてインストールが完了したら、バージョンを確認します。


$ brew --version
Homebrew 2.2.17
Homebrew/homebrew-core (git revision c87df; last commit 2020-05-22)

パッケージのインストール

試しに、ファイルダウンロードをするコマンド wget を brew でインストールしてみましょう。


$ brew install wget

インストールが完了したら、バージョンを確認します。


$ wget -V
GNU Wget 1.20.3 built on darwin18.7.0.
...

このようにHomebrewは Macで利用できないコマンドやアプリケーションを brew コマンドで管理します。

Cask でインストール

Cask は MacのGUIアプリ、フォント、プラグイン、その他オープンソースででないソフトウェアをインストールするときに利用します。

例えばブラウザアプリ「Firefox」を、Homebrewでインストールすることができます。


$ brew cask install firefox

Macのアプリケーションフォルダを確認するとFirefoxがインストールされているはずです。

 

PHPのインストール

Macのバージョンによっては、標準でインストールされているPHPのバージョンは異なります。
例えばLaravel 7.x をMac上で利用する場合、PHPのバージョン7.2.5以上が必要なため、別途インストールが必要です。

PHPパッケージの検索

PHPのインストールの前に、パッケージを検索してみます。


$ brew search php
==> Formulae
brew-php-switcher     php-code-sniffer      php@7.2               phplint               phpmyadmin            phpunit
php                 php-cs-fixer          php@7.3               phpmd                 phpstan

PHP7.3をインストール

php@7.3 パッケージがあるので、これをインストールします。


$ brew install php@7.3

PHPのパス設定

インストールが完了しましたが、現状はPHPの旧バージョンが有効のままです。

PHP7.3が利用できるようにパスの設定を ~/.bash_profile に記述します。


$ echo 'export PATH="/usr/local/opt/php@7.3/bin:$PATH"' >> ~/.bash_profile
$ source ~/.bash_profile

設定をすぐに反映するために .bash_profile を読み込むと、PHPのバージョンが変更されたことを確認できます。


$ php -v
PHP 7.3.18 (cli)

  2020/05/16

Matplotlib で3直線で囲まれた範囲を塗りつぶしをしてみます。

3直線の定義

まず、x の範囲を適当に設定し、3直線を定義します。


x = np.arange(0, 100, 0.1)
y1 = -x * (3/2) + 100
y2 = -x / 5 + 32
y3 = -x * (3/4) + 250 / 3

プロット


plt.plot(x, y1, label="y1: 3*x1 + 2*x2 >= 200")
plt.plot(x, y2, label="y2: x1 + 5*x2 >= 160")
plt.plot(x, y3, label="y3: 4*x1 + 3*x2 >= 250")

塗りつぶし

実際の塗りつぶしは、fill_between() 機能を利用します。

ですが、fill_between() は3式以上には対応していないため、2つのデータに落とし込む必要があります。

2式(データ)に落とし込む

numpy の maximum(), minimum() で2式の最大値または最小値を取得します。

まず y1  y2 のグラフのような条件下でデータ y4 を設定します。


y4 = np.maximum(y1, y2)

グラフを塗りつぶす

今度は y3, y4 を fill_between() と where パラメータで塗りつぶします。

グラフでもわかるように y4(y1, y2 条件のデータ) <= y3 となります。


ax = plt.axes()
ax.fill_between(
    x,
    y3,
    y4,
    where=y3 > y4,
    alpha=0.3,
    interpolate=True,
)

第1引数は、x軸の値、第2,3引数は2式のデータ、オプションとして where など設定します

もし、3式の交点がわあかっていれば、fill() を使って交点指定で塗りつぶしても良いかと思います。

  2020/05/15

線形最適化問題とは?

1次式のみで定義できる式から、ある条件(制約)をもとに問題の最適解を見つけることです。
2次以上の式や、離散的な変数(連続でない)に関しての問題は対象外となります。

目的関数と制約

問題を解決するには、目的関数(求めたい解の定義式)と、問題の制約(条件)を定義します。
問題定義の関数は、 最小化最大化の2種類あります。

例えば、生産するための最大利益、乗り換え案内などの最短経路を求めたりする問題です。

上記は3つの制約で、ある目的関数から最適解を求めたグラフ化です。
制約は(不等式)の不等号の向きで範囲が異なります。

 

PuLP とは

PuLP は COIN-OR プロジェクトで開発された線形最適化問題を解くための Pythonライブラリです。

Jupyter Notebook インストール

視覚的に確認するために、Jupyter Notebook をインストールします。
個人的には、Anaconda は入れたくないので pip3 でインストールします。


$ pip3 install jupyter

Pulp インストール


$ pip3 install pulp

Pulp の基本

決定変数

変数作成変数は、 LpVariable() で定義します。

  • 連続変数(実数値)
  • 0 or 1変数
  • 整数値

第1引数

「インスタンス名」で必須です。

第2引数

  • lowBound:変数の下限値(デフォルト:None)
  • upBound:変数の上限値(デフォルト:None)
  • cat:変数の種類(デフォルト:連続変数 = pulp.LpContinuous)

変数の利用例


x1 = pulp.LpVariable('x1', 0)
x2 = pulp.LpVariable('x2', 0) 

問題定義のモデル作成

目的関数と制約

目的関数を LpProblem() でインスタンスを作成し、制約を追加してきます。

最大化モデル作成


LpProblem(sense= LpMaximize)

最小化モデル作成


LpProblem(sense=LpMinimize)

ラベル付きの例


problem = pulp.LpProblem('最大化問題', sense=pulp. LpMaximize)

作成したインスタンスに、目的関数、制約の式を追加します。


problem = pulp.LpProblem('生産計画問題', sense=pulp. LpMaximize)
problem+= x1 + 2*x2, '目的関数 利益見込み'
problem+= x1 + 3*x2 <= 24, '原料制約'
problem+= 4*x1 + 4*x2 <= 48, '労働時間制約'
problem+= 2*x1 + x2 <= 22, '機会稼働制約'
problem

最適解の計算

定義した問題定義を実際に解くには、 solve() を利用しますが、戻り値は実際の解ではなく、成功フラグになります。


result = problem.solve()

実行結果のステータス

実行結果のステータスを確認するのに、 LpStatus() を利用します。


print(pulp.LpStatus[result])

ステータスの種類


{
 -3: 'Undefined',
 -2: 'Unbounded',
 -1: 'Infeasible',
 0: 'Not Solved',
 1: 'Optimal'
}

目的関数の最適値(最大・最小値)

目的関数の最適解は、 value(モデル.objective) で取得します。


print(pulp.value(problem.objective))

最適解を求める

解の取得

最適解を求めたら、解を取得します。
定義した決定変数を variables() 、それぞれの解を value(オブジェクト) で取得します。


for v in problem.variables():
    print(f’{v} = {pulp.value(v)}’)

結果


$ python3 2-1.py 
x1 = 6.0
x2 = 6.0

Jupiter Notebook

  2020/03/30

ペジネーションビューの書き出し

artisan コマンドで、ペジネーションビューをプロジェクト内に書き出します。


$ php artisan vendor:publish --tag=laravel-pagination

resources/views/vendor/pagination/ にページネーションのBladeファイルが作成されます。

あとで説明しますが、デフォルトは「bootstrap-4」で書き出されますが、ページネーションメソッドで他のBladeファイルを指定することができます。
よって、利用したいBladeファイルをカスタマイズしてください。

Eloquent モデルで取得

Eloquent モデルには、paginate()、simplePaginate() メソッドを利用できます。


$limit = 10;
$offset = 0;
$user = User::paginate($limit, '[*]', 'page', $offset);

AppServiceProvider に追加

AppServiceProvider::boot() でページネーションのBlade ファイル名を指定します。


    public function boot()
    {
        Paginator::defaultView('pagination::bootstrap-4');
        Paginator::defaultSimpleView('pagination::simple-bootstrap-4');
    }

Blade にページネーションを実装

Blade ファイルでは、Eloquent モデルデータの links() メソッドでページネーション表示できます。


{!! $user->links() !!}

また、Blade 側で明示的に指定することもできます。


{{ $paginator->links('pagination::bootstrap-4', ['key' => 'value']) }}

Eloquent のページネーションメソッドは以下を参照してください。

https://readouble.com/laravel/7.x/ja/pagination.html

  2020/03/30

node-sass をインストールする

CSSコンパイルは開発のみで利用するため、ローカル(devDependencies)にインストールします。


$ npm install node-sass --save-dev
//または
$ yarn install node-sass --dev

--save-dev はローカル(devDependencies)にインストールする npm コマンドオプションです。
yarn では --dev にあたります。(混乱しますが・・・)

ファイル構成

sass から css に書き出すディレクトリを構成します。

元ファイル(sass)

sources/sass/default.scss

書き出しファイル(css)

public/css/default.css

ファイル構成

npm を初期化してない場合は、新規作成します。


$ npm init

package.json

package.json の scripts に sass の設定を記述します。


"scripts": {
    "sass": "node-sass resources/sass/ --output public/css/ --output-style compressed --watch --source-map true"
}
  • compressed:css圧縮
  • --watch:監視設定(sass保存時に自動書き出し)
  • --source-map true: .css.map ファイルの書き出し/li>

CSSコンパイル


$ npm run sass

public/css/ に対象の cssファイルが書き出されます。

  2020/03/29

SQL が発行されるたびに Log ファサードを利用して SQLログを書き出してみます。

Laravel のLogファサードの仕様は以下を参照してください。

https://readouble.com/laravel/7.x/ja/logging.html

LogSqlServiceProvider の設定

プロバイダは、AppServiceProvider に登録しても良いですが、今回はカスタムで LogSqlServiceProvider を作成します。


$ php artisan make:provider LogSqlServiceProvider

app/Providers/LogSqlServiceProvider.php が作成されているのを確認します。

AppServiceProvider に登録

config/app.php の providers に LogSqlServiceProvider を登録します。


    'providers' => [
...
        App\Providers\LogSqlServiceProvider::class,
...
    ],

SQLログ処理を記述

app/Providers/LogSqlServiceProvider.php の register() に記述します。


namespace App\Providers;

use Illuminate\Support\ServiceProvider;
use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;

class AppServiceProvider extends ServiceProvider
{
    const SQL_LOG_ENVIROMENT = [
        'local',
        'development',
    ];
....

    public function register()
    {
        if (in_array(App::environment(), self::SQL_LOG_ENVIROMENT)) {
            DB::listen(function ($query) {
                $sql = $query->sql;
                for ($i = 0; $i < count($query->bindings); $i++) {
                    $sql = preg_replace("/\?/", $query->bindings[$i], $sql, 1);
                }
                Log::channel('sql')->debug("SQL", ["time" => sprintf("%.2f ms", $query->time), "sql" => $sql]);                                                      
            });
        }
    }

App::environment() で現在の環境を取得し、任意に設定した SQL_LOG_ENVIROMENT の場合に、ログを書き出します。

環境による設定は、.env の boolean で設定しても良いかも知れません。

SQLログファイルパス設定

config/logging.php で設定でき、デフォルト「storage/logs/larave.log」となります。

Log::debug() の場合、デフォルトで single チャンネルで書き出されるため、Log::channel('チャンネル名')で、SQL用のログを設定します。
(内部的に、Illuminate\Log\LogManagerクラスで、driver() に設定される模様)


    'channels' => [
...
        'sql' => [
            'driver' => 'sql',
            'path' => storage_path('logs/sql.log'),
            'level' => 'debug',
        ],
...
    ],

またロガーは RFC 5424 の以下の8つのログレベルを提供しています。

  • emergency
  • alert
  • critical
  • error
  • warning
  • notice
  • info
  • debug

Logファサードは、最終的にPsr\Log\LoggerInterface を実装した Monolog\Logger を利用しています。

  2020/03/28

今回は、複数のコンテナを docker-compose を利用して起動してみます。

Docker/Kubernetes 実践コンテナ開発入門

を参考に、Jenkins のMaster、Slave で複数のコンテナを構築します。

Jenkins(Master)コンテナ作成

まず、Jenkins(Master)を以下の設定で作成します。

  • Dockerイメージ:Jenkinsci/jenkins:latest
  • ポートフォワーディング:8080 <==> 8080
  • 共有ボリューム:./jenkins_home <==> /var/jenkins_home

ポートフォワーディング、共有ボリュームは、左がホスト(Mac)、右がDockerの設定となります。

docker-compose.yml の設定


version: "3"
services:
  master:
    container_name: master
    image: jenkinsci/jenkins:2.142-slim
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home

このように、volumes を設定することで、Dockerのデータをホスト側と共有させて、永続化することができます。

docker-compose の起動

docker-compose.yml を作成したら、 --build でイメージ構築と同時に起動をします。


$ docker-compose up --build

Jenkinsのパスワードを控える

途中で、Jenkins の管理者パスワードが表示されるため、控えておきましょう。
忘れた場合は、Docker内の「/var/jenkins_home/secrets/initialAdminPassword」に記載されています。


...
master    | Jenkins initial setup is required. An admin user has been created and a password generated.
master    | Please use the following password to proceed to installation:
master    | 
master    | パスワード
master    | 
master    | This may also be found at: /var/jenkins_home/secrets/initialAdminPassword
...

この時点で、ホスト側のルートにも「jenkins_home」ディレクトリが作成されます。

Docker側でSSH認証キーを作成

Jenkins(Master)コンテナ内で、SSH認証キーを作成します。

dockerコンテナに対して、シェルコマンドを実行します。


$ docker container exec -it コンテナ名 シェルコマンド

今回は、ssh-keygen を利用するので、


$ docker container exec -it master ssh-keygen -t rsa -C ""
Generating public/private rsa key pair.
Enter file in which to save the key (/var/jenkins_home/.ssh/id_rsa):        
Created directory '/var/jenkins_home/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
...
SHA256:SSHキー

すると、jenkins_home/.ssh/ に id_rsa、id_rsa.pub が作成されます。

docker-compose の停止

Jenkins(Slave)を設定するため、一旦、コンテナを停止します。


$ docker-compose down

Jenkins(Slave)コンテナ作成

Jenkins(Slave)を設定を行います。

docker-compose.yml の設定


version: "3"
services:
  master:
    container_name: master
    image: jenkinsci/jenkins:2.142-slim
    ports:
      - 8080:8080
    volumes:
      - ./jenkins_home:/var/jenkins_home
    links:
      - slave01

   slave01:
     container_name: slave01
     image: jenkinsci/ssh-slave
     enviloment:
       - JENKINS_SLAVE_SSH_PUBKEY=id_rsa.pub のキー

enviloment は環境変数の設定で、「JENKINS_SLAVE_SSH_PUBKEY」に「jenkins_home/.ssh/id_rsa.pub」のキーを設定します。

また、Jenkins(Master)で、links を設定して master から slave01 を名前解決できるようにします。

docker-compose の起動

コンテナをバックグランドで起動します。


$ docker-compose up -d

docker-compose の起動

設定したポートで、http://localhost:8080/ にアクセスすると、Jenkins の画面が表示されます。

パスワードは、Jenkins(Master)の起動で表示されたものを利用します。

手っ取り早く、Install suggested plugins を選択してインストールします。

Jenkins のユーザを作成してログインします。

Jenkins のノード(slave01)の設定

本の通りにノードの管理で、slave01 の認証情報(id_rsa、パスフレーズ)などを設定していきますが、slave01 の起動がエラーになってしまいました。
(Jenkins の Jenkinsの管理 > ノードの管理 で slave01 の設定の箇所)


...
java.io.IOException: Java not found on hudson.slaves.SlaveComputer
...

調べたところ、slave01 で java のパスを通す必要があるようです。

Slave に Java のパスを通す

ホスト(Mac)側から、slave01 へログイン


$ docker exec -it slave01 bash

slave01 の Java のパスを調べる


# which java
/usr/local/openjdk-8/bin/java

このパスを、slave01 の「高度な設定 > Javaのパス」に設定します。

これで、ノード再起動すると同期が完了します。

 

ちなみに、Docker For Mac で利用してみましたが、結構CPU負荷が高いです。


$ docker-compose stats

  2020/03/28

Qiita とか調べていると、いきなり docker と docker-compose が混在してなんだこりゃ?となったりします。
(少なくとも自分は)

特に、他人の作ったdocker-compose.yml を docker の基礎がわからないと何をしているのか読み取れません。

例えば、Laravel を Docker で動かす Laradock はすごく便利で少しの知識があれば開発環境を動作せることが可能ですが、「やっぱり自分で構築したい!」となると、その設定を全部把握するのはかなりの時間がかかりそうです。

docker-compose が必要になる段階

  • docker の基本コマンドを覚える
  • Dockerファイルを記述
  • 複数のコンテナの設定が必要になる
  • Dockerファイルの管理が必要となる
  • docker-compose があると一度に管理できる

最初は docker の基本コマンドを繰り返し実感するのが良いのでは?と思います。

docker-compose を使ってみる

まず、docker-compose コマンドが存在するか確認します。


$ docker-compose version
docker-compose version 1.25.4, build 8d51620a
docker-py version: 4.1.0
CPython version: 3.7.5
OpenSSL version: OpenSSL 1.1.1d  10 Sep 2019

あらかじめ、Dockerfile でイメージを作成済みであることを前提とします。

hello:latest イメージの シェルスクリプト「hello.sh」


#!/bin/sh
echo "Hello Shell Script"

hello:latest イメージの Dokcerfile


FROM ubuntu:18.04

COPY hello.sh /usr/local/bin
RUN chmod +x /usr/local/bin/hello.sh

CMD ["hello.sh"]

docker-compose を利用する前にまず docker コマンドでの起動を確認します。
 

docker コマンドによるビルド&起動コマンド


$ docker image build -t example/hello:latest .
$ docker container run example/hello:latest

起動確認ができたら、一度 dockerコンテナを落としておきます。


$ docker stop コンテナID

docker-compose.yml を設定して実行する

docker-compose を利用するには、「docker-compose.yml」の設定が必要となります。

docker-compose.yml


version: "3"
services:
   hello:
     image: example/hello:latest
     ports:
       - 9000:8080

docker-compose で起動(フォアグランド)

docker-compose up で、docker-compose.yml を読み込み、「hello.sh」が実行されます。

version

docker-compose.yml のフォーマットバージョンで、「3」は2020/3時点での最新です。

services

services: の第一階層に、各コンテナの名前を複数定義します。

例では、hello がコンテナ名となります。

image

Dockerイメージ名を設定します。

ports

ホストと docker のポートフォワーディング設定(ホストポート:dockerポート)


$ docker-compose up
Creating network "docker-hello_default" with the default driver
Creating docker-hello_hello_1 ... done
Attaching to docker-hello_hello_1
hello_1  | Hello Shell Script
docker-hello_hello_1 exited with code 0

ちなみに、このサンプルは hello.sh を実行したのちに exit しているため、状態は「Exit 0」となっています。

プロセスを確認する

docker のプロセス確認は docker-compose コマンドでも可能です。


$ docker-compose ps
       Name           Command    State    Ports
-----------------------------------------------
docker-hello_echo_1   hello.sh   Exit 0   

コンテナを停止

docker-compose.yml で設定しているコンテナを全て停止します。


$ docker-compose down

  2020/03/26

AWS ECR(Elastic Container Repository)を使ってみます。

Amazon Elastic Container Registry

ECRは、Dockerコンテナイメージを保存するレジストリサービスで、DockerHub の AWS版のような感じです。
AWS ECS 、AWS fargate と併用してコンテナを用いたサーバを運用します。

料金

2020/3時点で、以下の枠で無料のようです

Amazon Elastic Container Registry の料金

  • イメージ:500Mまで
  • 転送量:1G/月

リポジトリ作成

マネジメントコンソールもしくは、AWS Client でリポジトリを作成します。

マネジメントコンソールでリポジトリ作成する場合

使用方法にアクセス

 

リポジトリ名を入力、プッシュ時にスキャンを有効にして、リポジトリを作成

 

リポジトリが作成される

AWS CLI でリポジトリ作成する場合

aws コマンドでも、ECR リポジトリを作成できます。


$ aws ecr create-repository --repository-name php

AWS CLI のプロファイル追加

AWS Client を利用して ECRのプロファイルを作成します。

リージョンは東京(ap-northeast-1)としています。


$ aws configure --profile ecr
AWS Access Key ID [None]: AIM アカウント ID
AWS Secret Access Key [None]: AIM シークレットキー
Default region name [None]: ap-northeast-1
Default output format [None]: 

AWS CLI 用の環境変数設定

AWS ECR のリージョン(東京)を環境変数に設定(.bash_profile)します。


$ vi .bash_profile

export AWS_REGION=ap-northeast-1

環境確認


$ source .bash_profile
$ echo $AWS_REGION
ap-northeast-1

Dockerfile 作成


FROM amazonlinux:2

SHELL ["/bin/bash", "-c"]

ARG PROJECT_DIR="projects"
WORKDIR $PROJECT_DIR

CMD ["/bin/bash"]

AWS ECR ログイン


$ aws ecr get-login-password --region ${AWS_REGION} | docker login --username AWS --password-stdin xxxxxx

Dockerイメージビルド


$ docker build -t linux2 .

Dockerイメージタグ付け


$ docker tag linux2:latest 517704528142.dkr.ecr.ap-northeast-1.amazonaws.com/linux2:latest

AWS ECR に Dockerイメージをプッシュ


$ docker push xxxx.amazonaws.com/linux2:latest

イメージが作成されたのを確認

AWS ECR リポジトリ確認


$ aws ecr describe-repositories --region ${AWS_REGION}
{
    "repository": {
        "registryId": "xxxxxxxxxxxx",
        "repositoryName": "linux2",
        "repositoryArn": "arn:aws:ecr:ap-northeast-1:xxxxxxxxxxxx:repository/linux2",
            "createdAt": 1585197107.0,
            "imageTagMutability": "MUTABLE",
            "imageScanningConfiguration": {
                "scanOnPush": true
            }
    }
}

AWS ECR イメージ確認

リポジトリ名一覧


$ aws ecr describe-repositories --query 'repositories[].repositoryName'

リポジトリを指定した詳細


$ aws ecr list-images --repository-name linux2 --region=${AWS_REGION}

 

AWS ECR イメージ削除


$ aws ecr batch-delete-image --repository-name linux2 --image-ids imageTag=v2.0

  2020/03/24

Laravel 7 で認証ページを作成してみます。

※Laravel7 の認証ページ

https://readouble.com/laravel/7.x/ja/authentication.html

プロジェクト作成


$ composer create-project laravel/laravel laravel-auth --prefer-dist
$ cd laravel-auth
$ chmod -R 777 storage
$ chmod -R 777 bootstrap/cache

この時点で、 config/auth.php などが作成されています。

  • config/auth.php
  • app/User.php
  • app/Http/Middleware/Authenticate.php
  • database/migrations/xxxx_create_users_table.php
  • database/migrations/xxxx_create_password_resets_table.php
  • database/factories/UserFactory.php

User モデル

デフォルトで app/User.php が作成されています。


namespace App;

use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;

class User extends Authenticatable
{
    use Notifiable;
    protected $fillable = [
        'name', 'email', 'password',
    ];
    protected $hidden = [
        'password', 'remember_token',
    ];
    protected $casts = [
        'email_verified_at' => 'datetime',
    ];
}

今回は、App/Models/User.php にパスを変更しておきます。
(namespace など修正が必要)

Admin モデル作成

マルチ認証用に、管理者(Admin)モデルを作成してみます。

Models/Admin.php を作成します。


$ php artisan make:model Models/Admin

Admin マイグレートファイル作成

databases/ に Admin用のマイグレーションファイルを作成します。


$ php artisan make:migration create_admins_table

モデル&マイグレートファイルを同時に作成

上記のモデルとマイグレーションファイルを同時に作成することもできます。

Models/Admin.php を作成します。


$ php artisan make:model Models/Admin -m

use Illuminate\Support\Facades\Schema;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Database\Migrations\Migration;
 
class CreateAdminsTable extends Migration
{
    public function up()
    {
        if (Schema::hasTable('admins')) return;
        Schema::create('admins', function (Blueprint $table) {
            $table->bigIncrements('id');
            $table->timestamps();
            $table->string('email');
            $table->string('name');
            $table->string('password');
            $table->string('remember_token')->nullable();
        });
    }
    public function down()
    {
        Schema::dropIfExists('admins');
    }
}

Guard の設定

Guard は Auth認証用のドライバークラスで、config/auth.php に設定をします。


    'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],
        'api' => [
            'driver' => 'token',
            'provider' => 'users',
        ],
      'admin' => [
         'driver' => 'session',
         'provider' => 'admins',
      ],
    ],

Guard を設定することにより、Controllerなどに記載するミドルウェアでの認証が可能となります。


$this->middleware('auth:admin');

config/auth.php の設定

config/auth.php ファイルに Eloquent の App\Models\User クラスを設定します。
※User.php の namespace は App\Models\ に変更


    'providers' => [
        'users' => [
            'driver' => 'eloquent',
            'model' => App\Models\User::class,
        ],
       'admins' => [
        'driver' => 'eloquent',
        'model' => App\Models\Admin::class,
      ],
    ],

artisan で auth を作成する

make:auth 廃止

Laravel6 から 以下のコマンドは廃止されました。


$ php artisan make:auth

laravel/ui を利用

代わりに、「laravel/ui」でログイン画面を作成するようになりました。

更に、リリースノートには、2.0 を指定するように記載されています。


$ composer require laravel/ui "^2.0"
$ php artisan ui vue --auth

vue の部分は bootstrap などの設定もできます。

認証用ファイル

  • resources/views/auth
  • App/Http/Controllers/Auth

が作成されているので、管理者用にコピーしておくと良いでしょう。

  • resources/views/admin/auth
  • App/Http/Controllers/Admin/Auth

データベース作成

PostgreSQL


$ createdb sample_auth

MySQL


# mysql -u root
mysql > create database sample_auth;

.env

各種DBの設定を合わせる


DB_CONNECTION=pgsql
DB_HOST=postgres
DB_PORT=5432
DB_DATABASE=sample
DB_USERNAME=postgres
DB_PASSWORD=secret

DBマイグレート

DB設定が一通り完了したら、マイグレートしてみます。


$ php artisan migrate

テーブルが作成したことを確認したら、サンプルデータを作成してみます。

Seeder 作成

サンプルデータを作成する場合、artisan に seeder コマンドにも用意されています。

ユーザ、管理者の Seeder を作成すると「database/seeds/」にファイルが書き出されます。


$ php artisan make:seeder UsersTableSeeder
$ php artisan make:seeder AdminsTableSeeder

UsersTableSeeder.php


    public function run()
    {
        DB::table('users')->insert([
            'name' => Str::random(10),
            'email' => Str::random(10).'@gmail.com',
            'password' => Hash::make('password'),
        ]);
    }

AdminsTableSeeder.php


    public function run()
    {
        DB::table('admins')->insert([
                'email' => 'xxxx@xxxx.com',
                'name' => 'Admin',
                'password' => Hash::make('password')
            ]
        );
    }

DatabaseSeeder.php

Seeder ファイルが作成されたら、「database/seeds/DatabaseSeeder.php」に seeder を実行できるよう設定します。


public function run()
{
     $this->call(UsersTableSeeder::class);
     $this->call(AdminsTableSeeder::class);
}

設定したら、artisan コマンドで Seeder を実行します。


$ php artisan db:seed

実際に、テーブルにデータが作成されているか確認してみましょう。

Factory

ここでは割愛しますが、Factory の faker を利用する方法で seeder を実行できます。
Factory ファイルは以下のコマンドで作成できます。


$ php artisan make:factory UserFactory

コントローラー作成

各種コントローラーを作成します。

管理者ホーム

App/Http/Controllers/Admin/ にコントローラーを作成します。


$ php artisan make:controller Admin/HomeController

Admin/HomeController.php

ファイルを作成したら、index の実装と、コンストラクタに認証用のミドルウェアを記述(Guard で設定したパラメータ)をします。
以下の例は、管理者の認証制御となります。


    public function __construct()
    {
        $this->middleware('auth:admin');
    }

    public function index(Request $request)
    {
        return view('admin.index');
    }

ただコントローラが増えてくると、コンストラクタに毎度記述するのも面倒なので、Route のグループ設定で一括管理すると良いでしょう。
(認証用の親コントローラを継承する方法もありますが)

Route の設定

認証が必要・不要のページを考えて、グループ化した Route を設定します。

認証が不要のページ

ログイン、ログアウト、登録ページなどの認証不要のページのルートを作成します。
管理者URIは、admin で統一したいので「admin」プリフィックスを利用しています。

routes/web.php


Route::group(['prefix' => 'admin'], function () {
    Route::get('login', 'Admin\Auth\LoginController@index')->name('admin.login');
    Route::post('login', 'Admin\Auth\LoginController@login')->name('admin.login');
    Route::get('logout', 'Admin\Auth\LoginController@logout')->name('admin.logout');
    Route::post('logout', 'Admin\Auth\LoginController@logout')->name('admin.logout');
});

認証が必要のページ

認証が必要なページのルートを設定します。
ルートグループのパラメータに、ミドルウェアの Guard 設定します。


Route::group(['prefix' => 'admin/topic', 'middleware' => 'auth:admin'], function() {
    Route::get('/', 'Admin\HomeController@index')->name('admin.index');
});
pngファイルの軽量化
Google DriveのIconを再起的に削除
php-markdownでバニラPHPなコードブロック処理
laravel-ffmpeg を使う
2021年版 Ubuntu + certbot + Let's Encrypt でサーバ証明書設定
GihHub のデフォルトでない master ブランチを checkout する
マルチログインで未認証のリダイレクト
Homebrew で Redis をインストール
CSS だけでスムーズスクロール
EC-CUBE4 で Gmail の smtp を利用する
Amazon Linux 2 の amazon-linux-extras とは
UNIQUE カラムのバリデーションで自分自身を除外して更新
フォーム有効期限切れで Page Expired をリダイレクト
ログを日付でローテーションやクリアや削除
Homebrew で PHP8.0 から PHP7.4 にダウングレード
Big sur で zsh 移行と Homebrew アップグレード
Mac に minikube をインストール
途中から .gitignore に追加する
Larevel 6.x から Laravel 8.x にバージョンアップ
Composer で Allowed memory size (メモリ不足)エラー
Blade でカスタムクラスを利用する
git push git pull にブランチ指定せずに実行する
git pull や git push できなくなったとき
Docker のコンテナからホストOS に接続
Mac で ローカル IP アドレス(ipv4)のみを表示する
ホストOS から Docker の MySQLコンテナに接続
caching_sha2_password のエラー
node-config で環境設定ファイルを利用する
rootパスワードを初期化(再設定)する
Git から clone したときのエラー対処
Mac に MySQL をインストール
Mac に PostgreSQL をインストール
Laravel 環境構築 - Mac ネイティブ編
Firebase 入門 - Firebase とは
Firebase 入門 - CLI インストールとデータベースの設定
AWS 無料枠(t2.micro)で容量とメモリエラー
Cloud9 を起動する -初心者編-
gcloud で GCEインスタンスを起動してみる
AWS CLI と jq でインスタンス一覧を整形して表示
React と Laravel7 のプロジェクトを作成する
Homebrewインストール-2020年版
3直線で囲まれた範囲塗りつぶし
PuLP で線形最適化問題を解く
カスタムのペジネーションを作る
node-sass を使って sass をコンパイルする
Log ファサードでSQLログを分離して書き出す
いちから始める Docker - 複数のコンテナを使う - (2020年)
いちから始める Docker - docker-compose を使う - (2020年)
AWS ECR を使ってみる
Laravel7 でマルチ認証