[Laravel 備忘録] Laravel Sail作成したプロジェクトにLaravel Adminで管理画面導入

小規模プロジェクトの場合、フロント画面しか必要ないようなプロジェクトもある(あるよね?)

そんな時、実装していない機能なんかはDBを直接操作したり、phpMyAdminとかを管理画面代わりに使ったりするケースもある(あるよね?)

でもlaravelにはlaravel adminがある。

https://laravel-admin.org/docs/en/

簡単に言うと、管理画面を自動で実装してくれるツール。

LaravelのModelの定義とかを見て、例えばroleのカラムはプルダウンで選択肢から選んだりできるのでphpMyAdminよりは遥かに便利な管理画面となる。

管理画面からGUIで管理メニュー自体を新たに作ることもできる。

本記事は、これを実装する手順の備忘録である。

Laravelを使ったプロジェクトの作成は以前の記事を参照するべきである。

Laravel Adminもコマンドで導入

sailでlaravelプロジェクトを作った場合はこんな感じで導入。

sail composer require encore/laravel-admin

sail artisan vendor:publish --provider="Encore\Admin\AdminServiceProvider"

sail artisan admin:install

インストールが無事に完了すれば、http://localhost/admin/ にアクセスするとログイン画面がでる。

2020年12月現在、Laravel Adminの推奨環境がLaravel 5.5。

今構築した環境がLaravel 8でPHP7.4、MySQLは5という状態なので推奨環境とは程遠い状態なので動くか不安だったけど動いたでござる。

このままだと管理者がいないので、ログインできないよねと思ったけど、適当にadmin/adminと入力したらログインできた。

ところどころエラーが出ているみたいだけど、動く部分だけで動作するようになってるみたい。

柔軟で素晴らしい考えだと思う。

初期状態だと管理ユーザーを管理する画面が実装されている。

artisanにadminコマンドが追加されている。

管理画面で使うファイルはこのコマンドから作ることになる。

$ sail artisan admin

略
                                                                          
Laravel-admin version 1.8.14

Available commands:
 admin:make             Make admin controller
 admin:controller       Make admin controller from giving model
 admin:menu             Show the admin menu
 admin:install          Install the admin package
 admin:publish          re-publish laravel-admin's assets, configuration, language and migration files. If you want overwrite the existing files, you can add the `--force` option
 admin:uninstall        Uninstall the admin package
 admin:import           Import a Laravel-admin extension
 admin:create-user      Create a admin user
 admin:reset-password   Reset password for a specific admin user
 admin:extend           Build a Laravel-admin extension
 admin:export-seed      Export seed a Laravel-admin database tables menu, roles and permissions
 admin:minify           Minify the CSS and JS
 admin:form             Make admin form widget
 admin:permissions      generate admin permission base on table name
 admin:action           Make a admin action
 admin:generate-menu    Generate menu items based on registered routes.
 admin:config           Compare the difference between the admin config file and the original

一般ユーザーを管理する機能を追加

どんなサービスでもほぼ確実に実装するであろう会員管理の機能をLaravel Adminで実装してみよう。

最初からあるUserモデルを扱うコントローラーをartisanで作成。

ドキュメントでは、

php artisan admin:make UserController --model=App\\User

こうなっていますが、Laravel8系からはモデルのディレクトリがapp/Modelsに変更になっているので注意。

※ 参考サイト

https://qiita.com/Dev-kenta/items/25ac692befe6f26f11cf


sailということも考慮してこんな感じで実行するのがいいのかな

sail artisan admin:make UserController --model=App\\Models\\User

実行すると色々メッセージがでるので言われるとおりに/app/Admin/routes.php に変更を加えよう

App\Admin\Controllers\UserController created successfully.

Add the following route to app/Admin/routes.php:

    $router->resource('users', UserController::class);
<?php

use Illuminate\Routing\Router;

Admin::routes();

