初心者のプログラミング日記

プログラミング初心者の日記

プログラミングに関することを書いていきます。

Laravelのログイン周りの事

Laravelでログイン周りを変更していたので、そのメモを残しておきます。
フロントエンドはReactでやっています。
Laravelのバージョンは7です。

ログイン機能の追加

composer require laravel/ui
php artisan ui react --auth
npm install
npm run dev
php artisan migrate

これでログイン関係の機能とそのデーターベースができます・

ログイン後のリダイレクト先変更

デフォルトでは/homeになっていますが、ここを任意のページに変更します。

<!--場所はapp/Providers/RouteServiceProvider.phpです-->

public const HOME = '/home'; //ここを好きなURLに変えてください

これだけで変更できます。

ルートの保護

今のままでは/home以外にはログインしていなくてもアクセスできてしまうので、ログインしていないときは、ログインページに飛ばたいと思います

Route::get('/todo','TodoController@index');

ルートは適当に用意しておきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

class TodoController extends Controller
{

    public function __construct()     
    {
        $this->middleware('auth');
    }
    
    public function index()
    {
        return view('todo');
    }
}

コントローラのコンストラクターでmiddlewareメソッドを呼び出すだけです。
これでこのページはログインが必須になりました。

名前でログイン

デフォルトではメールアドレスとパスワードでログインする仕様になっているので名前とパスワードでログインするように変更する。

<!--場所はapp/Http/Controllers/Auth/LoginController-->
<?php
 public function username(){
        return 'name';
    }

これを書き足すだけです。といってもAuthenticatesUsersをオーバーライドしてるだけなんですけどね。
ソースコード
https://github.com/laravel/framework/blob/5.8/src/Illuminate/Foundation/Auth/AuthenticatesUsers.php

あとはログインフォームを書き直していきます。

<!--場所はresources/views/auth/login.blade.php-->
<div class="form-group row">
  <label for="name" class="col-md-4 col-form-label text-md-right">{{ __('Name') }}</label>

       <div class="col-md-6">
              <input id="name" type="name" class="form-control @error('email') is-invalid @enderror" name="name" value="{{ old('email') }}" required autocomplete="name" autofocus>

              @error('name')
                       <span class="invalid-feedback" role="alert">
                               <strong>{{ $message }}</strong>
                       </span>
              @enderror
       </div>
</div>

emailだった所をnameに書き換えてあげるだけです。
英語じゃなくて日本語にしたい場合は下記URLを参考に
https://laraweb.net/tutorial/6949/

ユーザ情報の取得

今回はAPIを使って取得したいと思います。

<!--場所はroutes/api.php-->
<?php

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;

Route::group(['middleware' => 'api'], function(){
    Route::get('user', 'UserController@index');
});

ルートにはユーザの情報を取得するコントローラ指定しておきます。

次にコントローラを書いていきます。

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth; //追加

class UserController extends Controller
{
    public function index(Request $request) {
        $user = Auth::user();   #これでログインユーザー情報を取得

        return $user;
    }
}

ここまで一旦、ログインした状態で/api/userにアクセスしてみてみ下さい。おそらく何も表示されません。
なので、以下のファイルを変えてください。

<!--場所はapp/Http/Kermel.php-->
<?php

protected $middleware = [
        \App\Http\Middleware\TrustProxies::class,
        \Fruitcake\Cors\HandleCors::class,
        \App\Http\Middleware\CheckForMaintenanceMode::class,
        \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class,
        \App\Http\Middleware\TrimStrings::class,
        \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
        \Illuminate\Session\Middleware\StartSession::class, //追加
    ];

これで再び/api/userにアクセスするとユーザー情報が表示されます。

ついでにReactで表示する方法も書いておきます。

import React from 'react';
import ReactDOM from 'react-dom';


class Example extends React.Component{
    constructor(props){
        super(props);
        this.state={user:[]}
    }

    componentDidMount(){
        axios
            .get('/api/user')
            .then(res => {this.setState({user: res.data});})
            .catch(error => {console.log(error)})

        console.log(this.state.user);
    }

    render(){
        return(
            <div>
              <h1>ユーザー情報</h1>
              <p>{this.state.user.id}</p>
              <p>{this.state.user.name}</p>
            </div>
        );
    }
}

export default Example;


ReactDOM.render(<Example />, document.getElementById('example'));

これでユーザー情報が画面に表示されたと思います。

ログアウトボタンの設置

今度はログアウトボタンを設置していきます。

return(
            <div>
              <h1>ユーザー情報</h1>
              <p>{this.state.user.id}</p>
              <p>{this.state.user.name}</p>
              <a href="/api/logout">ログアウト</a> //追加
            </div>
 );

