- 投稿日:2019-04-17T23:53:00+09:00
Laravel5.8で指定したテーブルのマイグレーションだけロールバックする
経緯(大した言ってないので、飛ばしてください)
特に新規開発に多いと思うのですが、開発するアプリのビジネスロジックがガチッと固まりきっていない&テストデータをすでに入れちゃってる時ってスキーマ変更が結構発生しますよね(あくまで個人的にそう思う)。
以前まではphp artisan migrate:rollback
もしくはphp artisan migrate:rollback --step=xx
一旦全部ロールバックしてた(だって 公式ドキュメント?にこれしか書いてないんだもん)んですが、これって対象テーブル以外もロールバックされる(migrationの仕方によっては)のでテストデータを失うので、ちょっとツライ...
せめて同時にマイグレーションした他のテーブルには影響しないようにしたい...
ってことでググったら指定したテーブルだけロールバックする方法が見つかったのでメモ。ロールバック
$ php artisan migrate:rollback --path=/database/migrations/2019_01_27_130520_create_****_table.php Migration not found: 2019_02_01_134904_create_****_table Rolling back: 2019_01_27_130520_create_****_table Rolled back: 2019_01_27_130520_create_****_table Migration not found: 2019_01_27_125630_create_****_tableマイグレーション
$ php artisan migrate:rollback --path=/database/migrations/2019_01_27_130520_create_****_table.php個人的にこれからはこの手のことで困ったら
--path=
を指定を試してみようって覚えとくことにしました![]()
- 投稿日:2019-04-17T23:45:54+09:00
LaravelでDBのデフォルト文字セットと照会順序を変更する
使用するMySQLのデフォルト文字セットと照会順序と、Laravelの設定を合わせたい時に。
使いたいMySQLの設定
Laravelの設定を変えるため、database.phpを編集する
config/database.php'mysql' => [ 〜略〜 // 'charset' => 'utf8mb4', // 'collation' => 'utf8mb4_unicode_ci', 'charset' => 'utf8', 'collation' => 'utf8_general_ci', 〜略〜 ],これでmigrationでテーブルを作り直せば、文字セットと照会順序が統一できる。
参考
https://qiita.com/n-funaki/items/6ce33602d096da0968f4
https://www.playfulit.net/articles/kzvXJM6YfWT1mUP492odNfBR
- 投稿日:2019-04-17T22:41:00+09:00
ValetでLaravel開発環境を構築してみた
概要
MacミニマニストのためのLaravel開発環境である「Valet」を実装してみました。
注意事項、留意点
- 基本的には公式ドキュメントを参考にしてます
- というよりほぼこれを見ながらやりました
- Valetは「ベレット」と読むらしいです
前提条件
- バージョン
- OS: MacOS 10.14.2
- Homebrew: 2.0.5 (当時の最新版)
- 更新日
- 2019/04/17
構築手順
1. Homebrewのインストール
- ここでは割愛します
- 基本的には公式ページを参照するといいと思います
- 私はこちらをはじめとしたQiita記事を参考にしました
brew doctor
でYour system is ready to brew.
と出てこればOKらしいです- 私は以下のようなメッセージが出ましたが、「気にするな」と書いてあるので気にせず次に進みました
Please note that these warnings are just used to help the Homebrew maintainers with debugging if you file an issue. If everything you use Homebrew for is working fine: please don't worry or file an issue; just ignore this. Thanks!2. インストール
- php7.3をhomebrewでインストールします
brew install php
composerをインストールします
- ここでは割愛します。私は以前curlで入れたもので問題なかったので、brewでなくてもいいらしいです
Valetをインストールします
- これによりValetとDnsMasqがインストール/設定され、システム起動時に起動するValetのデーモンが登録されるとのことです。
composer global require laravel/valet valet install3. サイト動作
- 任意の場所でディレクトリを作成し、移動します
(ここではlaravel/valet/
を再帰的に作成します)mkdir -p laravel/valet/ cd laravel/valet/
- parkコマンドを実行します
- サイト検索の親ディレクトリとして登録されるとのことです
valet park
- pathsコマンドで、実際にparkされたかを確認します
valet paths
- 以下のような形で出力されればOKです
[ "/********/laravel/valet" ]
- Laravelプロジェクトを作成します
(ここではstartlaravel
という名前のLaravelプロジェクトを作成します)laravel new startlaravel
- サイトを動かします(http://{プロジェクト名}.test/で開きます)
http://startlaravel.test/参照
以下のサイトを参考にしました。
- 投稿日:2019-04-17T22:37:40+09:00
Laravel でDBのテーブルを全削除して作り直す
既存のtableをリセットしたい、または、接続先のDBを変更した、というようなときに。
全tableを削除して、マイグレーションを初めから実行するartisanコマンド。
php artisan migrate:fresh.envを書き換えてDBを変えた場合、先にcacheクリアする。
php artisan cache:clear php artisan config:clear
- 投稿日:2019-04-17T22:36:28+09:00
LaravelのGateを使ってルーティングにアクセスコントロールを実装する
はじめに
LaravelでのWebアプリケーションの開発をしていて、ログイン中のユーザーのロール毎にアクセス可能なルーティングのコントロールを実装する必要がでてきました。
Laravelの認可の機能である、ゲートを使った簡単なルーティングへのアクセスコントロールを実装したので、やったことを書いておきます。
なお、ここではゲートをルーティングに実装する基本のみで、ログイン認証の実装などには触れません。やりたかったこと
以下、簡単なプロジェクト管理システムを開発している前提で進めます。
ログインユーザーのロールは4種類あります。
- 管理者
- リーダー
- マネージャー
- メンバーそれぞれのロール毎に使える機能を制限したかったので、アクセスできるURIを設定するのがやりたいことでした。
ロール毎にアクセス可能なURIは次の表の様になります。
URI 機能 管理者 リーダー マネージャー メンバー /manage_member メンバーの管理 ○ × × × /add_project プロジェクトの追加 ○ ○ × × /edit_project プロジェクトの編集 ○ ○ ○ × /view_project プロジェクトの閲覧 ○ ○ ○ ○ ログインユーザー毎にロールをもたせるためにrolesテーブルとusersテーブルを次の様に設計しました。
テーブル設計
roles テーブル
id name 1 管理者 2 リーダー 3 マネージャー 4 メンバー users テーブル
id name role_id 1 管理者山田 1 2 リーダー鈴木 2 3 マネージャ伊藤 3 4 メンバー加藤 4 ゲートの記述
ここでは、特定のルーティングにアクセスする許可があるかどうかの定義をします。定義には、ログイン中ユーザーの
role_id
で判別します。app/Providers/AuthServiceProvider.php/** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); // メンバーの管理ができるロール Gate::define('manage_member', function (User $user) { // ゲートは常に最初の引数にユーザーインスタンスを受け取ります。 return $user->role_id === 1; // 管理者 }); }この記述をすることで、Laravelのミドルウェアで
canミドルウェア
を使った認可をすることができます。
次のコードがcanミドルウェア
をLaravelのルーティングroutes/web.php
で使う例になります。routes/web.php// このルーティングには`メンバーの管理ができるロール`のみアクセスできる Route::group(['middleware' => 'can:manage_member'], function () { Route::get('/manage_member', 'MemberController@manage'); });続きのコードも書いていきます。
app/Providers/AuthServiceProvider.php/** * Register any authentication / authorization services. * * @return void */ public function boot() { $this->registerPolicies(); // メンバーの管理ができるロール Gate::define('manage_member', function (User $user) { return $user->role_id === 1; // 管理者 }); // プロジェクトの追加ができるロール Gate::define('add_project', function (User $user) { return in_array($user->role_id, [1, 2], true); // 管理者とリーダー }); // プロジェクトの編集ができるロール Gate::define('edit_project', function (User $user) { return in_array($user->role_id, [1, 2, 3], true); // 管理者とリーダー、マネージャー }); // プロジェクトの閲覧ができるロール Gate::define('view_project', function (User $user) { return in_array($user->role_id, [1, 2, 3, 4], true); // 管理者とリーダー、マネージャー、メンバー }); }定義したゲートをルーティングで使う
routes/web.php// このルーティングには`メンバーの管理ができるロール`のみアクセスできる Route::group(['middleware' => 'can:manage_member'], function () { Route::get('/manage_member', 'MemberController@manage'); }); // このルーティングには`プロジェクトの追加ができるロール`のみアクセスできる Route::group(['middleware' => 'can:add_project'], function () { Route::get('/add_project', 'ProjectController@add'); }); // このルーティングには`プロジェクトの編集ができるロール`のみアクセスできる Route::group(['middleware' => 'can:edit_project'], function () { Route::get('/edit_project', 'ProjectController@edit'); }); // このルーティングには`プロジェクトの閲覧ができるロール`のみアクセスできる Route::group(['middleware' => 'can:view_project'], function () { Route::get('/view_project', 'ProjectController@view'); });許可のないロールでアクセスした場合、ミドルウェアは403ステータスコード(Forbidden/アクセス拒否)を返します。
おわりに
以上がゲートを使ったルーティングへの認可の実装でした。
Laravelの認可には、ルーティング以外にもモデルやアクション単位で認可のロジックを導入する仕組みがありますので、詳しくは公式ドキュメント Laravel 5.7 認可 をご覧ください。
- 投稿日:2019-04-17T21:48:22+09:00
Laravel Homestead でLaravel 開発環境を構築してみた
概要
Laravel HomesteadというLaravel公式の仮想マシンで、
Laravel開発環境を構築してみました。
ここではその構築手順を記載します。このLaravel Homesteadでは必要なソフトウェアが仮想環境内に入っていて、
ローカルマシンにそれぞれインストールせずに環境構築を完了できます。
Laravel公式ページで推奨されているやり方です(2019/04/01当時)。注意事項、留意点
- 基本的には公式ドキュメントを参考にしてます
- というよりほぼそれを見て構築しました。
- 他の仮想化ソフトウェアでもOKらしいです(VMWareなど)が、無料なのでVirtualBoxを使いました。
前提条件
- バージョン
- OS: MacOS 10.14.2
- VirtualBox: 6.0.4
- Vagrant: 2.2.4
- laravel: 5.8
- 更新日
- 2019/04/17
実際の手順
1. VirtualBoxのインストール(インストールしてない場合のみ)
- VirtualBoxからダウンロードします
- お使いのOSのhostsを選んでクリックし、ダウンロードします
- ダウンロードされたdmgファイルをクリックします
- pkgファイルのアイコンが表示されるので、それをダブルクリックしします
- そのあとはインストール画面に則ってインストールします
- 「安全でないアプリケーション」等が出てインストールできない場合は、以下を確認してください
- 左上のアップルマーク →「システム環境設定」 →「セキュリティとプライバシー」
- 左下の鍵マークをクリックしてインストールの許可を行ってください
- VirtualBoxがアプリケーションに表示されていればOKです
2. Vagrant のインストール(インストールしてない場合のみ)
- Vagrantからダウンロードします
- お使いのOSを選んでクリックし、ダウンロードします
- ダウンロードされたdmgファイルをクリックします
- pkgファイルのアイコンが表示されるので、それをダブルクリックします
- そのあとはインストール画面に則ってインストールします(怒られたらVirtualBoxと同様に対応してください)
- ターミナルで
vagrant -v
を叩いて、バージョン情報が表示されればOKです(こちらはアプリケーションに出ません)3. Homestead Vagrant Boxのインストール
- Laravel用のボックス(ベースとなるイメージ)であるHomestead Vagrant Boxを以下コマンドでインストールします
- これを叩くことで、複数の環境で laravel/homestead ボックスを呼び出せるようになります
vagrant box add laravel/homestead
- 途中provider を選択する箇所があるので、VirtualBoxを選択します
- 問題なくいけば成功です
- Vagrantのバージョンが古い場合に失敗する可能性があるらしいので、その場合はバージョンを確認してみてください
4. Homesteadのインストール
- Homestead をリポジトリからクローンします
git clone https://github.com/laravel/homestead.git ~/Homestead
- masterだと安定しない可能性があるため、バージョンタグがついたHomesteadをチェックアウトします
(私が見た時の最新バージョンはv8.2.0
でした)cd ~/Homestead git checkout v8.2.0
Homestead.yaml
設定ファイルを生成する用のバッシュコマンドを実行します
(init.sh
ファイルの中をみたらわかりますが、resourceディレクトリ内のyamlファイルをコピーしているだけです)bash init.sh5. Homesteadの設定
Homestead.yaml
内のprovider
をvirtualbox
に書き換えます
(デフォルトがvirtualbox
になっていたので書き換え不要でしたが、一応確認しましょう)provider: virtualbox
Homestead.yaml
内のfolders
を書き換え、共有フォルダを設定します (ここでは/laravel/environment_homestead/
ディレクトリを作って、この中のディレクトリ全てをHomestead環境と同期するようにします)folders: - map: ~/laravel/environment_homestead to: /home/vagrant/code type: "nfs"6. Nginxの設定
Homestead.yaml
内のsites
を書き換え、Nginxを設定します (ここではstartlaravel
という名前のlaravelプロジェクトをあとで作成することを前提としています)sites: - map: homestead.test to: /home/vagrant/code/startlaravel/public7. hostsファイルの書き換え
/etc/hosts
ファイルに以下を追加し、ローカルドメインへのリクエストをHomesteadに転送されるようにします192.168.10.10 homestead.test8. Vagrantの起動、ssh接続
- 以下コマンドでvagrantを起動します
vagrant up
- 以下コマンドでssh接続します
vagrant ssh9. vagrant内でLaravelプロジェクトを作成
- 以下コマンドで
code
ディレクトリに移動して、laravelプロジェクトを作成します
(ここではstartlaravel
というプロジェクトを開始しますが、何でも構いません。ただし6で行ったNginxの設定と同じディレクトリルートにしましょう)vagrant@homestead:~$ cd code vagrant@homestead:~/code$ composer create-project --prefer-dist laravel/laravel startlaravel10. サイトを開く
参照
以下のサイトを参考にしました。
- 投稿日:2019-04-17T21:17:08+09:00
CleanArchitectureとLaravelとTransaction
【概要】
CleanArchitectureにおいてデータの整合性を担保するためにUseCaseでトランザクション処理を行うと、Application Business RulesがFramework & Driversに依存することになります。
これは図の依存の矢印とは逆向きに依存してしまうため違反することとなります。
この記事では実際にUseCaseでトランザクション処理を行うサンプルコードと違反することなくデータの整合性を担保する方法を提示します。なおサンプルコードにはLaravelを用います。【対象読者】
- CleanArchitectureを学習中の方
- CleanArchitectureにおけるデータの整合性に関してお悩みの方
【例題】
[題材]
店舗の口コミサイトを例にします。このサイトでは口コミを投稿することでポイントがもらえるものとします(他の仕様を考え出すと本筋から脱線してしまうため非常に簡易ですが、ここではこの仕様だけ考えます)
口コミとポイントのテーブル設計は下記の通りだとします。
- 口コミテーブル
review_id shop_id content 1 101 良かった 2 102 イマイチ 3 102 悪かった
- ポイントテーブル
point_id review_id point 201 1 50 202 2 50 203 3 100 [クラス図]
口コミ投稿におけるクラス図を作成しました。
[サンプルコード]
PostReviewInteractor.phpuse Illuminate\Support\Facades\DB; class PostReviewInteractor implements PostReviewUsecase { private $reviewRepository; private $pointRepository; private $presenter; public function __construct(IReviewRepository $reviewRepository, IPhotoRepository $pointRepository, IPostReviewResultPresenter $presenter) { $this->reviewRepository = $reviewRepository; $this->pointRepository = $pointRepository; $this->presenter = $presenter; } public function handle(PostReviewInputdata $inputData) { try { DB::beginTransaction(); $review = $this->reviewRepository->save($inputData->getShopId(), $inputData->getContent()); $point = $this->pointRepository->save($inputData->getShopId(), $inputData->getPath()); $outputData = new PostReviewSuccessOutputData($review->getId(), $point->getId()); $this->presenter->complete($outputData); DB::commit(); } catch (\Exception $ex) { DB::rollBack(); $outputData = new PostReviewFailedOutputData($ex); $this->presenter->failed($outputData); } } }[問題点]
コード動いてそうだし問題なくね?と思いきや、
DB::beginTransaction(); DB::commit(); DB::rollBack();ユースケースでDBトランザクション制御を行なっていることに気づきます。
概要に記載したCleanArchitectureの図を見るとUse Casesが所属するApplication Business RulesはDBが所属するFrameworks & Driversの内側に位置することが分かります。依存の矢印は外から内へ向いているためユースケースがDBトランザクション処理を行うのは違反していると考えられます。【解決案】
トランザクション以外の方法を用いたデータの整合性を担保を考えます。まず整合性に関してですが、ACID特性とBASE特性の2通りがあります。ACID特性とBASE特性に関しての詳細は こちらの記事 が分かりやすかったので、参考にしていただけると幸いです。ここではACID特性の一貫性とBASE特性の結果整合性に関して触れます。それぞれの概要は下記の通りです。
- 一貫性
- DB内のデータに矛盾のない事を常に保証します。
- 結果整合性
- 最終的に整合性とれてればいい。
UseCaseにおいてトランザクション処理を出来ないということで、一貫性は妥協して結果整合性を担保することを考えることになると思います。
結果整合性を担保する手法の1つとしてキューを用いた手法を提示します。
例題のサンプルコードでは口コミ投稿とポイント登録を同一サービスにて行なっていましたが、口コミサービスとポイントサービスに分割します。口コミサービスでは口コミ投稿とポイントキューへのエンキューを行い、ポイントサービスではポイントキューからデキューしDBに登録を行います。
クラス図は下記の通りです。【まとめと謝辞】
UseCaseにおいてトランザクション処理を行うと違反してしまうため、トランザクション処理によるデータの整合性の担保ではなく他の方法を用いる必要がある。しかしトランザクション処理が出来ないためACID特性ではなくBASE特性を考える必要がある。
なお実際にキューを用いた手法を考えると冪等性など他にも考えなければいけないことが出てきます。これに関してまとめきる事が出来ませんでした。 こちらの記事 を参考にすると良いと思います。
他の記事に丸投げしてしまい申し訳ありません。
- 投稿日:2019-04-17T20:26:32+09:00
初心者がlaravelをロリポップレンタルサーバーに導入した手順
初心者でもlaravelをレンタルサーバーに導入!
- 今まで生のPHPかcodeigniterしか使ったことない完全なlaravel初心者。
- なので初心者目線で色々書いてます。(主にターミナルへの愚痴)
- なんかみんなAWSとかばっかだけど、laravelを導入したい既存のサイトのサーバーがロリポップだったのでなんとかしてみた。
- macで実行してます。
- laravel5.5
- こちらのサイトめちゃくちゃ参考にしました。この記事で行き詰まった方はこちらもご参考ください。
ロリポップにcomposerをインストールしてLaravel5.5を公開する
前提条件
ロリポップでSSHが使えること。
つまりはスタンダードプラン、エンタープライズプランの契約であること。php 7.1に設定していること(これもロリポップのユーザーページにて)
まずはロリポップのユーザーページでSSH認証
ターミナルからロリポップに入る!
ターミナルは怖くない!
もう本当にターミナルが苦手…(泣)
しかし頑張りましょう。
ターミナルがなんぞやって方はググってください。
超抵抗がある方はありそうですが、意外とコピペが上手にできればなんとかなります。まずはターミナルでこちらを入力。
$ ssh アカウント名@サーバー名 -p接続ポートこのアカウント名やサーバー名が?な方はご安心を、
先ほどのSSHを認証したところと同じ画面にもう一度行けば全部綺麗に書いてくれてますので
そのままコピペしましょう。そしてエンター!パスワード入力
上記のコマンドがうまくいくとパスワードを求められます。
password:ってだけ!
パスワードはSSHのパスワードです!
こちらもさっきのページにのっています。
自分はここで延々とロリポップのパスワードとかを打って弾かれてました。
SSHパスワードが勝手に発行されてるとは…。ディレクトリの移動
パスワードの入力もうまくいくと、
ターミナルが[アカウント名~]$とだけいきなり出してきます。
(可愛くなさすぎてヤバイ。OKくらい言ってくれ。)ここでターミナルのコマンドである
lsと入力すると、
webとだけまた出してくれます…。
けどこれで一応正解です。このwebという中に入りたいので
ターミナルのコマンドのcd webといれます。必ずスペース(空白)は必要です。
すると
[アカウント名 web]$と分かりづらいですがちゃんとwebの中に入れました!
ちなみに後で気づいたのですが、
今いる位置はロリポップFTP開いた最初のページにいる感じです!
ここにlaravelが入った「フォルダ」をインストールするのです。composerをインストール
PHPやってたら嫌というほど出てくるこの人。
laravelはこのcomposerを通してインストールするので、まずはこの人をインストールするしかない!/usr/local/php7.1/bin/php -r "eval('?>'.file_get_contents('https://getcomposer.org/installer'));"こちらをコピペでターミナルに打ち込みます。
意味はわからなくていいと思います。(よくない)するとインストールが開始されます!
すごい!Composer (version 1.8.5) successfully〜〜〜
と出ればOK。
(2019/4/16現在)確認したい人は、ロリポップFTPの最初のページに
composer.phar
があることを確認できるはずです。PHPのPATHを通します。
export PATH="$PATH:/usr/local/php7.1/bin"このままコピペでOKですが、PATHとは?とか興味ある方は調べてみてください〜。
ちなみにこれを入力してエンターしてもターミナルは何も言いません。
けどエラーとかも出しません。
なんて冷たい…。あとはlaravelをインストールするだけ!
/usr/local/php7.1/bin/php composer.phar create-project --prefer-dist laravel/laravel フォルダ名 "5.5.*"laravelは5.7も出ているようですが、情報の多い5.5にしてます。
(2019/4/16現在)フォルダ名はlaravelを公開したい独自ドメインで指定しているフォルダ名です。
ロリポップのユーザーページの「独自ドメイン設定」からご確認を!ここで
独自ドメインの公開(アップロード)フォルダについて大事な補足!上記のフォルダ名はだいたい、
example.comとかなら
example
となっていますが、
laravelを使う場合は、
example/public
とする必要があります。
laravelをインストールしたら分かりますが、中にpublicというフォルダがあり
ここが公開フォルダのためです。なのでロリポップの独自ドメイン設定の部分の確認・変更で
先に変更しておきましょう。(一瞬です)ちなみに当然ですがターミナルに打ち込むフォルダ名はexampleの部分だけでOKです。
さて仕切り直して、
さきほどのコマンドをターミナルを入力したら、
バーーーーーーとインストールが始まります。
数分はかかります!set successfully.と出ればOK。
というデフォルトページが!
これにてlaravelの導入完了です!
がここで
500エラー出た方。
実は自分も最初の30分くらい500エラーでした。
色々情報を探し実行しましたが変化なし…
調べ終わって意気消沈してる時に、もう一回更新したらさらっと表示されました・・・・・。多分ですが、直前でレンタルサーバーのPHP設定を7.1に変えたりしていたのでその反映に時間がかかったのかなぁと思っています。
こういうケースに該当する場合は少し待ってみたら改善されるかも…。
- 投稿日:2019-04-17T18:17:36+09:00
51歳からのプログラミング 備忘 laravelで複数モデルを変数に格納して操作してみたい
<?php // ---------------------------- // <課題>認証されたIDに対応する、他の従テーブルのフィールド情報を取得してみる // ・ 下記は、laravel\app\Http\Controllers\Controller // ・ 従テーブル名を、laravel\config\model_name.phpに、配列に用意 // ・ foreachで従テーブル名を取り出し、'App\\'.$valueを作成して変数$model_fieldに格納 // ・ $model_fieldのフィールド情報を取得 public function getTest() { $user=Auth::user(); $model_name=config('model_name.model_name'); foreach($model_name as $value) { $model_app='App\\'.$value; $model_field=$model_app::where('user_id',$user->id)->first(); }
- 投稿日:2019-04-17T16:32:55+09:00
Laravelで認証用APIのテストを書く
Laravel + Vue.jsを勉強している際に、APIを利用した認証でログアウトを確認するためのUnitテストで、便利なアサーションがあったので、備忘録として記録
前提
- Laravel5.8(5.5~)
テストケースの作成
Laravelのドキュメントルート上で、以下コマンドを実行する
php artisan make:test AuthenticationTestテストコード
tests/Feature/AuthenticationTest.php<?php namespace Tests\Feature; use App\User; use Tests\TestCase; use Illuminate\Foundation\Testing\WithFaker; use Illuminate\Foundation\Testing\RefreshDatabase; class AuthenticationTest extends TestCase { use RefreshDatabase; protected $user; public function setUp(): void { parent::setUp(); // テストユーザ作成 $this->user = factory(User::class)->create(); } /** * ログイン認証テスト */ public function testLogin(): void { // 作成したテストユーザのemailとpasswordで認証リクエスト $response = $this->json('POST', route('login'), [ 'email' => $this->user->email, 'password' => 'password', ]); // 正しいレスポンスが返り、ユーザ名が取得できることを確認 $response ->assertStatus(200) ->assertJson(['name' => $this->user->name]); // 指定したユーザーが認証されていることを確認 $this->assertAuthenticatedAs($this->user); } /** * ログアウトテスト */ public function testLogout(): void { // actingAsヘルパで現在認証済みのユーザーを指定する $response = $this->actingAs($this->user); // ログアウトページへリクエストを送信 $response->json('POST', route('logout')); // ログアウト後のレスポンスで、HTTPステータスコードが正常であることを確認 $response->assertStatus(200); // ユーザーが認証されていないことを確認 $this->assertGuest(); } }参考サイト
- 投稿日:2019-04-17T02:24:27+09:00
[Laravel]保存した画像が404エラーで表示されない
問題
画像を取得して表示させようとしたときに、データを取得してくることまではできたのですが、表示すると404エラーがでてきて、パスは間違っていないのに、表示できませんでした。
開発環境
PHP :7.2.15
Laravel :5.6画像の取得、表示については公式リファレンスや他の記事等で書いてあることを参考にしていたのですが、大まかには以下の流れです。
解決方法
画像自体のパスは間違っていなかったので、「Public」のシンボリックリンクのパスを調べたところ下のように「storage -> /Users/[ユーザ名]/laravel/application/storage/app/public」となっていました。
root@qw2b32a12s7e:/var/www/public# ls -la total 32 drwxr-xr-x 13 root root 416 Apr 10 03:56 . drwxr-xr-x 27 root root 864 Apr 10 02:56 .. drwxr-xr-x 3 root root 96 Apr 1 08:07 css -rw-r--r-- 1 root root 6148 Apr 10 07:53 .DS_Store -rw-r--r-- 1 root root 0 Apr 1 08:07 favicon.ico -rw-r--r-- 1 root root 593 Apr 1 08:07 .htaccess -rw-r--r-- 1 laradock www-data 1823 Apr 1 08:07 index.php drwxr-xr-x 3 laradock laradock 96 Apr 1 08:07 js -rw-r--r-- 1 root root 70 Apr 1 08:07 mix-manifest.json -rw-r--r-- 1 root root 24 Apr 1 08:07 robots.txt lrwxr-xr-x 1 root root 56 Apr 10 03:56 storage -> /Users/[ユーザ名]/laravel/application/storage/app/public -rw-r--r-- 1 root root 914 Apr 1 08:07 web.configStorageのシンボリックリンクを変更します。↓
root@qw2b32a12s7e:/var/www/public# ln -nfs /var/www/storage/app/public storage↑のコマンドを入力するとStorageのパスが「storage -> /var/www/storage/app/public/」に変更され、画像が表示されました。
root@qw2b32a12s7e:/var/www/public# ll total 32 drwxr-xr-x 13 root root 416 Apr 10 08:20 ./ drwxr-xr-x 27 root root 864 Apr 10 02:56 ../ -rw-r--r-- 1 root root 11 Apr 9 08:41 aaa.html drwxr-xr-x 3 root root 96 Apr 1 08:07 css/ -rw-r--r-- 1 root root 6148 Apr 10 07:53 .DS_Store -rw-r--r-- 1 root root 0 Apr 1 08:07 favicon.ico -rw-r--r-- 1 root root 593 Apr 1 08:07 .htaccess -rw-r--r-- 1 laradock www-data 1823 Apr 1 08:07 index.php drwxr-xr-x 3 laradock laradock 96 Apr 1 08:07 js/ -rw-r--r-- 1 root root 70 Apr 1 08:07 mix-manifest.json -rw-r--r-- 1 root root 24 Apr 1 08:07 robots.txt lrwxrwxrwx 1 root root 27 Apr 10 08:20 storage -> /var/www/storage/app/public/ -rw-r--r-- 1 root root 914 Apr 1 08:07 web.config
- 投稿日:2019-04-17T01:44:51+09:00
Laravel管理画面ライブラリVoyagerとLaravel-adminの比較
概要
Laravelの管理画面ライブラリであるVoyagerとLaravel-adminどちらが良いか検証してみました。
管理画面ライブラリは他にも存在しますが今回はこの2つに絞ります。
検証項目は調べたかった部分を重点的に調べたので、当たり前ですがこれが全てではないです。検証環境
Homestead 8.2.0
PHP 7.3.1
Larval 5.5.45
Voyger 1.2
Larval-admin 1.6.11環境構築ドキュメント
Laravel Homestead 5.5 Laravel
Installation - Voyager
Installation - Laravel-adminVoyager
動画です。英語ですが雰囲気や操作等の使用感はわかると思います。
Voyager - The Missing Laravel AdminVoygerでできること
インストールするといくつかの機能のModle, Controller, View, データベース等が用意されてます。
ブラウザ上からデータベースの追加や、新規ページの追加などの操作が可能です。BREADの作成画面ではカラムの表示や操作の設定なども行えます。
データベースとBREADを作成するとデータを作成・編集する管理画面を生成することができます。
カスタマイズ
Modle, Controller, Viewはそれぞれオーバーライドしてカスタマイズ可能です。
Overriding files - Voyager
削除操作は論理削除に変更可能です。
Enabling Soft-Delete - Voyagerユーザ認証
UserとRoleのデータベースが用意されており、ユーザや権限を追加可能です。
権限はデフォルトでは各メニューのBREADの有無を設定できます。
権限もカスタマイズ可能です。
Roles and Permissions - VoyagerUIコンポーネント
Bootstrapを使用しているため使い回し可能です。
バリデーション
BREADの設定画面でjsonで指定します。
BREAD Builder - Voyager
ファイルパス
{project_dir}/vendor/tcg/voyager/
{project_dir}/config/voyager.phpその他気になること
・Avaterの画像が壊れている
・Menu BuilderのBuilderのメニューが0個の場合に表示がバグる
・BREAD作成後にDatabase名を変更するとバグるLaravel-admin
公式のデモです。
Demo - Laravel-adminLaravel-adminでできること
Quick start - Laravel-admin
上記記事に沿って、マイグレーション実行->Model作成->Controller作成->ルート設定 を行います。
Laravel-adminのコマンドadmin:make
を実行すると、Modelのカラムに合わせてControllerを生成され、ページが作成されます。カスタマイズ
ページの表示はControllerのshow(), grid(), form()関数内等で変更可能です。
ユーザ認証
UserとPermissionとRoleのデータベースが用意されており、ユーザや権限を追加可能です。
権限はデフォルトでHTTP method+HTTP pathの組み合わせで指定できます。
また、マルチ認証に必要なガードやプロバイダがあらかじめ設定されています。
UIコンポーネント
Bootstrapを使用しているので使い回し可能です。
バリデーション
Laravelに則ってControllerから指定します。
バリデーション 5.5 Laravel
Laravel5.7 laravel-admin バリデーションルールの追加 | のるぼるのるの関連ファイル
{project_dir}/app/Admin
{projcet_dir}/vendor/encore/laravel-admin
{projcet_dir}/config/admin.phpその他気になること
・LaravelのLTS(安定版)のみ公式サポートしているようなのでLaravel5.5を使うのが無難そう
・ フッターのPowered by laravel-admin
の表示。消せるかな?
・ダッシュボードのデモのリンクが404
・ドキュメントの軽微な誤字VoyagerとLaravel-adminの比較
Voyagerのメリット
・ ブラウザからの直感的な操作ができる
データベースや、BREADと呼ばれるコントローラのようなものをブラウザ上から作成・編集することができるので直感的に操作できます。
・ 学習コストが低い
ブラウザからある程度開発的な操作をできるため、学習コストが低く始めるのに敷居が低いです。
・ 多機能
上記に加え、ドキュメントのようなものをまとめたcompassという機能や、簡易ブログや画像の管理画面のようなものがあらかじめ用意されており、機能が豊富です。
・ デザインがリッチでアニメーションがぬるぬる動く
全体的な質感やメニューの出方などがいい感じです。
Voyagerのデメリット
・ 若干コードの全体像が見えにくい
自分の手に負えない部分で何かエラーが起きた時に対処しづらそうな気がします。
・ ドキュメントが少ない
Voyagerを使ってカスタマイズしたという記事が少なく、自力で解決できる力が必要かもしれません。
Laravel-adminのメリット
・ コードからの素早い編集
基本的にLaravelの作法に則っていてコマンドやコードから作成・編集するのでコードの全体像が把握しやすいです。
・ 関連記事が多い
日本語・英語ともに関連記事が多い印象です。
・ マルチ認証に必要なガードやプロバイダが設定済
admin_userとuserテーブルが分かれていたり、ガードやプロバイダが設定されていて認証の追加設定が不要なのでその分の工数がかかりません。
Laravel-adminのデメリット
・ 学習コストがかかる
コードを触る部分が多いので、比較的学習コストがかかります。
・ デザインが質素
華やかさはあんまりないです。
・ 機能が最小限
あらかじめ用意されている機能は少なめです。
感想
やれることにそこまで違いはなく、どう実装するかという好みの問題が大きいので開発者が何を重視するかによりそうです。
個人的な意見としては、Laravel-adminは必要十分な機能で自分の手の中にある感じがあって実装しやすそうです。
一方、Voyagerのとっつきやすさとぬるぬるさは好きです。笑
それぞれに良いところがあると思います。
自分なら個人開発ならVoyager使うけど、規模が大きくてカスタマイズする可能性が高いならLarave-adminを選ぶかも?最後に
記事に間違いや不明な点があれば遠慮なくご指摘ください。
雑談ですが4月に転職したばっかりで新しく取り組むことが多いので最近更新頻度高めです。
やっぱり自分の興味あることを仕事にできるっていいですね。
- 投稿日:2019-04-17T00:16:03+09:00
Laravel5.4 ファイル複数ダウンロード
ファイルダウンロード処理の実装
主な方法
・Response::download
(サーバー上のファイルダウンロード)(IEだと文字化け可能性)
・Response::make()
(文字化けはないが、ファイル内容をキャストしてコピーするので、大容量には向かない)
・Storage::disk()->downlaod (バージョン的に使えない)
・phpの処理で作る (カスタマイズできる)ダウンロード参考記事
大容量・laravel・phpファイルダウンロード参考記事今回は、ファイル内容はそんなに重くなく、また既にファイルの中身をバイナリデータで持っていたので、Response::make()を使用することにした。
(Storage->disk('s3')->get(ファイルパス)でバイナリデータは取得していた。)$headers = [ 'Content-Type' => $mineType, 'Content-Disposition' => 'attachment; filename="' . $fileName . '"' ]; return Response::make($fileBinaryData, 200, $headers);これでファイルダウンロードは完了。
複数ダウンロードを実装する
{{Form::button('ダウンロード', ['class' => 'on-download'])}} <script> $('.on-download').on('click', function(){ handleDownload("samplel1.jpg"); handleDownload("samplel2.jpg"); handleDownload("samplel3.jpg"); }); function handleDownload(name) { const route = "{{route(download)}}"; // IE if (window.navigator.msSaveBlob) { const xhr = new XMLHttpRequest(); xhr.open("GET", route, true); xhr.responseType = "blob"; xhr.onload = function (e) { var blob = xhr.response; window.navigator.msSaveBlob(blob, name); } xhr.send(); return; } // chrome,firefox const a = document.createElement('a'); a.download = name; a.href = route; document.body.appendChild(a); a.click(); document.body.removeChild(a); } </script>aタグのdownload属性を使用して、ダウンロード処理を実装する。download属性を持つaタグを生成してclickで実行させ、消すを繰り返す.
IEはdownload属性をサポートしていないので、一つのファイルがダウンロードされるくらいなので、IE用に処理を分岐させる。ダウンロードする画像数分タブが表示されては消えるようにしているため、msSaveBlobで保存する。実践的に使うには
僕が今回実際に使ったときは、テーブルの行ごとの先頭にチェックボックスが存在し、チェックが入ったレコードのファイルだけをダウンロードさせるというものだった。
なので、checkboxにdata属性でfileIdとfileNameを渡す必要があった。ダウンロードボタンを押した瞬間に、checkが入ってるもののチェックボックスからfileIdとfileNameを取り出して、それをeach文で、handleDownload(fileId, fileName)(fileIdはrouteを生成するときにどのファイルをダウンロードさせるかを判定するためにくっつけて渡す)を複数回実行させることで、課題をクリアした。
aタグのdownload属性を使って、直接ファイルをダウンロードさせる方法もあるが、僕の場合ダウンロード履歴をDBに保存する必要があったため、いったんスクリプトを経由した。
- 投稿日:2019-04-17T00:16:03+09:00
Laravel5.4 ファイル複数ダウンロード(画像でもテキストでも)
ファイルダウンロード処理の実装
主な方法
・Response::download
(サーバー上のファイルダウンロード)(IEだと文字化け可能性)
・Response::make()
(文字化けはないが、ファイル内容をキャストしてコピーするので、大容量には向かない)
・Storage::disk()->downlaod (バージョン的に使えない)
・phpの処理で作る (カスタマイズできる)ダウンロード参考記事
大容量・laravel・phpファイルダウンロード参考記事今回は、ファイル内容はそんなに重くなく、また既にファイルの中身をバイナリデータで持っていたので、Response::make()を使用することにした。
(Storage->disk('s3')->get(ファイルパス)でバイナリデータは取得していた。)$headers = [ 'Content-Type' => $mineType, 'Content-Disposition' => 'attachment; filename="' . $fileName . '"' ]; return Response::make($fileBinaryData, 200, $headers);これでファイルダウンロードは完了。
複数ダウンロードを実装する
{{Form::button('ダウンロード', ['class' => 'on-download'])}} <script> $('.on-download').on('click', function(){ handleDownload("samplel1.jpg"); handleDownload("samplel2.jpg"); handleDownload("samplel3.jpg"); }); function handleDownload(name) { const route = "{{route(download)}}"; // IE if (window.navigator.msSaveBlob) { const xhr = new XMLHttpRequest(); xhr.open("GET", route, true); xhr.responseType = "blob"; xhr.onload = function (e) { var blob = xhr.response; window.navigator.msSaveBlob(blob, name); } xhr.send(); return; } // chrome,firefox const a = document.createElement('a'); a.download = name; a.href = route; document.body.appendChild(a); a.click(); document.body.removeChild(a); } </script>aタグのdownload属性を使用して、ダウンロード処理を実装する。download属性を持つaタグを生成してclickで実行させ、消すを繰り返す.
IEはdownload属性をサポートしていないので、一つのファイルがダウンロードされるくらいなので、IE用に処理を分岐させる。ダウンロードする画像数分タブが表示されては消えるようにしているため、msSaveBlobで保存する。今回こうやって使用した
僕が今回実際に使ったときは、テーブルの行ごとの先頭にチェックボックスが存在し、チェックが入ったレコードのファイルだけをダウンロードさせるというものだった。
なので、checkboxにdata属性でfileIdとfileNameを渡す必要があった。ダウンロードボタンを押した瞬間に、checkが入ってるもののチェックボックスからfileIdとfileNameを取り出して、それをeach文で、handleDownload(fileId, fileName)(fileIdはrouteを生成するときにどのファイルをダウンロードさせるかを判定するためにくっつけて渡す)を複数回実行させることで、課題をクリアした。
aタグのdownload属性を使って、直接ファイルをダウンロードさせる方法もあるが、僕の場合ダウンロード履歴をDBに保存する必要があったため、いったんスクリプトを経由した。
まとめ
複数画像ファイルをダウンロードさせることにすごいはまった。
つぎからはいけそう。
今度はダウンロード後を検知する方法を知りたいなぁ。