Route::group([
    'prefix'        => config('admin.route.prefix'),
    'namespace'     => config('admin.route.namespace'),
    'middleware'    => config('admin.route.middleware'),
    'as'            => config('admin.route.prefix') . '.',
], function (Router $router) {

    $router->get('/', 'HomeController@index')->name('home');

    // ここに追加
    $router->resource('users', UserController::class);

});

この状態で管理画面をみる

http://localhost/admin/users

にアクセスするとこんな感じ。

Laravel Breezeの動作確認用に追加したユーザーがちゃんと編集とかできるようになってる。

管理画面からメニューリンクを追加

このままだとURLを直接入力しないとページが表示されないので不便。

管理メニューのmenuのリンクから、http://localhost/admin/auth/menu を開いて以下のようにメニュー自体を追加しよう。

URIはadmin以降のURLを入力(今回はusers)。

その他は適当でOK。色々いじるといいでしょう。

メニュー追加後は、画面の再読み込みとかをしないと反映されないので注意。

ちょっとカスタマイズしてみる

Userの管理画面自体は最低限できているけどこのままだと結構不便なので、UserController.phpを最低限修正しよう。

一覧画面ではパスワードの項目自体非表示に

grid()で一覧表示の項目を変更できる。今回はパスワードとremember_tokenの項目をコメントアウトして対応。

    protected function grid()
    {
        $grid = new Grid(new User());

        $grid->column('id', __('Id'));
        $grid->column('name', __('Name'));
        $grid->column('email', __('Email'));
        $grid->column('email_verified_at', __('Email verified at'));
//        $grid->column('password', __('Password'));
//        $grid->column('remember_token', __('Remember token'));
        $grid->column('created_at', __('Created at'));
        $grid->column('updated_at', __('Updated at'));

        return $grid;
    }

編集時、パスワード項目は変更できないように

form()が追加・編集時のフォームの決め事。ここもコメントアウトして対応。

    /**
     * Make a form builder.
     *
     * @return Form
     */
    protected function form()
    {
        $form = new Form(new User());

        $form->text('name', __('Name'));
        $form->email('email', __('Email'));
        $form->datetime('email_verified_at', __('Email verified at'))->default(date('Y-m-d H:i:s'));
//        $form->password('password', __('Password'));
//        $form->text('remember_token', __('Remember token'));

        return $form;
    }

まとめ

CRUDの基本操作だけで済むならLaravelAdminは超便利ツール。

ただ、枠から外れた操作を実装する場合は、逆にめんどくさいこともあるかも。

GUIでメニュー増やせるのはいいけど、逆にGUIじゃないとメニューすら増やせない(できるかもしれんけど大変)ので、一長一短。

小規模プロジェクトならLaravelAdmin、そうじゃないなら独自で管理画面を作るのがいいと思う。

[Laravel 備忘録] Laravel Sail作成したプロジェクトにLaravel Breezeで認証系入れるとこまで

大体どんなシステムでも必要になる認証系の仕組みをLaravel Sailで作成したプロジェクトにBreezeで導入してみるところまでの備忘録

Laravel Sailについては以下参照

コマンドを打ってほとんどの作業が完了

sailコマンドのパスが通っている状態まで進んでいるなら↓でOK

sail composer require laravel/breeze --dev

sail artisan breeze:install

sail npm install

sail npm run dev

sail artisan migrate

やっていることは、

composer を更新して、artisanでbreezeをインストール、npmでnode環境を整えて最後にmigrateかな。

(とにかくこれで動くんであんまり考えてない)

エラーが出てる場合

よく遭遇するエラーのひとつがこれ

SQLSTATE[42000]: Syntax error or access violation: 1071 Specified key was too long; max key length is 767 bytes (SQL: alter table `users` add unique `users_email_unique`(`email`))

MySQLのインデックス最大長が変わったことで発生するエラー

AppServiceProviderに以下の記述を追加すればindexが短くなるので解決

