20190417のlaravelに関する記事は14件です。

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=を指定を試してみようって覚えとくことにしました :relaxed:

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

LaravelでDBのデフォルト文字セットと照会順序を変更する

使用するMySQLのデフォルト文字セットと照会順序と、Laravelの設定を合わせたい時に。

使いたいMySQLの設定

_ 2019-04-17 23.36.54.jpg

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

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

ValetでLaravel開発環境を構築してみた

概要

MacミニマニストのためのLaravel開発環境である「Valet」を実装してみました。

注意事項、留意点

  • 基本的には公式ドキュメントを参考にしてます
  • というよりほぼこれを見ながらやりました
  • Valetは「ベレット」と読むらしいです

前提条件

  • バージョン
    • OS: MacOS 10.14.2
    • Homebrew: 2.0.5 (当時の最新版)
  • 更新日
    • 2019/04/17

構築手順

1. Homebrewのインストール

  • ここでは割愛します
  • 基本的には公式ページを参照するといいと思います
  • 私はこちらをはじめとしたQiita記事を参考にしました
  • brew doctorYour 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 install

3. サイト動作

  • 任意の場所でディレクトリを作成し、移動します
    (ここでは 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/

参照

以下のサイトを参考にしました。

Laravel 5.8 Laravel Valet
GitHub

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel でDBのテーブルを全削除して作り直す

既存のtableをリセットしたい、または、接続先のDBを変更した、というようなときに。

全tableを削除して、マイグレーションを初めから実行するartisanコマンド。

php artisan migrate:fresh

.envを書き換えてDBを変えた場合、先にcacheクリアする。

php artisan cache:clear
php artisan config:clear
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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 認可 をご覧ください。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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.sh

5. Homesteadの設定

  • Homestead.yaml内のprovidervirtualboxに書き換えます
    (デフォルトが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/public

7. hostsファイルの書き換え

  • /etc/hostsファイルに以下を追加し、ローカルドメインへのリクエストをHomesteadに転送されるようにします
192.168.10.10  homestead.test

8. Vagrantの起動、ssh接続

  • 以下コマンドでvagrantを起動します
vagrant up
  • 以下コマンドでssh接続します
vagrant ssh

9. vagrant内でLaravelプロジェクトを作成

  • 以下コマンドでcodeディレクトリに移動して、laravelプロジェクトを作成します
    (ここでは startlaravelというプロジェクトを開始しますが、何でも構いません。ただし6で行ったNginxの設定と同じディレクトリルートにしましょう)
vagrant@homestead:~$ cd code
vagrant@homestead:~/code$ composer create-project --prefer-dist laravel/laravel startlaravel

10. サイトを開く

  • http://homestead.testで以下の画面が表示されればOKですスクリーンショット 2019-04-17 21.39.05.png

参照

以下のサイトを参考にしました。

Laravel Homestead イントロダクション
Homestead GitHubリポジトリ

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

CleanArchitectureとLaravelとTransaction

【概要】

CleanArchitectureにおいてデータの整合性を担保するためにUseCaseでトランザクション処理を行うと、Application Business RulesがFramework & Driversに依存することになります。
これは図の依存の矢印とは逆向きに依存してしまうため違反することとなります。
この記事では実際にUseCaseでトランザクション処理を行うサンプルコードと違反することなくデータの整合性を担保する方法を提示します。なおサンプルコードにはLaravelを用います。

image.png

【対象読者】

  • 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

[クラス図]

口コミ投稿におけるクラス図を作成しました。

Untitled Diagram-Page-1 (1).png

[サンプルコード]

PostReviewInteractor.php
use 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に登録を行います。
クラス図は下記の通りです。

  • 口コミサービス Untitled Diagram-Page-2.png
  • ポイントサービス Untitled Diagram-Page-3.png

【まとめと謝辞】

UseCaseにおいてトランザクション処理を行うと違反してしまうため、トランザクション処理によるデータの整合性の担保ではなく他の方法を用いる必要がある。しかしトランザクション処理が出来ないためACID特性ではなくBASE特性を考える必要がある。
なお実際にキューを用いた手法を考えると冪等性など他にも考えなければいけないことが出てきます。これに関してまとめきる事が出来ませんでした。 こちらの記事 を参考にすると良いと思います。
他の記事に丸投げしてしまい申し訳ありません。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

初心者がlaravelをロリポップレンタルサーバーに導入した手順

初心者でもlaravelをレンタルサーバーに導入!

  • 今まで生のPHPかcodeigniterしか使ったことない完全なlaravel初心者。
  • なので初心者目線で色々書いてます。(主にターミナルへの愚痴)
  • なんかみんなAWSとかばっかだけど、laravelを導入したい既存のサイトのサーバーがロリポップだったのでなんとかしてみた。
  • macで実行してます。
  • laravel5.5
  • こちらのサイトめちゃくちゃ参考にしました。この記事で行き詰まった方はこちらもご参考ください。

ロリポップにcomposerをインストールしてLaravel5.5を公開する

前提条件

ロリポップでSSHが使えること。
つまりはスタンダードプラン、エンタープライズプランの契約であること。

php 7.1に設定していること(これもロリポップのユーザーページにて)

まずはロリポップのユーザーページでSSH認証

スクリーンショット 2019-04-17 19.09.16.png
このメニューにある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。

あとは実際のURLをブラウザで入力すれば、、、
スクリーンショット 2019-04-17 20.20.22.png

というデフォルトページが!

これにてlaravelの導入完了です!

がここで

500エラー出た方。

実は自分も最初の30分くらい500エラーでした。
色々情報を探し実行しましたが変化なし…
調べ終わって意気消沈してる時に、もう一回更新したらさらっと表示されました・・・・・。

多分ですが、直前でレンタルサーバーのPHP設定を7.1に変えたりしていたのでその反映に時間がかかったのかなぁと思っています。
こういうケースに該当する場合は少し待ってみたら改善されるかも…。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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();
}
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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();
    }
}

