Laravelの認可を解説|Gateについて言及

認可とはどんな概念でしょうか。
認可とは、特定の行動に対しての権限の制御をする設定です。

認可には、Gate・Policy、2つの方法があります。

Gateで設定する場合

・App\Providers\ AuthServiceProvider に定義を記述
・認可したい箇所でGateファザードを用いて制御

Gateを App\Providers\ AuthServiceProvider で定義する

public function boot()の中で定義していきます。

Gateの名称を設定:chat-view
Gateが認可される条件を設定:if文の中がtrueの場合に返り値として return true;を返します。
※引数$userは、認証されているユーザー情報が入ってきます。

         Gate::define('chat-view', function (User $user, $chatRoom) {
            if ($chatRoom->apply_user_id === $user->id) {
                return true;
            }
        }); 

認可したい箇所でGateファザードを用いて制御

Gateを活用する場所では、下記のように扱います。
Gateファザードには、denies, allows , authorizeなどのメソッドがあります。
authorize で設定している下記では、Gateの定義した処理でtrueを返さない場合には403エラーを返します。

        $chatRoom = ChatRoom::findOrFail($chatRoomId);
        Gate::authorize('chat-view', $chatRoom); 

Laravelの認証を整理 | guard,provider

概念として理解が難しい、認証について整理していきたいと思います。

まず、認証とは何か。
簡単に述べると、「誰なのか」を判断することです。

認証をする際に、2つの機能を紹介します。
guardとproviderです。

guardは、認証の方法について定義します。具体的には、sessionかtokenなのか。

providerは、認証の情報(「誰なのか」の情報)の提供場所を定めます。

guard, providerの設定はcongif > auth.phpで設定することが出来ます。
defaultで認証情報が設定されていますが、自由に追加することが出来ます。

追加する機会として、メジャーなのは「管理者権限を追加」などがあると思います。

guradの設定をみていくと、
下記だと、web、apiというguradが存在しています。
webの方に着目すると、
・session方式で、認証を実行する
・認証の情報提供(provider)はusersにて実行する
(providerについては後述)

     'guards' => [
        'web' => [
            'driver' => 'session',
            'provider' => 'users',
        ],

        'api' => [
            'driver' => 'token',
            'provider' => 'users',
            'hash' => false,
        ],
    ], 

providerは、
上記で設定したusersの内容が設定されています。
・eloquent方式で、users情報を提供する
・提供場所は、App\Models\User::classの情報

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

Laravelで多対多のリレーションを結合する方法【記事にタグ情報を付与】

Webアプリケーションを作成していくうえで、避けては通れないデータベースの作成・データ構造の作成です。

そのなかでも少し複雑になる多対多のリレーションの作成について解説していきます。

以前、下記にてリレーションについて解説しております。
今回は、多対多のみについて、少し深くです。

今回は、記事にタグを付与する多対多のリレーションをイメージしてみます。

記事A・記事B・記事C
タグ1・タグ2・タグ3

といった具体にお互いが、1対多の関係になる状態が多対多の関係性です。

作成するテーブルは、
・記事
・タグ
・記事とタグを紐づける中間テーブル

この3つです。

記事とタグを紐づける中間テーブル とは、何か。
記事IDとタグID
の紐づけが行われるテーブルです。

記事A_ID タグ1_ID
記事A_ID タグ2_ID
記事B_ID タグ2_ID
記事C_ID タグ3_ID

みたいに、各記事とタグのIDを紐づけます。

Modelに対してリレーションを記述していきます。
記事モデルに対して、タグとのリレーションを記述します。

1対多のリレーションの考え方でいくと
記事 → 中間テーブル → タグ でテーブル2つ跨ぐのでリレーションを2度する必要があると考えられますが、Laravelのリレーションはここを1度で処理する方法があります。

public function tagRelations()
{
return $this->belongsToMany('App\Models\Tag', 'tag_maps', 'article_id', 'tag_id' );
} 

簡単に解説します。

belongsToMany メソッドを使います。
第2引数は、中間テーブルとなるテーブル名称
第3引数は、モデルID(記事)と中間テーブルを紐づける、中間テーブルのカラム
第4引数は、リレーション先ID(タグ)と中間テーブルを紐づける、中間テーブルのカラム

これで、tagRelations()を使うことで
記事 → タグ へのリレーションが完成します。

Laravelで、メッセージ未読ユーザーに定期的にメールを送信する方法

今回は、Laravelでメールを送信する方法を解説していきます。
即時的に、メール送信するだけではなくて、特定の条件(メッセージが未読)を定期的に判断して、メール送信を処理していく方法です。

大きく分けて下記のステップがあります。
1:Mailを送信するクラスを作成する
2:Mailのメッセージ内容を作成する
3:コマンドをMail送付する
4: cronを用いてスケジュール通りにコマンドを実行