Laravelで開発すると大体最初にいじるのがここですね(笑

use Illuminate\Support\Facades\Schema;

public function boot()
{
  Schema::defaultStringLength(191);
}

修正したら忘れずにmigrateしなおし

http://localhost にアクセスして、認証用のメニューが出ていたらOK

会員登録画面もあるしログインしてダッシュボードも見れる

会員登録画面
ログイン後のダッシュボード

Mailhogの設定

Breezeに含まれるリマインドメール機能を使うにはメールサーバーが必要。開発環境ならMailhogが最初から入っているので.envファイルを修正しておく

.envの例(適当でOK)

MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=admin
MAIL_PASSWORD=123456
MAIL_ENCRYPTION=null
MAIL_FROM_ADDRESS=admin@admin.com
MAIL_FROM_NAME="${APP_NAME}"

これで開発環境だといちいちややこしいメールの挙動もMailhogで確認できる

Mailhogには http://localhost:8025/ でアクセス

リマインドメールが確認できた様子

ところどころ日本語なのは最終的に調整すればいいんじゃないのかなと思う。

一応各箇所で翻訳関数を噛ませているので、翻訳ファイルを用意しておけば一括で変換可能。

おさえておくポイント

Laravelのこういう自動作成機能は便利なんだけど、自動過ぎてどのファイルが変更されたのかわからない弊害もあるので、要所だけまとめておく。

web.php

ルーティングを設定するファイルroutes/web.php

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

});
// ↓認証してないと見られない/dashboardへのrouteが追加されてる(ルート名はdashboard)
Route::get('/dashboard', function () {
    return view('dashboard');
})->middleware(['auth'])->name('dashboard');

require __DIR__.'/auth.php';

この記述を参考に、例えばログインした人しかアクセスできないルートを追加するにはこんな感じにする↓

Route::get('/memberonly', function () {
    return view('memberonly');
})->middleware(['auth']);

Authenticate.php

ログインの有無に応じて処理を判定しているのが app/Http/Middleware/Authenticate.php

    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('login');
        }
    }

特に触ることは無いと思う。ログイン後のURLを変えたい時とか?

ログインユーザーの情報を取得する方法

認証スターターキットをインストールし、ユーザーがアプリケーションへ登録・認証できるようにした後、多くの場合は現在認証済みのユーザーを操作する必要があります。受信リクエストの処理時、Authファサードのuserメソッドを使用して認証済みユーザーにアクセスできます。

use Illuminate\Support\Facades\Auth;

// 現在認証しているユーザーを取得
$user = Auth::user();

// 現在認証しているユーザーのIDを取得
$id = Auth::id();

その他細かくはこちらから
https://readouble.com/laravel/8.x/ja/authentication.html

まとめ

とりあえず会員登録、ログイン認証ができるところまで完了。

なれれば10分もあれば完了するんじゃないかな。

[Laravel 備忘録] Laravel Sailでプロジェクト作成してDockerで動かすまで

久々にLaravelで開発することになったので、認識の確認がてらメモ

便利と噂のLaravel Sailでプロジェクト作成して、管理画面をLaravel-Admin、ユーザーログイン周りをLarabel Breezeを使って実装するまでのの手順をまとめる

ちなみにRedisとかよくわからんし、本番環境で使えないこともある(?)と思うし今回は使いません

開発環境はmac + Docker

Laravelインストーラーを使ってlaravel11のプロジェクト作る

laravel/installerをv5.8以上に更新

composer global require laravel/installer

これでOK

laravel -V

↑でバージョンが4.0以上なのをチェック

Laravel Installer 5.8.0

エラー出てたら –with-all-dependencies オプションなどで解決すること

composer global require laravel/installer  --with-all-dependencies

Laravel Sailのインストール

composer require laravel/sail --dev

こんだけ

Sailでプロジェクト作成

既存プロジェクトにSailを組み込むのもできるみたいだけど今回は公式で言ってるcurlを使って新規にプロジェクト作成する。

今回はプロジェクト名kirin-appとする

この名前のディレクトリが作成されるのでワークスペースディレクトリで実行するのがいい

curl -s "https://laravel.build/kirin-app" | bash