aタグにこれから作るAPIをセットしておきます。

次にルーティングの設定です。

<?php
Route::group(['middleware' => 'api'], function(){
    Route::get('user', 'UserController@index');
    Route::get('logout', 'UserController@logout'); //追加

});

コントローラに以下のコードを書き足して終わりです。

<?php
public function logout(Request $request){
        Auth::logout(); //これでログアウトできる

        return redirect('/');
 }

ちなみにこのままだとAPIはログインしていないユーザーでもアクセスできるので、ルートの保護をしておくといいかもしれません。ここはあまり調べていないのでわかりません。

homeの編集

f:id:nasubiFX:20200429223032p:plain

上記の画像の赤枠の編集は以下のコードを編集します。

<!--場所はresources/views/layouts/app.bladephp-->
 <!-- 26~28行 -->
 <a class="navbar-brand" href="{{ url('/todo') }}">
                    ユーザー情報
 </a>

新規登録時にメール送信

イベントとリスナーを使って実装します。
ここはほとんど下記URLのままです。
https://reffect.co.jp/laravel/laravel-event-listener

メールの設定は下記記事から
nasubifx.hatenablog.com


一応コピペ用にコードを貼っておきます。

<?php
//場所はapp/Http/Controllers/Auth/RegisterController.php
use App\Events\UserRegistered; //追加
//省略
protected function create(array $data){
  //app/User.phpで$fillableを使っている
  $user= User::create([
            'name' => $data['name'],
            'email' => $data['email'],
            'password' => Hash::make($data['password']),
        ]);

        //eventヘルパー関数
        event(new UserRegistered($user));
        return $user;
}

デフォルトでは laravel規定のUserモデルを使うようになっています。
protected $table = 'users';


次にイベントの作成
まず、下記のコマンドでイベントを作成

php artisan make:event UserRegistered

中身を書いていきます。

<?php
//場所はapp/Events/UserRegistered.php
use App\User; //追加
class UserRegistered{
    use Dispatchable, InteractsWithSockets, SerializesModels;
    public $user;

    public function __construct(User $user){
        $this->user = $user;
    }

    /* 省略 */
}


次にリスナーを作って行きます。
手順はイベント作成と同じ。
まず、下記のコマンドでリスナーを作成

php artisan make:listener SendWelcomeEmail --event=UserRegistered

中身を書いていきます。

<?php
//場所はapp/Listners/SendWelcomeEmail.php
use App\Events\UserRegistered; //追加
use Mail; //追加
use App\Mail\WelcomeMail; //追加

class SendWelcomeEmail{
  //省略
    public function handle(UserRegistered $event){ 
        Mail::to($event->user->email)->send(new WelcomeMail($event));
    }
}

イベントのuserプロパティにアクセスしています。

次にEventServiceProviderに作成したイベントとリスナーの情報を登録します。

<?php
//場所はapp/Providers/EventServiceProvider.php
use App\Events\UserRegistered; //追加
use App\Listeners\SendWelcomeEmail; //追加

class EventServiceProvider extends ServiceProvider{
  protected $listen = [       
          UserRegistered::class => [
             SendWelcomeEmail::class,
          ],
     ];
}

次にMailbleクラスを作って行きます。

php artisan make:mail WelcomeMail

中身を書いていきます。

<?php
//省略
class WelcomeMail extends Mailable
{
    use Queueable, SerializesModels;
    protected $name;

    public function __construct($event)
    {
        $this->name = $event->user->name;
    }

    public function build()
    {
        return $this->view('emails.welcome')
                    ->subject('登録ありがとうございます')
                    ->with(['name'=>$this->name]);
    }
}

withメソッドでviewに登録時の名前をセットしています。

最後に本文の作成です

//場所はresouces/views/emails/welcome.blade.php
<p>{{$name}}</p>

これで新規登録時にメールが届きます。
f:id:nasubiFX:20200501193413p:plain

LaravelのAuth機能でリダイレクト先の変更

<?php
//場所はapp/Http/Middleware/Authenticate.php

namespace App\Http\Middleware;

use Illuminate\Auth\Middleware\Authenticate as Middleware;

class Authenticate extends Middleware
{
    /**
     * Get the path the user should be redirected to when they are not authenticated.
     *
     * @param  \Illuminate\Http\Request  $request
     * @return string|null
     */
    protected function redirectTo($request)
    {
        if (! $request->expectsJson()) {
            return route('welcome'); //ここを変更
        }
    }
}

指定するルートには名前を付けておいて下さい。