これらのステップです。

1:Mailを送信するクラスを作成する

まずは、Mailを送信するクラスを作成していきます。

まずはclassを作成します。

$ php artisan make:mail MessageSend (class名称)

APP/Mailの配下にMessageSend が生成されます。

何のためのクラスかというと、主にメールの各プロパティを決定します。

     public function build()
    {
       return $this
       ->view('emails.message') // views > emails > message.blade.php
       ->from('info@oshimen.net','Oshimen')
       ->subject('メッセージが届いております。');
    } 

view → メールの文面(これは、viewsで記述しております。)
from → メールの送り主
subject → 件名

を決めることが出来ます。

2: Mailのメッセージ内容を作成する

viewsにメールの文章を記述します。

views > emails > message.blade.php を用意します。
このmessage.blade.phpの中に文章を作成ます。

<p>
    メッセージを未読の方に通知しております。
</p>

<p>
    サービスへアクセスしてみましょう。
</p> 

例えば、こんな感じです。

3:コマンドでMail送付する

Laravelでは、最初から様々なコマンドが用意されいますが、自らコマンドを生成することも可能です。

 php artisan list 

こちらで、使用可能な全Artisanコマンドを確認することが出来ます。

それでは、コマンドを生成していきます。

php artisan make:command sendNotificationMail (コマンド名)

app > Console > Commands の配下に
sendNotificationMail が生成されています。

コマンドで処理されるべき内容・設定情報を追記していきます。

1つ目、コマンド名称を設定

$signature を設定

 protected $signature = 'app:send_notification_mail'; 

public function handle()の中に設定方法を書いていきます。

 Mail::to($to)->send(new MessageSend()); 

Mailファザードで、メール送信の実行となります。
$to:宛先です。
情報構造としては、emailとnameを設定します。
下記です。

[
 'email' => $readChatRoom->users->email, 
 'name' => $readChatRoom->users->name, 
]

sendの中身は送信する内容です。
「2:Mailのメッセージ内容を作成する」で作成したメッセージ内容となります。
※classは継承して

4: cronを用いてスケジュール通りにコマンドを実行

cronを用いて、コマンドを実行していきます。

app > Console > Commandsの配下で
コマンドが実行されるスケジュールを設定します。

 protected function schedule(Schedule $schedule)
 { 
 $schedule->command('app:send_notification_mail')->hourly();
 }

command(‘app:send_notification_mail’) 
 → 作成した、コマンドの名称を設定します。

hourly()
 → コマンドが実行される周期を設定します。
   この場合1時間おきに実行されます。

周期の設定は色々とできます。

https://readouble.com/laravel/5.7/ja/scheduling.html

で、これで動くわけではなくて、cronを設定しないといけないのです。

使っているWebサーバーのOSバージョンにもよるらしいですが
Amazon Linux 2 の場合は、

 crontab -e 

下記を追記して下さい。

 * * * * * cd /opt/www/xxx artisanまでのパス xxx/ && php artisan schedule:run >> /dev/null 2>&1 

これでスケジュール通りに動くと思います。

LaravelでDBファザードのtransactionから返り値を取得する方法

DBファザードにtransactionという、メソッドが用意されています。

メソッドの内容としては、
transaction メソッドの処理内で例外が発生すると(エラーが発生する)と
ロールバック処理されます。

つまり、メソッド内で問題が発生した際に、途中までの処理も全てなかったことにしてくれます。問題おきた際に途中までの処理は完了していると不都合な事態が発生してしまいますので、便利です。