結構時間がかかるのでコーヒーを飲みながら待つ

毎回これに5分くらいかかる。最終的にパスワードを求められるのでmacのパスワードを入力。

ディレクトリに入って /vendor/bin/sail up すればコンテナが立ち上がるけどその前に設定を最低限見直しておく。
最低限phpMyAdminは入れておく必要ある

(必要に応じて)docker-compose.ymlの編集

PHPのヴァージョン変更

標準でPHP8になってるけど、現状PHP8を使う予定がないので7にしておくなど

# context: ./vendor/laravel/sail/runtimes/8.1
↓
# PHP 7.4
context: ./vendor/laravel/sail/runtimes/7.4

イメージ名もPHPのバージョンにあわせ変更します。

# image: sail-8.1/app

# 変更後
image: sail-7.4/app

MySQLを5.6に

同様にMySQLのバージョン変更はこう

# image: 'mysql/mysql-server:8.0'
# ↓変更後
image: 'mysql/mysql-server:5.6'

phpMyAdminを入れておくこれは大事

あれば便利インデントに気をつけて以下をコピペ

    phpmyadmin:
        image: phpmyadmin/phpmyadmin
        links:
            - mysql:mysql
        ports:
            - 8080:80
        environment:
            MYSQL_USERNAME: '${DB_USERNAME}'
            MYSQL_ROOT_PASSWORD: '${DB_PASSWORD}'
            PMA_HOST: mysql
        networks:
            - sail

http://localhost:8080 にアクセスすればphpMyAdminが表示される。
ログイン情報は.envファイルを参照する(基本的にプロジェクト名がユーザーIDでパスワードはpassword)

Sailを起動

設定できたらSailをupしよう

cd kirin-app
./vendor/bin/sail up

初回upはイメージファイルを作るとこからなので、これまた時間かかる。コーヒーを飲みながら待とう

ymlファイルいじったせいでエラーが出てる場合は、composer updateかけてまたsail upすると大体解決すると思う

完了したら http://localhost/ にアクセスすればLaravelの初期画面が出るはず。

トラブルが無ければ、コマンド2発でここまで行く。

途中、2回待つ時間があるので暇つぶしの用意をして望むのがいいだろう。

sailコマンドをaliase登録

sailで作ったプロジェクトは./vendor/bin/sailコマンドをよく使うことになる、パスが長いのでエイリアス登録しておく(相対パスのエイリアスになるから複数プロジェクトあってもOK)

alias sail='[ -f sail ] && bash sail || bash vendor/bin/sail'

~.bash_profileに上記を追加して以下を実行

source ~/.bash_profile 

これでsailと打てばコンテナ上でコマンドが実行されるようになった

migrateを実行して準備完了

sailのパスを通したら以下のコマンドを打てば初回migrateが完了する

sail artisan migrate

すごい便利

コンテナを自作する場合

Sail便利だけど環境が特殊すぎる時コンテナは1から作ったほうが楽かもそんな場合は過去記事を参照

まとめ

なんか長くなったけど、インストーラーやパスが通っている状態なら以下のコマンドを打つだけで最後まで行く

curl -s "https://laravel.build/kirin-app" | bash
cd kirin-app
sail up
sail artisan migrate

途中待つ時間必要だけど、長くても30分位じゃないかな

ほとんどオートで完了するので、頻繁に開発環境を整える人とかはLaravelを検討したほうがいいと思う。

次はのプロジェクトにLaravel Breezeで認証系つけていく

[Laravel備忘録] Secified key was too longエラーの対処法

Laravelで開発してると頻繁に出くわすこのエラー

SQLSTATE[42000]: Syntax error or access violation: 1071 
Specified key was too long; max key length is 767 bytes 

MySQLの環境次第では、インデックスできるキーは768バイトまでなので環境によってはこれが弊害になるので解決策をまとめます。

原因

Laravelの文字コードはLaravel5.4以降utf8mb4を使うようになりました。

以前はutf8。

