- 投稿日:2020-09-08T23:34:00+09:00
【Laravel】ラズパイのDBと連携させる
ラズパイ側の操作とLravel側の操作に分けて解説していく。
DBでのユーザの作成と権限付与は別々でやる
ラズパイ側の操作
DB操作用ユーザ作成
CREATE USER 'user'@'%' IDENTIFIED BY 'pass';
%
を使用することでどんなホストでも接続ができる権限確認
登録されているユーザ名を確認
select user,host from mysql.user;特定ユーザの権限確認
show grants for 'ユーザ名'@'ホスト名';ユーザ名とホスト名は
'
か"
で囲むこと権限付与
形式GRANT [権限] ON [レベル] TO [ユーザ] IDENTIFIED BY PASSWORD '[パスワード]'権限は
- select
- update
- insert
- delete
- all
レベル 説明 GRANT [権限] ON *.* TO [ユーザ] グローバルレベル GRANT [権限] ON [DB名].* TO [ユーザ] データベースレベル GRANT [権限] ON [DB名].[テーブル名] TO [ユーザ] テーブルレベル GRANT [権限](カラム1,カラム2,...) ON [DB名].[テーブル名] TO [ユーザ] カラムレベル ポートの確認
show variables like 'port';+---------------+-------+ | Variable_name | Value | +---------------+-------+ | port | 3306 | +---------------+-------+Laravel側の操作
後は今まで得た情報を
.env
とdatabase.php
に反映するだけ
ここでは.env
だけ書いておく.envDB_CONNECTION=mysql DB_HOST=IPアドレス DB_PORT=3306 DB_DATABASE=DB名 DB_USERNAME=作成したユーザ名 DB_PASSWORD=パスワード参考
- 投稿日:2020-09-08T16:33:22+09:00
メモ書き : Laravel8 Release & Upgrade
2020/09/08 リリース。バグフィックス期間は 2021/03/08 セキュリティフィックスは2021/09/08 までという予定。
そして、新機能が多いため Upgrade の量は少ないですが、factory をゴリゴリ使っているとちょっと注意です。( migration の
schema:dump
やった後のmigrate
したときの挙動が怖そうなので、そこらへんは自己責任でしてください)アップグレードに対する更新をソースコード単位で見たい場合は Github comparision tool を見ると良いですよ。
個人的なメモ: upgrade の時は phpstan で静的解析を通すのが良いですよーよー。
[新機能] Laravel Jetstream
see : https://github.com/laravel/jetstream
新しいパッケージだそうです。
Scaffolding の livewire か Inertiaを使って、ええ感じに Vue や Tailwind CSS っぽく使って…?
なんやこれ全くわからん。bladeを抜かした管理画面を自動で作るよってことかしら。
[新機能] Model Directory
Eloquent Model の初期位置が
app/Models
の中になりました。[新機能] Model Factory Classes
factory がクラスになりました。例えば User factory が旧だとベタなPHPスクリプトだったのが、クラスで指定するようになります。
旧 Factory を使う場合は laravel/legacy-factories を使うことになります。極力書き換えるのをおすすめします。
<?php /** @var \Illuminate\Database\Eloquent\Factory $factory */ use Faker\Generator as Faker; $factory->define( \App\Eloquent\User::class, function (Faker $faker){ return [ 'name' => $this->faker->name, 'email' => $this->faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]; } );新::
<?php namespace Database\Factories; use App\Models\User; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Support\Str; class UserFactory extends Factory { /** * The name of the factory's corresponding model. * * @var string */ protected $model = User::class; /** * Define the model's default state. * * @return array */ public function definition() { return [ 'name' => $this->faker->name, 'email' => $this->faker->unique()->safeEmail, 'email_verified_at' => now(), 'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password 'remember_token' => Str::random(10), ]; } }これに伴い、Eloquent 側からfactory を作ることになるそうです。
<?php use App\Model\User; User::factory()->count(50)->create();[新機能] Migration Squash
SQL で書かれたスキーマの出力ができるようになります。出力されたスキーマは
database/schema
に保存されます。migration にも関わってくる。(後で)
php artisan schema:dump[新機能] Job Batching
Bus
でバッチ処理が追加されて、axios みたいな書き方で使えるっぽいです。<?php use App\Jobs\ProcessPodcast; use App\Podcast; use Illuminate\Bus\Batch; use Illuminate\Support\Facades\Batch; use Throwable; $batch = Bus::batch([ new ProcessPodcast(Podcast::find(1)), new ProcessPodcast(Podcast::find(2)), new ProcessPodcast(Podcast::find(3)), new ProcessPodcast(Podcast::find(4)), new ProcessPodcast(Podcast::find(5)), ])->then(function (Batch $batch) { // All jobs completed successfully... })->catch(function (Batch $batch, Throwable $e) { // First batch job failure detected... })->finally(function (Batch $batch) { // The batch has finished executing... })->dispatch(); return $batch->id;[新機能] Improved Rate Limit
Requtest Rate Limit を
throttle
ミドルウェアで制御してるが、もうちょっとフレキシブルにレートリミットを変えられるようになるっぽいです。例えば、会員ユーザのレートリミットは無し、それ以外はレートリミットは100回/分にする、とする場合は下記のように変更できるみたいです。
<?php use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Support\Facades\RateLimiter; // おそらく AppServiceProvider の中で設定 RateLimiter::for('uploads', function (Request $request) { return $request->user()->vipCustomer() ? Limit::none() : Limit::perMinute(100); });ミドルウェアの
throttole
で指定することで使える様になるみたいです。Route::middleware(['throttle:uploads'])->group(function(){ Route::post('/audio', function(){ }); Route::post('/video', function(){ }); });[新機能] Improved Maintenance Mode
php artisan down
でメンテナンスモードにした時の挙動を云々。
- --secret='1630542a-246b-4b66-afa1-dd72a4c43515'
このオプションを使うことで
/
に来たユーザは/1630542a-246b-4b66-afa1-dd72a4c43515
にリダイレクトされます。
- --render='errors::503'
このオプションを使うことで、表示するテンプレを指定することができる。
[新機能] Closure Dispatch/Chain
dispatch helper に
->catch(function(){})
ができるようになりました。おそらく、上記のBus
と同じ理屈。<?php use Throwable; dispatch(function () use ($podcast) { $podcast->publish(); })->catch(function (Throwable $e) { // This job has failed... });[新機能] Dynamic Blade Components
Blade::component('package-alert', AlertComponent::class);
で登録したコンポーネントを<x-package-alert/>
とテンプレート側に書くことで使えるようになります。クラス名は
camelCase
で書き、コンポーネント名はkebab-case
で書くみたい。Component Methods
コンポーネントテンプレート内でメソッドを動かすことができる。
/** * Determine if the given option is the current selected option. * * @param string $option * @return bool */ public function isSelected($option) { return $option === $this->selected; }<option {{ $isSelected($value) ? 'selected="selected"' : '' }} value="{{ $value }}"> {{ $label }} </option(何か vue みたいだなとぼんやり)
[新機能] Event Listener Improvements
Facade で
\Event::listen
をする時に、Queueを使うようにデコレートする事ができます。use App\Events\PodcastProcessed; use function Illuminate\Events\queueable; use Illuminate\Support\Facades\Event; Event::listen(queueable(function (PodcastProcessed $event) { // }));そして
queue job
のように細かくしてする事ができて->catch
チェインができます。Event::listen(queueable(function (PodcastProcessed $event) { // })->catch(function (PodcastProcessed $event, Throwable $e) { // The queued listener failed... })->onConnection('redis') ->onQueue('podcasts') ->delay(now()->addSeconds(10)) );[新機能] Time Testing Helpers
Carbon::now()
で返す時間を指定することができます。[新機能] Artisan serve Improvements
.env
ファイルを更新したばあいに、artisan serve
は自動に設定を読み直します。[新機能] Tailwind Pagination Views
Pagination のテンプレートに今までの Bootstrap3, Bootstrap4 の他に Tailwind が使えます。
[Upgrade] パッケージ依存
"laravel/framework": "^8.0"
"nunomaduro/collision": "^5.0"
"guzzlehttp/guzzle": "^7.0.1"
"facade/ignition": "^2.3.6"
他のパッケージを使っているばあいは、それらもアップデートしてください
- https://github.com/laravel/horizon/blob/master/UPGRADE.md
- https://github.com/laravel/passport/blob/master/UPGRADE.md
- Socialite v5.0
- Telescope v4.0
[Upgrade][Medium] Use PHP >=7.3.0
事情により PHP は 7.3.0 以上を指定してください。
[Upgrade][Low]
isset
method
Illuminate\Support\Collection
のoffsetExists
の挙動がかわりました。のでisset
で確認した時の挙動が変わります。<?php $collection = collect([null]); // Laravel 7.x - true isset($collection[0]); // Laravel 8.x - false isset($collection[0]);[Upgrade][High] Model Factories
model factories がクラス化されました。7.x までの factory を書き換えをせずに使い続ける場合は
laravel/legacy-factory
を使う必要があります。[Upgrade][Low] The Castable Interface
Castable
のcastUsing
の引数$arguments
に、array
のタイプ指定が加わりましたので、追加をしてください。[Upgrade][Low] Increment / Decrement Events
model の
update
およびsave
が動いた時にincrement
,decrement
インスタンスメソッドが動きます。[Upgrade][Low] The Dispatcher Contract
Illuminate\Contracts\Events\Dispatcher
のlisten
メソッドの第二引数$listener
の標準値にnull
を付けられました。public function listen($events, $listener = null);[Upgrade][Optional] Mentenance Mode Updates
新しく入った機能
--render
等を使う場合はpublic/index.php
を更新してください。この条件分岐の行はLARAVEL_START
の直下に書く必要があります。<?php define('LARAVEL_START', microtime(true)); if (file_exists(__DIR__.'/../storage/framework/maintenance.php')) { require __DIR__.'/../storage/framework/maintenance.php'; }[Upgrade][Low] Manager $app Property
Illuminate\Support\Manager
クラスの$app
プロパティが消えました。もしそのプロパティを使用している場合は$container
プロパティを使用してください。[Upgrade][Low] The elixir Helper
elixir
ヘルパーは削除されました。Laravel Mix に移行してください。[Upgrade][Low] Mail::sendNow Method
sendNow
メソッドは削除されました。send
メソッドを使ってください。[Upgrade][High] Pagination Defaults
Paginate の標準テンプレートが Tailwind CSS になりました。いままでの BootStrap を使い続ける場合は
AppServiceProvider
のboot
メソッドに\Illuminate\Pagination\Paginator::useBootstrap();
を記入してください。[Upgrade][High] Queue::retryAfter method / property
QueuedJob, Mailer, Notification, Listener にある
retryAfter
メソッドとretryAfter
プロパティの名前がbackoff
に変更されました。[Upgrade][High] Queue::timeoutAt property
QueueJob、Notification, Listener の
timeoutAt
プロパティがretryUntil
になりました。[Upgrade][Optional] Failed Jobs Table Batch Support
queue_driver が
database
でfailed_jobs
を使用している時に、uuid
フィールドが必要になります。<?php use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; Schema::table('failed_jobs', function (Blueprint $table) { $table->string('uuid')->after('id')->unique(); });次に
queue.php
のfailed.driver
にdatabase-uuids
を設置します。[Upgrade][Low] The cron-expression Library
Cron 書式の解析に使用している
dragonmantank/cron-expression
のバージョンが3.x
に更新されました。
下手に込み入った書き方をしている場合だと意図しない時間に動きますので、変更履歴を見て確認をする必要があります。[Upgrade][Low] The Session Contract
\Session::pull()
メソッドが追加されました。/** * Get the value of a given key and then forget it. * * @param string $key * @param mixed $default * @return mixed */ public function pull($key, $default = null);[Upgrade][Medium] Testing, The assertExactJson Method
assertExactJson
メソッドは数値キーの順番が同じである事をチェックするようになりました。順番が違っても良い場合はassertSimilarJson
を使うようにしてください。ぼんやり:: こういう事?
$asset = [ 0 =>1, 1 =>1, 2 =>1]; $data = ['1'=>1, '0'=>1, '2'=>1]; $this->assertExactJson(json_encode($asset), json_encode($data)) // => false $this->assertSimilarJson(json_encode($asset), json_encode($data)) // => true[Upgrade][Low] Database Rule Connections
unique
,exists
ルールにgetConnectionName
メソッドが追加されました。
- 投稿日:2020-09-08T15:35:06+09:00
【Laravel 】localhost/プロジェクト名/public ←publicをなくす方法
調べたところ方法はいくつかあるが一番スマートな方法かなと思ったのでメモとして残します。
.htaccessを作成する
.htaccessとは隠しファイルの1つでリダイレクトなどの設定を記述するファイルのことです。
そこに以下記述をコピペします。
<IfModule mod_rewrite.c> <IfModule mod_negotiation.c> Options -MultiViews </IfModule> RewriteEngine On RewriteCond %{REQUEST_FILENAME} -d [OR] RewriteCond %{REQUEST_FILENAME} -f RewriteRule ^ ^$1 [N] RewriteCond %{REQUEST_URI} (\.\w+$) [NC] RewriteRule ^(.*)$ public/$1 RewriteCond %{REQUEST_FILENAME} !-d RewriteCond %{REQUEST_FILENAME} !-f RewriteRule ^ server.php </IfModule>参照:https://gist.github.com/liaotzukai/8e61a3f6dd82c267e05270b505eb6d5a
vscodeなどでコードを貼り付けてLaravelのルートディレクトリに保存します。
保存しても隠しファイルなのでフォルダには表示されていません。
隠しファイルを表示させたい時はそのフォルダで
(macの場合)command + shift + .(ドット)
を入力すると表示させることができます。
以上で完了です!
localhost/プロジェクト名 でルートディレクトリへ遷移できます。
- 投稿日:2020-09-08T14:42:52+09:00
kintoneクローン? OSSWebDBのExmentをLightsail+Dockerで立ち上げたら結構ハマったのでメモしておく
Exment is 何?
Exmentは、Laravel製(ということは、LAMPですね。ということは、レンタルサーバーでも動きますね。)のWeb DBシステムです。リレーショナルなデータベースをGUI管理画面から操作できます。ExmentはOSSで、GPLライセンスです。開発は株式会社カジトリが中心となって行っています。詳細は開発者の方の記事をご覧ください。
GUIのWeb DBというと、なんとなくサイボウズ社のkintoneを連想する方もいるのではないでしょうか。
開発元からはキントーンのキの字も聞こえてきませんが、筆者はひそかにkintoneクローンだと思っていて、かなり可能性を秘めているOSSプロダクトだと考えています。
正直、かなりほれ込んでいるのですが、この記事ではお気に入りポイントは解説しません。また別の機会に。
クラウドでなるべくお安くExmentを運用したい!
ローカルでは、Dockerを使ってExmentを試すことができます。作ってくれた人ありがとう!
ローカルで実際やってみたところ(macOS Mojave、Windows 10 Home WSL2で確認)、あっさり出来ました。すごいですね。
そうしたら、クラウドでホスティングして、外出先などからもアクセスしたくなるというのが人情ですよね。
ホスティング先をいろいろ考えてみました。フロントエンドだけなら、NetlifyやVercelといった無料のサービスもあるのですが、残念ながらこれはバックエンドのシステムです…
先述していますが、Exmentはレンタルサーバーでも運用できます。
Exment公式サイトには、さくらやエックスサーバーといったレンサバでのインストール手順が公開されていますが、残念ながら、さくらやエックスサーバーのアカウントを私は持ち合わせておりません。つまり、筆者はレンサバの契約をしていないのですね。(フロント寄りの作りかけ個人プロダクトがNetlifyやVercelにはわんさかあるんですけど)
Exmentのためだけにレンサバ借りるのもなんだかなあ、だったらVPSのほうが良くない? と色々調べた結果、AmazonのLightsailが私の用途にぴったりだと気付きました。
(なお、筆者はこの時点でVPS、AWS童貞です)
ではさっそくLightsailのアカウントを取得して、始めるぞ!
Lightsailにログインしてからインスタンスの作成あたりまでは、下記記事が詳しいです。
今回は、一番安い$3.5/月の512MBRAMのインスタンスにしました。なるべくお安く、というテーマなので。どうしてもスペック足りなかったら、その時にスケールアップなりなんなり対応を考えようというスタンスです。
Lightsailには、WordPressなどのWebアプリケーションがセットになったインスタンスひな形があるのですが、当然知名度まだまだのExmentひな形というのはありません。
そこで、OSのみのインスタンスを選択します。今回は、CentoOS7を選択しました。
CentOSにフツーにインストールする? それとも…?
Exment公式には、CentOS7にインストールする手順も公開されており、またそれを補強する記事もあります。(下記参照)
が、公式を見ていただければわかる通り、結構な手順があります。で、実際1度やりました。何度か環境を捨てたりやり直したりする過程で「この手順毎回やってられんわ!」となり、他の方法を考えることに至ります。
せや、Dockerそのまま載せたったらええやん?
Lightsail+DockerでExmentを動かす(httpsもあるよ!)
ここからは、ハマりポイントを踏まえた回避策も含めて手順を記します。ここを守れば、最短でExment on Lightsail+Dockerが実現できます。
CentOS7でインスタンス作成後、Docker、Docker-composeとgitをインストールする
では、もろもろインストールしていきます。
毎回、sudo つけるの大変なので、rootになります。
Lightsailでrootになるには、こちらの記事を参考にしました。
$ sudo su -Dockerをインストールします。こちらの記事が詳しいです。
[root@ip-172-xx-xx-x ~]# yum install -y docker # dockerのインストール [root@ip-172-xx-xx-x ~]# service docker start # dockerの起動 [root@ip-172-xx-xx-x ~]# groupadd docker # ユーザー権限で実行できるようにしておく [root@ip-172-xx-xx-x ~]# usermod -g docker centos # 作成したグループにcentosユーザを追加 [root@ip-172-xx-xx-x ~]# sudo /bin/systemctl restart docker.service [root@ip-172-xx-xx-x ~]# docker infoこれでDockerはインストールできました。
続いて、Docker-composeです。[root@ip-172-xx-xx-x ~]# curl -L https://github.com/docker/compose/releases/download/1.21.0/docker-compose-$(uname -s)-$(uname -m) -o /usr/local/bin/docker-compose [root@ip-172-xx-xx-x ~]# chmod +x /usr/local/bin/docker-compose [root@ip-172-xx-xx-x ~]# docker-compose --version最後に、Gitをインストールします。CentOS7のyumで入るGitは、1.8.2と古いバージョンのものです。気になる人は、下記記事を参考に新しいのを入れてみてください。今回は、git cloneしたいだけなので、そのままyumでインストールします。
[root@ip-172-xx-xx-x ~]# yum install -y gitこれで、Gitもインストールできました。
スワップ領域を作る
RAM512MBのインスタンスなので、DockerでMySQLまで動かすとメモリ不足になりました。(ハマりポイント1)なので、先んじてスワップ領域を作っておきましょう。
スワップの作り方は下記記事を参考にしました。
[root@ip-172-xx-xx-x ~]# dd if=/dev/zero of=/swapfile bs=1M count=4096 status=progressコマンドの書き方をミスってたため、結構ハマりました(ハマりポイント2)
あれこれ試行錯誤した過程で、/dev/zeroが何のファイルかわかっておらず、rm -rfしちゃったのはいい思い出です。
/dev/zeroを復活させるのは、こちらの記事を参考にしました。
[root@ip-172-xx-xx-x ~]# mknod -m 666 /dev/zero c 1 5 [root@ip-172-xx-xx-x ~]# chown root:mem /dev/zero
status=progress
オプションですが、今回はスワップ領域が4Gと大きめなので、しばらくターミナルが沈黙しちゃうと心配です。なので、ddコマンドの進捗をお知らせしてくれるオプションをつけました。下記記事を参考にしています。ddでスワップ領域が作成されたら、粛々と残りの作業を進めます。
[root@ip-172-xx-xx-x ~]# chmod 600 /swapfile #パーミッションの変更 [root@ip-172-xx-xx-x ~]# mkswap /swapfile #スワップの作成 Setting up swapspace version 1, size = 1048572 KiB no label, UUID=d0519bf6-8abf-4c0d-9375-8068c9e5e9a1 [root@ip-172-xx-xx-x ~]# swapon /swapfile #スワップの有効化 [root@ip-172-xx-xx-x ~]# free -m #スワップの確認最後に、スワップの永続化をします。
viで/etc/fstabを開き、/swapfile swap swap defaults 0 0でおしまいです。
git cloneで、docker-compose.ymlとDockerfileを拾ってくる。
先述ご紹介した、ExmentのDockerを作ってくれた方のGithubから拾います。
[root@ip-172-xx-xx-x /home/centos/]# git clone https://github.com/yamada28go/docker-exment.git
場所はどこでもいいと思うんですけど、デフォルトユーザーディレクトリ直下にしました。
httpsは?
Dockerでhttpsというと、https-portalが有名なようです。
結論から先にいうと、https-portalを先に設定した状態でExmentをインストールしたら、上手くいきませんでした!!!(ハマりポイント3)
なので、SSLを設定する前に非SSLの状態でExmentのインストールを進めます。
一応、docker-compose.ymlに目を通しておきますか。
docker-compose.ymlversion: '3' services: nginx: image: nginx:latest ports: - 8080:80 volumes: - ./nginx/nginx.conf:/etc/nginx/conf.d/default.conf - www-data:/var/www depends_on: - php php: build: ./php volumes: - www-data:/var/www depends_on: - db db: image: mysql:5.7 ports: - 13306:3306 volumes: - mysql-data:/var/lib/mysql environment: MYSQL_DATABASE: exment_database MYSQL_ROOT_PASSWORD: secret MYSQL_USER: exment_user MYSQL_PASSWORD: secret phpmyadmin: image: phpmyadmin/phpmyadmin:latest ports: - 8888:80 depends_on: - db # volumes を定義する volumes: # volume の名前を指定 # Exmentのインストールパス www-data: # Compose の外ですでに作成済みの volume を指定する場合は ture を設定する。 # そうすると、 docker-compose up 時に Compose は volume を作成しようとしません。 # かつ、指定した volume が存在しないとエラーを raise します。 #external: true # mysql dbのインストールパス mysql-data:あとでhttps-portalが80番ポートを使うので、nginxが8080になっているのは逆に都合がいいです。特にこのまま何も編集しません。
docker-compose.ymlとDockerfileは何もさわりませんが、php.iniだけは1行だけ追記します。
最後の行に
memory_limit=-1を追記しておきます(ハマりポイント4、詳細は後述)
ではいよいよ…
[root@ip-172-xx-xx-x /home/centos/]# docker-compose up -d初回なので、イメージの取得とビルド、ボリュームの作成をやってくれます。
起動が完了したら、
docker-comopse ps
で、全コンテナがUpしていることを確認します。(スワップを作っていなかった時は、ここでMySQLがExitしてました)無事起動したら、IPアドレスでアクセスしてみよう
Lightsail側で以下の手順を済ませておきます。
- 静的IPのアタッチ
- ポート8080番の開放
xx.xx.xx.xx:8080にブラウザでアクセスしてみて、Laravelの初期画面が表示されていれば成功です。
xx.xx.xx.xx:8080/adminにアクセスすると、Exmentの初期設定画面になります。
画面は3部構成になっていて、
- 言語とタイムゾーンの指定
- DB設定
- DB設定開始ボタン
の3画面です。何か入力するのは2画面目のDB設定です。
Dockerを使っていますので「ExmentのDocker環境を作ってみた」の記事を参考に、設定を埋めます。
- ホスト名 → db
- データベース名 → exment_database
- ユーザー名 → exment_user
- パスワード → secret
この後、無事インストールが完了すれば、Exmentの初期画面となります。
添付ファイルとかはS3に保存したいじゃんね!
今回のLightsailインスタンスは、保存領域が20GBと、まあ何か動かすのはいいけど、バイナリデータ突っ込んでいったらすぐパンパンになるよね、って容量です。
Exmentには、外部のストレージサービスに各種ファイルを保存するオプションがあります。
せっかくですので、AWSでそろえて、S3に保存させるようにしてみましょう。
S3も童貞でしたので、下記記事を参考にバケットを作成してみました。
Exment側でも設定が必要です。既に
docker-compose exec php bash
で立ち上がっているコンテナの中に入ります。[root@ip-172-xx-xx-x /home/centos/]# docker-compose exec php bashこれで、Exmentが動いているphpコンテナの中に入れます。プロンプトの表示がこんな感じに変われば成功です。
root@f54bef27801a:/var/www#つまり、クラウド上にあるLightsailの中にあるDockerコンテナphpの中にいるという二重構造なわけですね。
引き続き、「(上級者向け)ファイルの保存先変更」を読み解きながら、Exment(Laravel)のファイルを修正していきます。
Exmentルートフォルダにある、.envファイルをvimで修正/追記します。
EXMENT_DRIVER_EXMENT=s3 EXMENT_DRIVER_BACKUP=s3 EXMENT_DRIVER_TEMPLATE=s3 EXMENT_DRIVER_PLUGIN=s3 AWS_ACCESS_KEY_ID=(AWS S3のアクセスキー) AWS_SECRET_ACCESS_KEY=(AWS S3のシークレットアクセスキー) AWS_DEFAULT_REGION=(AWS S3のリージョン) AWS_BUCKET_EXMENT=(添付ファイルで使用するAWS S3のバケット) AWS_BUCKET_BACKUP=(バックアップで使用するAWS S3のバケット) AWS_BUCKET_TEMPLATE=(テンプレートで使用するAWS S3のバケット) AWS_BUCKET_PLUGIN=(プラグインで使用するAWS S3のバケット)なお、
EXMENT_DRIVER_xxx
はすべて設定する必要はなく、必要があるものだけ設定します。それに紐づくAWS_BUCKET_xxx
も必要なものだけでOKです。私は添付ファイルとバックアップデータはS3に保存したかったので、
EXMENT_DRIVER_EXMENT
EXMENT_DRIVER_BACKUP
AWS_BUCKET_EXMENT
AWS_BUCKET_BACKUP
の4つのみ設定しました。
最後に、composerでライブラリをインストールします。
先ほど、
docker-compose up -d
の前にphp.iniを編集しましたが、Composerはメモリ食いで、すぐPHPのメモリ利用可能上限に達してしまうので、この上限を解除する設定をしたのでした。Composerはインストールに時間がかかるので、時間かかった結果失敗した、って辛いですよね…(筆者はとても悲しかったです。)なので、この設定は
composer require
をする前にもう一度確認しておきましょう。root@f54bef27801a:/var/www# php -i | grep memory_limit memory_limit => -1 => -1-1になっていればOKです。(メモリ上限なし、の意味)
では、いよいよライブラリのインストールです
root@f54bef27801a:/var/www# composer require league/flysystem-aws-s3-v3 ~1.0 -vvv
-vvv
オプションは、もっとも粒度細かくログを出す、という意味の指示です。composerはインストールにとても時間がかかるので、長い時間ターミナルが沈黙していると心配になります。なので、逐次ログを出してくれるようにします。このオプションをして長いこと沈黙があれば、それは本当に何かしらの理由で止まっているか、めちゃくちゃ重い処理をしている、ということになります…
S3に添付ファイルをアップするオプションの設定は以上です。適当な画像でもアップして、バケットの中にファイルがあることを確認しましょう。
最後に呪いのhttpsです…
いや、httpsに何の悪いところもないのですが、かなりハマって悩まされたので…
色々やり方が悪かったのかと思い、Docker環境全捨てからの再インストールを何度も行ったので、かなり時間を食ってしまいました。
さっきも言いましたが、docker-composeにhttps-portalも混ぜて書いてしまうと、初回インストールに失敗します。結局はよくわからんエラーに遭遇して詰みました。
インストールは3画面あるといいましたが、最後の3画面目のインストールボタンを押したら、あのLaravelのグレーみの強いエラー画面で
Use of undefined constant STDIN - assumed 'STDIN' (this will throw an Error in a future version of PHP)って出てきて、DBにデータが差し込めないことに。PHPやLaravelに明るくない筆者であるため、ここで断念しました。
httpならちゃんとうまくいったので、結局このエラーをつぶすことはあきらめ、httpでインストール完了させ、その後httpsにするという作戦に切り替えた次第です。
https-portalをdocker-compose.ymlに追記する
https-portalの部分だけ書き出します。
docker-compose.ymlhttps-portal: image: steveltn/https-portal:1 ports: - '80:80' - '443:443' links: - nginx restart: always volumes: - ./certs:/var/lib/https-portal environment: STAGE: 'production' DOMAINS: >- example.com -> http://nginx:8080 depends_on: - php特に難しいことはありません。公式のサンプルとそんなに変わりませんし。ポイントとしては、
enviroment:
のSTAGE:
が、'production'
か'staging'
でないと、Let's Encryptの本チャンの証明書はもらえないということです。ここがlocalとか指定なしだと、ローカル開発ってことで、なんちゃって証明書が発行されます。ここも地味にハマりポイントでした(ハマりポイント5)さて、最後に https://example.com/ にアクセスして、Laravelの初期画面が表示されれば晴れて成功です…
と言いたいのですが、まだあります。
https://example.com/admin にアクセスすると、盛大に画面崩れを起こしているじゃないですか!
ブラウザコンソールを見ると、mixed contentでhttpがソースのCSS/JS類が全部ブロッキングされています。
これの対処が最初全然わからなかったのですが、試行錯誤の結果、LaravelおよびLaravel-adminが犯人と断定されました! asset('/css/hoge.css')みたいな記述のところで、http付のパスを出力しちゃってるようです…
以下、この件についての対策です。また
docker-compose exec php bash
して中に入ってください。/var/www/exment/.envAPP_ENV=production/var/www/exment/app/Providers/AppProvider.phpclass AppServiceProvider extends ServiceProvider public function boot() { if (config('app.env') === 'production') { \URL::forceScheme('https'); //Schemaじゃなくて、Scheme!!!(ハマりポイント6) } }/var/www/exment/config/admin.php/* |-------------------------------------------------------------------------- | Access via `https` |-------------------------------------------------------------------------- | | If your page is going to be accessed via https, set it to `true`. | */ 'https' => env('ADMIN_HTTPS', true), // ←デフォはfalseなので、trueに!これで、すべてのアセットがhttpsから配信され画面崩れなく表示されるようになりました。
正直、これが本当の意味で正解かどうかわかりません。もしかしたら、AppProvider.phpは不要かもしれません… Laravelのバージョンによってコードの書き方が微妙に違うようでした。これは、本当にたくさんの参考ソースを読みまくって、なんとか動くコードに落ち着いたというのが実情です。
もし、もっと良い方法があるよ、という方はぜひコメント欄で教えてください。
以上、無事動くようになりました!
今のところ、機嫌よく動いてくれています。
セキュリティ等
本記事は検証目的の環境づくりのため、セキュリティ等については触れておりません。詳しい方は補足いただけると助かります。
今後
Exmentの素敵なところをほめまくる記事とか書きたいですね!
- 投稿日:2020-09-08T13:04:57+09:00
LaravelでFirebase Admin SDK for PHPを利用する(トークン再取得編)
Firebase Admin SDK for PHPでは、自動でトークン取得はできないっぽい
例えば、Javascriptなら以下のように
currentUser.getIdToken()
で取得できる。
期限切れ前に自動で更新してくれるので便利。firebase.auth().currentUser.getIdToken(/* forceRefresh */ true).then(function(idToken) { // Send token to your backend via HTTPS // ... }).catch(function(error) { // Handle error });Firebase Admin SDK for PHPには似たような機能はなかった。
トークンが切れるたびにいちいちログインし直すのもなんだか嫌。解決方法
// ログインしていない場合 if(!Session::get('token')){ $signInResult = $this->auth->signInAnonymously(); Session::put('token', $signInResult->idToken()); Session::put('refresh_token', $signInResult->refreshToken()); } // トークン認証 try { $auth->verifyIdToken(Session::get('token')); } catch (\Exception $e) { // ここはExpiredTokenとかに絞った方が良い // 期限切れなら更新トークンを使って再取得 $refresh_token = Session::get('refresh_token'); $signInResult = $auth->signInWithRefreshToken($refresh_token); Session::put('token', $signInResult->idToken()); }流れは以下のような感じ。
1)ログイン時の結果にrefresh_token
があるので、セッションか何かに取っておく。
2)トークンが期限切れになったらverifyIdToken()
で例外が発生するので、signInWithRefreshToken()
で再取得リフレッシュトークンが変更されるタイミングはそんなにないので、とりあえず使いたい場合は上記で間に合うと思う。
- 投稿日:2020-09-08T10:06:50+09:00
Laravel オリジナルの設定ファイルを作成してコントローラで呼び出す
目的
- Laravelの設定ファイルへの追記方法と設定ファイルの読み込み方法をまとめる
- ※本説明でいう設定ファイルとは.envファイルではなく、
アプリ名ディレクトリ/config
直下にあるファイルを指す実施環境
- ハードウェア環境
項目 情報 OS macOS Catalina(10.15.5) ハードウェア MacBook Pro (13-inch, 2020, Four Thunderbolt 3 ports) プロセッサ 2GHzクアッドコアIntel Core i5 メモリ 32 GB 3733 MHz LPDDR4 グラフィックス Intel Iris Plus Graphics 1536 MB
- ソフトウェア環境
項目 情報 備考 PHPバージョン 7.4.3 Homwbrewを用いて導入 Laravelバージョン 7.0.8 commposerを用いてこちらの方法で導入→Mac Laravelの環境構築を行う MySQLバージョン 8.0.19 for osx10.13 on x86_64 Homwbrewを用いてこちらの方法で導入→Mac HomebrewでMySQLをインストールする 前提条件
- 実施環境に記載した環境、またはそれに準ずる環境が用意されておりLaravelアプリが作成されていること。
前提情報
- 筆者は下記の記事で作成したアプリを用いて本記事の動作を確認する。
- 下記に本記事を記載する際に検証で使用したソースコードのリモートリポジトリのリンクを下記に記載する。
読後感
アプリ名ディレクトリ/config
直下の設定ファイルに独自の設定を追記することができる。アプリ名ディレクトリ/config
直下の設定ファイルに記載されている値を読み込み表示することができる。概要
- 設定ファイルの作成と記載
- ルーティング情報の追記
- コントローラファイルの作成と記載
- ビューファイルの作成と記載
- 確認
詳細
設定ファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行して設定ファイルを作成する。
$ vi config_test.php開いたファイルに下記の内容を追記し保存して閉じる。
アプリ名ディレクトリ/config/config_test.php<?php return [ # 文字列の設定 'config_str' => 'これは設定ファイルで設定された文字列です。', ] ?>ルーティング情報の追記
アプリ名ディレクトリで下記コマンドを実行してルーティングファイルを開く。
$ vi routes/web.php下記の内容を追記する。
アプリ名ディレクトリ/routes/web.phpRoute::get('/config_check', 'ConfigCheckController@config_check')->name('config_check');コントローラファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行してコントローラファイルを作成する。
$ php artisan make:controller ConfigCheckControllerアプリ名ディレクトリで下記コマンドを実行してただいま作成したコントローラファイルを開く。
$ vi app/Http/Controllers/ConfigCheckController.php下記の様に記載を行う。
アプリ名ディレクトリ/app/Http/Controllers/ConfigCheckController.php<?php namespace App\Http\Controllers; use Illuminate\Http\Request; // 下記を追記する use Illuminate\Support\Facades\Config; class ConfigCheckController extends Controller { // 下記を追記する public function config_check() { // アプリ名ディレクトリ/config直下に存在するconfig_test.phpファイルで定義されているconfig_strの文字列を$strに格納する処理 $str = Config::get('config_test.config_str'); return view('checks.config_check', [ 'str' => $str, ]); } // 上記までを追記する }ビューファイルの作成と記載
アプリ名ディレクトリで下記コマンドを実行してビューファイルを格納するディレクトリを作成する。
$ mkdir resources/views/checksアプリ名ディレクトリで下記コマンドを実行してビューファイルを作成する。
$ vi resources/views/checks/config_check.blade.php開いたビューファイルに下記の内容を記載する。
アプリ名ディレクトリ/resources/views/checks/config_check.blade.php{{ $str }}確認
アプリ名ディレクトリで下記コマンドを実行してローカルサーバを起動する。
$ php artisan serveブラウザで下記にアクセスする。(Authの認証機能が付与されているLaravelアプリで下記にアクセスする場合、ログインが必要になる場合がある。)
下記の様に、設定ファイルに記載した内容がブラウザ上で表示されていれば作業完了である。
*画像
参考文献
- 投稿日:2020-09-08T09:41:27+09:00
ドメイン駆動設計における5層アーキテクチャの全体図とソースの実装例
今回の記事では、過去に記述した以下のバックエンドに関する記事を一つに統合した内容となっている。
従来のドメイン駆動設計の4層アーキテクチャにDCIアーキテクチャを組み込んでいく過程で、様々なパラダイムが発生し、
最終的に4層アーキテクチャにミッション層を追加した5層アーキテクチャという形に落ち着いた。
今回の記事では、投稿した過去の記事の内容を5層アーキテクチャによって概念を整理し、整合性を担保している。投稿した過去の記事一覧
・ドメイン駆動設計のユースケース層(アプリケーション層)を軍事思想(作戦術)でドーピング
https://qiita.com/aLtrh3IpQEnXKN7/items/853ecb3cd109dd016476・OOUI(オブジェクト指向設計)によるバックエンド設計のパラダイムシフト
https://qiita.com/aLtrh3IpQEnXKN7/items/3aa05f9628544c43f279・DCIアーキテクチャの活用方法を紹介
https://qiita.com/aLtrh3IpQEnXKN7/items/355ad12f82ac424abea3・エリック・エヴァンスが提唱したアーキテクチャの4層モデルを拡張する
https://qiita.com/aLtrh3IpQEnXKN7/items/b7fe2014ccefcbb9e458・ドメイン駆動設計のミッション層を設計する手法を紹介
https://qiita.com/aLtrh3IpQEnXKN7/items/98e0c2d2ee0776e0e039・5層アーキテクチャモデルにおけるドメイン分析
https://qiita.com/aLtrh3IpQEnXKN7/items/e5d1a276c07f1fe140be各レイヤーの説明
レイヤーの全体図
1.コントロール層
アプリ外からアクセスの入り口となるインターフェースを主にRestApiで提供する。アプリ外からのアクセスがWeb、iOS、Androidと増加するたびにインターフェースを追加する必要がある。
インターフェース以外の機能として、コントロール層からユースケース層へデータを受け渡す際のデータ変換、コントロール層からアクセス元へのデータ変換(JSON化)を行う。データの受け渡し、データ変換機能をメインに担当する。2.ユースケース層
ビジネスロジックで実現したい目的を記載するための層。ミッション層のメソッドの呼び出しのみを行う。
ユースケース層では、フロントエンドから取得したデータを格納するためのBeanクラスを必ず用意する。
Beanクラスをミッション層へ引数として渡し、ミッション層内で具体的なロジック内容を実装する。ユースケース層のビジネスロジックは以下の種類で実装する。
偵察・・・画面に表示するデータを取得する
順次・・・ビジネスのワークフローを順番通りに進める
ゲリラ・・・不定期に行われるイベント処理を実施する
監視・・・DB内部の情報を監視し、アプリの規約に違反したユーザーの発見などを行う
エスカレーション・・・アプリのルールに違反しているユーザーへの通知、警告などを行う
エマージェンシ・・・緊急事態に対応する
相対・・・キャンセル処理などビジネスのワークフローから外れる例外処理3.ミッション層
具体的なビジネスロジックを記述するための層。ビジネスロジックはDCIアーキテクチャによって実装が行われる。
この層では、ユースケース層で実現したい目的をドメイン層のメソッドを組み合わせて実現する。
以下の観点で、ドメイン層のメソッドを組み合わせロジックを作成する。イベント・・・DBへデータを書き込む事象
リソース・・・企業が取り扱うサービス or 商品
ルール・・・イベントに紐づく運用ルール
テクノロジー・・外部ライブラリを使用して実装されるメールの転送やファイルアップロード
エージェント・・・ミッション層のロジックを統率する。イベント、リソース、テクノロジーのメソッドが全て集約する。4.ドメイン層
ミッション層のロジックを構成する層。ミッション層内でメソッドの呼び出しが行われる。
ドメイン層では、アプリ全体で共通するデータ構造の取得、共通するデータ構造に依存した業務ルールの提供、データ集約に基づいたデータ登録 or 更新 or 削除処理を取り扱う。5.インフラ層
外部ライブラリを使用したロジックを記述し、全レイヤーに外部ライブラリの機能を提供する。例としてメールの送信、ログの出力などが該当する。
ライブラリはバージョンアップや使用するライブラリ変更されるなど、頻繁に発生する箇所する。そのため、DIP(依存関係逆転の原則)に従って、
ドメイン層にインターフェースを配置し、実際のロジックはインフラ層に記述する。インターフェースをデータインジェクション(依存性注入)機能を利用してインタンス生成を行う。実装するクラス一覧
各レイヤー層に記述するクラス一覧について記載
1.コントロール層
Controller・・・REST APIの提供、Convetクラスのメソッドの呼び出し、ユースケース層の画面レベルのメソッドの呼び出し、
Web用、Andoroid、iOSへ引数を返却する際の値変換(JSON化)など
Coverter・・・REST APIから取得した画面の入力値の値をユースケース層へ引き渡す際の値の変換2.ユースケース層
Bean・・・コントロール層から取得した入力値を格納して、ユースケース層へ引き渡す際のクラス。getter setterでメソッドを構成。表示画面と1対1の関係にある。
SearchOperation・・・検索したデータを画面表示することを目的としたビジネスロジック
RegularOperation・・・ビジネスのワークフローを次状態に進めるデータ登録、更新処理を目的としたビジネスロジック
GuerrillaOperation・・・ゲリライベントで発生するデータ登録、更新、削除処理を目的としたビジネスロジック
MonitoringOperation・・・DBのデータを監視し、規約違反が発見した場合、規約違反のデータ登録、更新、削除処理を目的としたビジネスロジック
EscalationOperation・・・エスカレーションラダーを設定し、規約違反を起こしているユーザーに各エスカレーションに応じた通知処理を目的としたビジネスロジック
EmergencyOperation・・・緊急事態対応を目的としたビジネスロジック
IrregularOperation・・・従来のビジネスのワークフローから外れるデータ登録、更新、削除処理を目的としたビジネスロジック3.ミッション層
Mission ・・・Beanクラスを引数として受け取り、Beanクラスに対応したActorクラスのインスタンス、Actorクラスの型となるRoleインターフェスの選択、Roleメソッドの実行を行う。
Actor・・・Roleインターフェースを実装するクラス。Mixinを使用して多重継承を実施。
Role・・・インターフェース。ミッション層のEvent、Resource、Rule、Technologyのメソッドを集約する。ミッション層のロジックを組み合わせ ユースケース層で実現したいロジックを実装する。
Event・・・DBの登録 or 更新 or 削除に関する事象を実装するクラス。ドメイン層の、Aggregates、Servicesの組み合わせで実装される。
Resource・・・企業が取り扱う商品 or サービスのデータをDBから取得するクラス。ドメイン層の、Value Objects、Factories、Entities、Repositoriesの組み合わせで実装される。
Rule・・・運用ルールを実現するクラス。ドメイン層の、Specification、Value Objects、Factories、Entities、Repositoriesなどのメソッドの組み合わせで運用ルールを実現する。
Technology・・・技術的なビジネスロジックを実装するクラス。インフラ層のメソッドとインフラ層のメソッドを組み合わせて実現する。4.ドメイン層
Factorys・・・DTOクラスを引数とし、ValueObjectインスタンスを生成
ValueObject・・・共通構造クラス。DTOをフィールド変数として持ち、getterメソッドとisメソッドのみで構成されている。DTOのデータを加工して提供、DTOのデータに応じたif分の提供などを行う。
Specifications・・・ビジネスルール or 入力値チェックなどのビジネスロジックを提供する
Repositorys・・・DBからデータ検索処理を行うクラス。
Aggregates・・・特定のデータ範囲に応じて、データの登録、更新、削除を行うクラス。
Services・・・上記で上げたドメイン層のロジックに分類できない処理を取り扱うクラス。5.ドメイン層
Mail・・・メール送信を行う。
SFTP・・・SFTPによるデータ送受信を行う。
FileUpload・・・ファイルアップロードを行う。