transaction メソッドは返り値を受け取ることも可能です。
メソッド内での処理を、外部で利用することが可能です。
例えば、下記のようにreturn で返した値を$articleの変数で引き受けることが可能です。

 $article = DB::transaction(function () use ($request) {

            $article = RecomendArticle::updateOrCreate(
                ['id' => $request->articleId],
                [
                'title' => $request->title,
                'nickname' => $request->nickname,
                'work' => $request->work,
                'age' => $request->age,
                'sex' => $request->sex,

            );
            return $article;
        }); 

Facebookでuser_idを利用して、ユーザープロフィールページへ遷移する方法

LaravelでSNSログイン機能を実装した際に、ユーザーFacebookプロフィールリンクを付けたいと思いました。

ただ、Facebook認証で取得するユーザ情報の中にプロフィールリンクにある情報がない…??となりました。

具体的には、下記のような情報が取得できます。

+token: 
+refreshToken: 
+expiresIn: 
+id: 
+nickname: 
+name: 
+email: 
+avatar 

FacebookのプロフィールURLは
https://www.facebook.com/{識別情報}

ここの識別情報と、SNS認証で取得できるnameが違うのです。

結論としては
SNS認証で取得できるidを使います。

PC

https://www.facebook.com/profile.php?fbid={id}

SP

https://m.facebook.com/profile.php?fbid={id}

これで、Facebookのプロフィールへリンクさせることができます。

LaravelのIntervention Imageで、画像を丸く切り出す方法

Laravelの画像編集ライブラリで有名なIntervention Imageを使ったTIPSです。

四角い画像を読み込んで、丸く切り出す方法を解説します。
CSS的にいうと、radiusあたりの操作といった感じでしょうか。

先にコードを記述してしまうと、下記のような感じです。

$profileImage =  Image::make($user->image_path);

$width = 200;
$height = 200;
$profileImage->widen($width);
$profileImage->heighten($height);

$mask = Image::canvas(200, 200);
$mask->circle($width, $width/2, $height/2, function ($draw) {
    $draw->background('#fff');
});
$profileImage->mask($mask, false);

$profileImage->save($path."circled.png");  

簡単に解説していきます。

$profileImage =  Image::make($user->image_path);

Image::make($user->image_path);
ここで、画像を読み込んでおります。
私の場合は、 $user->image_path ここはAWS S3上UPした画像URLです。
https://oshimen-storage.s3.ap-northeast-1.amazonaws.com/XXXXXXXXXXXXXXXXXXXX
というやつですね。

$width = 200;
$height = 200;
$profileImage->widen($width);
$profileImage->heighten($height);

画像サイズを矯正しております。

$mask = Image::canvas(200, 200);
$mask->circle($width, $width/2, $height/2, function ($draw) {
    $draw->background('#fff');
});
$profileImage->mask($mask, false);

maskを作成しております。
maskと同じ直径のサイズの円を作成して、画像を切り出しております。

Laravelのwherehasで複数のリレーションを繋げてデータ取得する方法

「Laravelのwherehasで複数のリレーションを繋げてデータ取得する方法」というタイトルですが、もう少し詳細に伝えると、
リレーションがネスト化しているデータをwherehasで条件指定してから取得する方法です。

リレーションがネスト化している??一体どういうことと思う方もいるかもしれません。

例えば、
user -> posts がリレーションされていて
posts -> comments がリレーションされている場合です。

今回やりたいことは、user -> post -> comment と一括でつなぎます。
userデータを「commentデータを条件」に取得することです。
例えば、commentで、「よろしく」と言っている条件に絞って、userデータを取得する。と言った感じです。

実際の取得方法では、下記です。
※posts, comments はリレーション名称です。

$commentUser = User::with('posts.comments')
    ->whereHas('posts.comments', function ($query) {
     return $query->where('message', "よろしく");
    })
    ->get();

ネストしたリレーションを取得する場合のポイントは1つです。
リレーションネストを. でつなぎます。

with('posts.comments')
whereHas('posts.comments', function ($query)

と言った感じです。
ご活用下さいませ。

リレーションを利用したデータ取得に関しては下記もご参考下さい。

LaravelでCSSのキャッシュ対策を一番簡単にやる方法

CSSのキャッシュが残ることによって、変更がすぐに反映されないといった問題を抱えます。開発に影響があるだけでなく、リリース後にCSSを変更した場合は、CSSのキャッシュが残ってしまうので、エンドユーザーに対してもCSSキャッシュ問題は発生します。

今回は、とてつもなく簡単にCSSのキャッシュを解決する方法を紹介します。

通常であれば下記のように、HTMLのheader内にCSSを読み込んでいると思います。

<link href="{{ asset('/assets/css/style.css') }}" rel="stylesheet">

下記のように変更して下さい。

<link href="{{ asset('/assets/css/style.css').'?'.time() }}" rel="stylesheet">

追加した部分は「.’?’.time()」を追加しております。

こうすることによって、毎回違うCSSファイル名に変更されます。(参照するファイルの内容は変わりません。)
ファイル名が違うことによって、CSSを毎回読み込んでくれます。

こうすることで、CSSのキャッシュ問題を解決できます。

CSSのキャッシュ解決方法は色々とやり方があるので試してみてください。

Laravelのvalidation機能で画像比率を指定する方法

Laravelはvalidation機能が独自に組み込まれております。
様々な種類のvalidationを設定することが可能です。

今回は、画像比率を指定する方法をご紹介します。
プロフィール画像は1:1の画像に制限したい。などといったvalidationが可能です。

やりかたは非常にシンプルです。

 public function post(Request $request)
{
    $validatedData = $request->validate([
        'title' => 'required|unique:posts|max:255',
        'body' => 'required',
        'image' => 'required|dimensions:ratio=1/1',
    ]);

    /post内容/

} 
dimensions:ratio=1/1

のように、dimensions:ratio=〇〇
〇〇に指定したい比率を追加して下さい。