utf8では1文字3バイトだったものが、絵文字範囲をカバーするためにutf8mb4では1文字4バイトになっています。

そのため、制限の767バイトを超過してしまい、MySQLのエラーが出力されることに。

解決法(2こ)

MySQLの設定を変更できる場合

my.cnfに以下の記述をすればOK

[mysqld]
innodb_large_prefix
innodb_file_per_table
innodb_file_format=Barracuda

innodbのファイルフォーマットがBarracudaになるので、インデックス長さが拡大されるので解決。

MySQLの設定を変更できないならLaravel側で対応

AppServiceProviderに以下の記述を追加すればindexが短くなるので解決

use Illuminate\Support\Facades\Schema;

public function boot()
{
  Schema::defaultStringLength(191);
}

[Docker備忘録]php7 apache memcache mysqlのセットアップまとめ


運用プログラムの修正などでdockerで開発環境を作るときに便利なように、開発部分だけを一個のディレクトリに突っ込めば動くDockerの準備のための備忘録

↓この状態を目指す

├── _docker (Docker関連はここにまとめる)
│   ├── apache-php(Apacheサーバー用ディレクトリ)
│   │   ├── Dockerfile (webサーバビルド用Dockerfile)
│   │   └── httpd.conf (Apache設定ファイル)
│   └─ mysql-db (mysqlファイル保存)
├── deploy (この中にソースファイル入れてコンテナと共有)
│    └─ public (ドキュメントルート)
│       └ index.php
├── docker-compose.yml (docker-compose の設定ファイル)
├── docker-compose-dev.yml (docker-compose の設定ファイル)
└── docker-sync.yml (docker-sync の設定ファイル)

開発環境がmacなのでdocker-syncも導入する。(これがないと30倍くらい描画時間掛かる)

Docker Compose 概要

Docker composeは複数のコンテナから成るサービスを構築・実行する手順を自動的にし、管理を容易にする機能。

compose ファイルを用意してコマンドを1 回実行することで、設定を読み込んですべてのコンテナサービスを起動することができる。

大体web+DBプラスアルファで構築するんじゃないかな

Docker Compose を使うまでの主なステップ

  • それぞれのコンテナのDockerfile を作成(今回はウェブサーバーのみ)
  • docker-compose.yml を作成し、それぞれ独立したコンテナの起動定義
  • “docker-compose up” コマンドを実行してdocker-compose.yml で定義したコンテナを起動

docker-syncの導入

$ gem install docker-sync

brew 自体のアップデートしておくその他、必要に応じて以下など

$ brew upgrade
$ brew upgrade fswatch

各ファイルの補足説明

docker-compose.yml

複数のコンテナそれぞれがどんな役割か定義するファイル

docker-compose-dev.yml

docker-compose-dev.yml は、ボリュームとマウントのオーバーライドを定義します。

docker-sync.yml

docker-sync.yml は、同期に関する設定を定義します。

docker-compose.yml

version: "3"

services:
  web:
    build:
      context: ./apache-php
    ports:
      - 80:80
    privileged: true
    links:
      - db
      - memcached
    volumes:
      - "../deploy:/var/www/html"
    container_name: "kirin"
    command: /sbin/init
    stdin_open: true
  db:
    image: mysql:5.7
    volumes:
    - "./mysql-db/:/var/lib/mysql/"
    environment:
      MYSQL_DATABASE: db_development
      MYSQL_USER: root
      MYSQL_PASSWORD: root
      MYSQL_ROOT_PASSWORD: root
    container_name: "mysql_kirin"
  phpmyadmin:
    image: phpmyadmin/phpmyadmin:latest
    links:
      - db
    ports:
      - 8080:80
    environment:
      - PMA_ARBITRARY=1
      - PMA_HOST=db
      - PMA_USER=root
      - PMA_PASSWORD=root
    container_name: "phpmyamin_kirin"

  memcached:
    image: memcached:1.4
    container_name: "memcached_kirin"
    ports:
      - "11211:11211"