参考サイト

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

[Laravel]保存した画像が404エラーで表示されない

問題

画像を取得して表示させようとしたときに、データを取得してくることまではできたのですが、表示すると404エラーがでてきて、パスは間違っていないのに、表示できませんでした。

開発環境
PHP :7.2.15
Laravel :5.6

画像の取得、表示については公式リファレンスや他の記事等で書いてあることを参考にしていたのですが、大まかには以下の流れです。
無題 3.jpg

解決方法

画像自体のパスは間違っていなかったので、「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.config

Storageのシンボリックリンクを変更します。↓

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
  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

Laravel管理画面ライブラリVoyagerとLaravel-adminの比較

概要

Laravelの管理画面ライブラリであるVoyagerLaravel-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-admin

Voyager

動画です。英語ですが雰囲気や操作等の使用感はわかると思います。
Voyager - The Missing Laravel Admin

Voygerでできること

インストールするといくつかの機能のModle, Controller, View, データベース等が用意されてます。
ブラウザ上からデータベースの追加や、新規ページの追加などの操作が可能です。

データベースやBREADの作成
スクリーンショット 2019-04-17 0.13.26.png

データベースの作成画面
スクリーンショット 2019-04-17 0.14.31.png

BREADの作成画面
スクリーンショット 2019-04-17 0.14.56.png

BREADの作成画面ではカラムの表示や操作の設定なども行えます。
スクリーンショット 2019-04-17 0.15.03.png

データベースとBREADを作成するとデータを作成・編集する管理画面を生成することができます。
スクリーンショット 2019-04-17 0.36.15.png

カスタマイズ

Modle, Controller, Viewはそれぞれオーバーライドしてカスタマイズ可能です。
Overriding files - Voyager
削除操作は論理削除に変更可能です。
Enabling Soft-Delete - Voyager

ユーザ認証

UserとRoleのデータベースが用意されており、ユーザや権限を追加可能です。
スクリーンショット 2019-04-17 0.40.08.png
権限はデフォルトでは各メニューのBREADの有無を設定できます。
スクリーンショット 2019-04-17 0.42.26.png

権限もカスタマイズ可能です。
Roles and Permissions - Voyager

UIコンポーネント

Bootstrapを使用しているため使い回し可能です。

バリデーション

BREADの設定画面でjsonで指定します。
BREAD Builder - Voyager
スクリーンショット 2019-04-17 0.50.02.png

ファイルパス

{project_dir}/vendor/tcg/voyager/
{project_dir}/config/voyager.php

その他気になること

・Avaterの画像が壊れている
・Menu BuilderのBuilderのメニューが0個の場合に表示がバグる
・BREAD作成後にDatabase名を変更するとバグる

Laravel-admin

公式のデモです。
Demo - Laravel-admin

Laravel-adminでできること

Quick start - Laravel-admin
上記記事に沿って、マイグレーション実行->Model作成->Controller作成->ルート設定 を行います。
Laravel-adminのコマンドadmin:makeを実行すると、Modelのカラムに合わせてControllerを生成され、ページが作成されます。

ページ追加後の画面
スクリーンショット 2019-04-17 0.54.13.png

カスタマイズ

ページの表示はControllerのshow(), grid(), form()関数内等で変更可能です。
スクリーンショット 2019-04-17 0.58.02.png

ユーザ認証

UserとPermissionとRoleのデータベースが用意されており、ユーザや権限を追加可能です。
スクリーンショット 2019-04-17 1.00.59.png

権限はデフォルトでHTTP method+HTTP pathの組み合わせで指定できます。
スクリーンショット 2019-04-17 1.02.39.png

また、マルチ認証に必要なガードやプロバイダがあらかじめ設定されています。

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月に転職したばっかりで新しく取り組むことが多いので最近更新頻度高めです。
やっぱり自分の興味あることを仕事にできるっていいですね。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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に保存する必要があったため、いったんスクリプトを経由した。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む

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に保存する必要があったため、いったんスクリプトを経由した。

参考記事

まとめ

複数画像ファイルをダウンロードさせることにすごいはまった。
つぎからはいけそう。
今度はダウンロード後を検知する方法を知りたいなぁ。

  • このエントリーをはてなブックマークに追加
  • Qiitaで続きを読む