container_nameは自由につけよう僕の場合は大体アプリケーション名を使っています

docker-compose-dev.yml

version: '3'

services:
  web:
    volumes:
      - kirin_syncs:/var/www/html

volumes:
  kirin_syncs:
    external: true

docker-sync.yml

version: '2'

syncs:
  kirin_syncs:
    src: './deploy'

docker-compose.ymlで各コンテナの設定、docker-compose-dev.ymlでどのボリュームをsync対象にするか設定、docker-sync.ymlでどのローカルボリュームとsyncさせるか設定って感じ?

本番環境はdockerで構築してないので別にファイル分けない定義方法があるかもしれないけど、よくある設定にならって記述。

Dockerfile

Dockerfileの記述方法は人それぞれ僕の場合はyumで必要なパッケージを導入、その他必要に応じてライブラリなど入れてる
httpd.confは毎回同じ箇所を編集しているので、設定済みのconfファイルを用意しておいてそれをコピペして使う所まではビルド時に行うようにしている

FROM centos:7.4.1708

RUN yum -y update

RUN yum -y install less

# 外部リポジトリ(EPEL, Remi)を追加
RUN yum -y install epel-release
RUN yum -y install http://rpms.remirepo.net/enterprise/remi-release-7.rpm

# apache その他 phpパッケージを導入
RUN yum -y install httpd
RUN yum -y install --enablerepo=remi,remi-php73 -y php php-cli php-common php-devel php-fpm php-gd php-mbstring php-mysqlnd php-pdo php-pear php-pecl-apcu php-soap php-xml php-xmlrpc php-pecl-memcache libmcrypt php-mcrypt
RUN yum install -y ImageMagick ImageMagick-devel
RUN yum -y install zip unzip

RUN yum -y install make
RUN yum -y install php73-php-pecl-zip.x86_64


RUN pecl install imagick

# composerのインストール
RUN curl -sS https://getcomposer.org/installer | php
RUN mv composer.phar /usr/local/bin/composer


ENV    APACHE_LOG_DIR=/var/log/apache2 \
        APACHE_LOCK_DIR=/var/lock/apache2 \
        APACHE_RUN_DIR=/var/run/apache2 \
        APACHE_PID_FILE=/var/run/apache2.pid

# httpd.conf上書き
COPY ./httpd.conf /etc/httpd/conf/httpd.conf


# Apacheの自動起動設定
RUN systemctl enable httpd
CMD ["/sbin/init"]

WORKDIR /var/www/html

httpd.confのデータはググるか以下からもダウンロードできますhttps://kirinblog.net/wp-content/uploads/2021/12/httpd.conf_.txt

docker-syncを実行

docker-sync は docker-sync-stack start で実行


docker-sync.yml を変更した場合は、必ず docker-sync clean を実行してから、 docker-sync-stack start を実行

便利なdockerコマンド

コンテナに入る

docker container exec -it コンテナ名 bash

今回の場合は

docker container exec -it kirin bash

コンテナ名は

docker-compose ps

で見ることができます。docker container psより得られるコンテナIDでもOK


ビルド後、失敗していたら削除して再ビルドする時のコマンド

docker-compose up -d --no-deps --build <service_name>


だいたい1つ2つ間違えるので、最初環境整えるときよく使うコマンド
–no-deps – 紐づいている他のサービスを起動しない
–build – コンテナを起動する前にビルドをする<service_name>にはコンテナ名ではなく、docker-compose.ymlのサービス名を入れるのに注意。
上記の例だと、kiringではなく、webになります。docker-compose up -d –no-deps –build web

間違えて最初から全部やり直したい場合のコマンド


docker-compose down --rmi all --volumes

これでコンテナを止めてネットワーク削除してボリューム削除からのイメージ削除が一括で終わる

なんどもミスった点

webコンテナが動いてるのにApacheが動いていない
-> サーバー内にドキュメントルートがないとApache起動時にエラーが出るのでコンテナ立ち上げる前にpublic/index.php作っておく