Laravelのデータベースリレーションを活用して、別のModelのデータを取得する

Laravelのリレーションを活用することで、リレーション先の異なるテーブルとのデータ連携が可能になります。
非常に重要な機能ですので、是非試してみてください。

今回はリレーションについて2点お伝えしていきたいと思います。

( 1 ):Model内でのリレーションの設定方法
( 2 ):Eloquent で、リレーションを活用して別テーブルのデータを取得する方法

つまり、設定 → データ取得する 一連の流れをお伝えしたいと思います。

( 1 ):Model内でのLaravelリレーションの設定方法

こちらは下記サイトの「Eloquent:リレーション」を一度確認してみてください。

リレーションの方法は幾つかあります。
一番使う形式は、下記3つかと思います。基礎的な部分でいうとこの辺を抑えておけば問題ないと思います。

  • 1対1
  • 1対多
  • 多対多

イメージしやすい例は

1対1:
User_id と マイナンバー
※user_id もマイナンバーもどちらもユニークになる存在なので他のデータとの組み合わせは起きません。

1対多:
User_id と コメント履歴
※AさんのコメントはAさんにしか紐づきません。ただし、Aさんは複数コメントする場合はあります。

多 対 多 :
User_id と 好きな飲食店
※Aさんは、飲食店1、2,3が好き、Bさんは、飲食店2、3,5が好き。というように、紐づきが両データに紐づく可能性があります。

設定方法は、Model内にリレーションのメソッドを記述します。
詳細は 「Eloquent:リレーション」 こちらに書いてある通りです。
1つ注意して確認してみて欲しいのは、
データリレーションには、主従の関係性があるということです。

( 2 ):Eloquent で、リレーションを活用して別テーブルのデータを取得する方法

リレーションを設定する目的の1つは、データを取得しやすくすることです。
簡単な例で紹介します。


A // リレーション設定
※ChatRoomUser クラスから、UserクラスへID同士を紐づけしております。

 <?php

namespace App\Models\Chat;

use Illuminate\Database\Eloquent\Model;

class ChatRoomUser extends Model
{

    protected $fillable = ['chat_room_id', 'user_id', 'usertype'];    

    public function InterviewUser()
    {
        return $this->belongsTo('App\Models\User' , 'user_id' ,'id');
    }
} 

B // リレーションデータの取得
これを設定したことによって、Eloquent でChatRoomUser クラスを活用して、Userクラスの情報を取得できます。

$messageUser = ChatRoomUser::whereIn('chat_room_id', $chat_room_id)
->where('usertype', 'Interviewer')
->get();

foreach($messageUser as $user){
$email = $user->InterviewUser->email;
}
 
 

リレーションを活用した取得方法は下記です。
Eloquantで取得データ- > リレーション設定のメソッド -> リレーションした先のModelのデータカラム

今回でいうと:
・ Eloquantで取得データ  $messageUser
・ リレーション設定のメソッド  InterviewUser
・ リレーションした先のModelのデータカラム  email※Userクラスのデータカラム

リレーションデータ取得時の注意

1件のデータに対してメソッドを適用することが出来る

$messageUser は、配列の中に複数のデータが含まれている場合があります。
配列に対して、 リレーション設定のメソッド をアクセスすることは出来ません。
データを一つづつに分解して、そのデータに対してリレーションメソッドを適用しましょう。

LaravelのFacad/Validator で、ユニーク化するテーブルを変更する方法

Laravel初心者の気づきをお伝えします。

マルチ認証の登録・ログイン方法を試していました。
主に参考にしていたのは、下記のやり方です。

https://qiita.com/namizatop/items/5d56d96d4c255a0e3a87

1つ不都合なことがありました。
Adminで新規登録時に、emailがユニークになるデータベーステーブルの対象先がuserのテーブルだったのです。つまり、Adminで登録しようとした際に、Adminでユニーク判定されるのではなくて、userでユニーク判定されてしまっていました。

原因が分からず、Facad の Validatorにデータベーステーブルを指定する場所があるのかなと思い
Illuminate\Support\Facades\Validator::class,
を調べてみても、テーブルを指定しているようにも見えません。

他を調べてみたところ、
下記がテーブルを指定している場所でした…

return Validator::make($data, [
            'name'     => ['required', 'string', 'max:255'],
            'email'    => ['required', 'string', 'email', 'max:255', 'unique:users'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);

ここの部分

'email' => 'unique:users'

app/Http/Controllers/Admin/Auth/RegisterController.php

のuser → adminに変更してあげれば、ユニーク化する対象のテーブルがadminへ変更なります。

return Validator::make($data, [
            'name'     => ['required', 'string', 'max:255'],
            'email'    => ['required', 'string', 'email', 'max:255', 'unique:admin'],
            'password' => ['required', 'string', 'min:8', 'confirmed'],
        ]);

composer require google/apiclient:^2.0で、エラーが起きたときの対処法

Errorは下記です。

Your requirements could not be resolved to an installable set of packages.
Installation failed, reverting ./composer.json to its original content.

下記のように、バージョンをアスタリスクで設定してあげるとインストールが実行されました。

composer require google/apiclient:^2.*

Laravelにて、マルチ認証を制御している部分を一番簡潔に説明します。

Laravelで、マルチ認証を知っていますか。マルチ認証ということばは知っていなくても、機能は見たことがあると思います。
代表的なのは、管理者とユーザーに分けたり、企業と求職者に分けたり。
ユーザー別に権限を変え、機能やViewで表示する内容を変えるときに用います。

多くのエンジニアの方々が、マルチ認証について解説してくれています。

ただ、初心者エンジニアからすると、分かるような、分からないような。 要するに、何処かが制御しているのか。まずは知りたい。

と、言った課題を感じます。
(最終的には、フレームワークが何の処理をしているのかを総合的に理解する必要はあると思いますが。)

今回は、簡潔に、マルチ認証を制御しているところは何処なのかを解説します。

色々と調べつつ、実験しながら間違った情報ではないのですが、
確証を持てていないので、違ったら申し訳ないです…
ただ、初心者エンジニアの方で、簡潔に知りたい場合は一読の価値はあるのかなと思います。
では、いってみましょう。

1:マルチ認証を制御するために必要なパーツ
2:マルチ認証を制御しているのに変更する部分

1:マルチ認証を制御するために必要なパーツ

・ログイン時に所有する権限

・ 権限に応じて、閲覧可能(閲覧不可)に制御する方法(機能の場合もあるが…)

簡単にいってしまうと、この2つです。

認証とは、ログインした際に付与されるものです。
(おそらく、sessionが所持しているのだと思ってます。違ったらごめんなさい…)

で、このログインのタイミングで、権限を付与して、その権限に応じて、Viewの制御をしてあげればよいのです。

2:マルチ認証を制御しているのに変更する部分

では、それぞれどこで制御しているのかを確認していきましょう。

ログイン時に所有する権限

権限の付与が全てと言っても過言ではありません。
この権限の付与のために操作するべきところは

・LoginさせるためのController(LoginController.phpなど)
・config/auth.php

この2つです。
(この2つを操作する前に整えなけらばいけないことは省きます。簡潔に。)
guardという機能を使って設定していきます。

LoginさせるためのController (LoginController.phpなど) に対して、
下記を追記します。

protected function guard()
{
    return Auth::guard('admin');
     // adminという権限を付与しています。
     // 名称は必要に応じて変更してOK
 }    

また、Authファザードを使うので、下記を忘れずに。

use Illuminate\Support\Facades\Auth;

config/auth.php を操作していきます。

細かい説明は省いてしまいますが、

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

        'user' => [
            'driver' => 'session',
            'provider' => 'users',
        //    'provider' => 'admins',
        ],

        // Admin用の認証を追加
        'admin' => [
            'driver' => 'session',
            'provider' => 'admins',
        ],            
    ] 

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

         // Admin用のmodel連携を追加 
        'admins' => [
            'driver' => 'eloquent',
            'model' => App\Models\Admin::class,
        ]        
    ], 

adminという権限を付与するためにadmin部分を追加します。
これがあることによって

・Auth::guard(‘admin’); が使えるようになります。
・また、adminsというDBからユーザー認証するためのログインユーザーを抽出できます。

先ほども言及した通り、認証はログイン時に付与される権限です。
どこのDBからのログインなのかで、認証を切り分ける仕組みがあるのです。

・ 権限に応じて、閲覧可能(閲覧不可)に制御する方法

権限を付与できたら、後はどの権限なのかによって閲覧可能 / 不可を制御してあげればOKです。

やり方は幾つかあると思います。
Routeで制御する方法と、Controllerで制御する方法です。
どちらにしても、Middlewearを使って制御します。

controllerで制御する方法を紹介しておきます。
ルーティングで振り分けるcontrollerのconstructにて宣言します。
この宣言によって、admin 権限を持って、ログインしたユーザーのみ閲覧することができます。

     public function __construct()
    {
        $this->middleware('auth:admin');
    } 

参考にさせて頂いたサイトは下記です。

ttps://qiita.com/namizatop/items/5d56d96d4c255a0e3a87

LaravelでGET,POSTにパラメーターを追加して、渡す方法・受け取る方法

Webアプリケーションでのデータの受け渡しで使われる、GET・POSTです。
普通に使う場合の説明は、色々と紹介されていると思います。

今回は、パラメータを追加した場合の方法に絞って説明していきます。

GETにパラメーターを追加した場合

まずは、GETにパラメータを追加した場合です。
GETの特徴としては、URLに情報を渡してデータのやりとりをする部分です。

重要情報を明記するのはNG行為ですね。
使われ方としては、ページ別 id とかで出し分けるときに使います。

Route・Controllerで必要な処理を明記していきます。

■Route

Route::get('URL/{parameter}','Controller@method');

メソッドはgetです。
重要な部分は、{parameter}です。
ここに引き渡したいパラメータをセットされるようにします。

■Controller

controllerでデータを受け取る場合は単純です。

public function method($parameter)    {
// $parameter を使える。
}

メソッドの引数に変数を入れてあげればOKです。
(引数の名称はなんでもOK!なはずです。)

POSTにパラメーターを追加した場合

POSTでサーバにデータを送信する際は、HTTPリクエストボディにデータが記述されるので、比較的安全にデータを渡すことができます。
フロント側から、サーバー側へデータを渡すことができます。

HTMLのformからPOSTを送信する場合は、パラメータをactionの中に組み込みます。

  <form method="POST" 
        action="{{ route('route_nama', ['key' => $parameter]) }}"> 
 </form> 

controllerで受け取る場合には、

public function method(Request $request)    
{     
// $request->key でpameterの内容を受け取ることができる。

}

$requestの中にデータが入っています。
引き出す際には、送信する際に設定した、keyを変数名にして
$request->key を指定することで受け取ることができます。

Laravelのメール配信機能をyahoo Mailを使って送信する方法

LaravelでWebサービスを作っています。
仮登録で、メールに誘導してから本登録をする導線を作ろうとして大分てこずりました。

一連の流れは、Quitaでの投稿を参考にさせて頂いております。
※ 幾つか修正をしつつ参考にさせて頂いております。
https://qiita.com/nitaking/items/588a645968efcac6d37a

今回紹介するのは、メール送信システムとしてYahooメールを使う方法です。
(記事通りに、 mailtrap を活用する方には不要な内容です。)

ざっくりとした流れは、下記です。

1:Yahooアドレスを用意
2:Yahooでの設定を有効にする。※Yahooダイレクトオファーへの登録も必要
3:Laravelで.env に情報を反映
4:Laravelで config/mail.phpの情報を変更
5:必要に応じて、キャッシュ情報のclear

[追記]6:Yahooに制限をかけてブロックされました。

1:Yahooアドレスを用意

これは言わずもがなですね。準備してください。
重要なことは、 メール送信設定をする際に、パスワードの登録が必要なのでパスワードを発行してください。
最近は仕様が変更したのか、SMSでの番号認証で、パスワードでの登録を省いてる仕様でした。なので、アカウントを作成した後に、パスワードの作成をして下さい。(謎の二度手間ですね。)

パスワードの作成方法は、
登録情報 > ログインとセキュリティ > パスワードの変更

https://accounts.yahoo.co.jp/profile?.src=ym&.done=https://mail.yahoo.co.jp/&current=security

2:Yahooでの設定を有効にする。※Yahooダイレクトオファーへの登録も必要

外部のシステム(今回は、Laravel)を利用してYahooメールシステムから、メール送信する場合には幾つかの設定を完了しておく必要があります。

「IMAP」「POP」「SMTP」をそれぞれ「有効にする」を選択します。

Yahoo公式サイトに掲載されている情報に従って、メール設定から 「IMAP」「POP」「SMTP」が有効になっているのかを確認してください。有効でない場合には、変更をして下さい。

https://knowledge.support.yahoo-net.jp/PccMail/s/article/H000007321

Yahoo!ダイレクトオファーの登録

これ必要性は若干謎だと思っているのですが、Yahoo!ダイレクトオファーの登録が必要なようです。

Yahoo!ダイレクトオファーは、Yahoo! JAPANまたは提携先企業から、新商品、各種セール、お買い得情報などをお知らせするサービスです。

https://support.yahoo-net.jp/PccDirect/s/article/H000011064

必要とのことなので、登録しておきましょう。
設定変更は、下記からいけます。

https://direct.yahoo.co.jp/config/deliver?.src=help

3:Laravelで.env に情報を反映

Laravelに移って、.envの設定をしていきましょう。
ここでの設定が、理解が足らずエラーに苦しみました。
.envで設定されるべき内容が何かを正しく理解して、今回使うYahooのシステムを利用するためには、何が必要なのかを判断しましょう。という話です。

Yahooが指定している情報を参考にしてください。

https://knowledge.support.yahoo-net.jp/PccMail/s/article/H000011473

送信の際に気を付けるべき項目は下記です。

送信メールの通信方式    SSL
送信メール(SMTP)サーバー    smtp.mail.yahoo.co.jp
SMTPサーバのポート番号    465

このyahooのルールを参考に
.envで設定されるべき項目は下記です。

MAIL_DRIVER=smtp
MAIL_HOST=smtp.mail.yahoo.co.jp
MAIL_PORT= 465
MAIL_USERNAME=<Yahooのユーザー名>
MAIL_PASSWORD=<Yahooのパスワード>
MAIL_ENCRYPTION=ssl
MAIL_FROM_ADDRESS=<Yahooのユーザー名>@yahoo.co.jp
MAIL_FROM_NAME=<好きなNameを設定>

4:Laravelで config/mail.phpの情報を変更

.env に情報を反映でOKかなと思っていましたが
下記、エラー分が発生しました。

Connection to tcp://smtp.mail.yahoo.com:465 Timed Out

色々と調べていくと、下記にたどり着きました。

https://stackoverflow.com/questions/38341424/connection-to-tcp-smtp-mail-yahoo-com465-timed-out/38361849

どうやら、config/mail.phpの設定を一部変更する必要があるとか。
(この設定をして、エラーが消えましたが、もしかすると .envでMAIL_ENCRYPTION=sslを設定するだけでOKかもしれないです。)

5:必要に応じて、キャッシュ情報のclear

.envの情報を変更するとすぐに情報が反映されずに、データがキャッシュに残ってしまう場合があります。その際には、キャッシュをクリアしてあげましょう。

ターミナル(コマンドプロンプト)にて、下記を実行してあげてください。

php artisan cache:clear 
php artisan config:clear 

[追記]6:Yahooに制限をかけてブロックされました。

上記のように、Yahooで登録して5件ほどメールの送信をしていたところ、下記エラーがでました。

 Expected response code 250 but got code "521", with message "521 smtp.mail.yahoo.co.jp closing transmission channel. User is over the limit for messages allowed to be sent in a single day.  " 

色々と調べていくと、Yahoo側で制限をかけているようです。

これは、Yahooのアドレスを使って送信をするのは得策ではないかもしれないですね…

Laravelで「Illuminate\XXXX」はどこにあるのか。

Laravelで開発を始めたばかりです。
フレームワークあるあるですが、様々な場所からクラスを継承してきて、何処に何があるのかが慣れるまで分かりづらいです。

Illuminate はどこにあるのかを解説していきます。

use Illuminate \ XXXX
は、よく使うと思いますが、
一番上のフォルダ階層に Illuminate というフォルダはありません。
どこにあるのでしょうか。

vendor\laravel\framework\src\illuminate

↑ ここに、あります。

Laravelでphp artisan migrateをするとエラー:「 [1044]Access denied for user」を解決した

MySQLとの接続において、Access deniedされたのを解決した方法です。
自分の場合は、普通に何度もphp artisan migrate(MySQLとの接続)を実行していて急に接続出来なくなったシチュエーションです。

調べていくと、下記のサイトが有力情報としてあがってきました。

https://qiita.com/terry_6518/items/13f5fbf4e5f58577d6d9

.env ファイルで、MySQLとの接続情報を所持しており、そこの情報が違うのではないか??という情報がチラホラ。

.envファイルを確認しても、
接続出来ていた状態と何も変わらない….

ということは、MySQL側で何か変化が起きている可能性がありそう。
ということで確認してみると。

接続可能なユーザー情報を確認しようと、MySQLの特権にアクセスすると、エラーが…..

全く同じエラーで困っている人の情報を参考に、このエラーを解決しました。

https://tt-computing.com/mariadb-error-176

すると、もともと接続するために作っていた
DB_USERNAMEが消えているではないですか。

特権から、ユーザアカウントを追加する、で新しく追加しました。

.envの

DB_DATABASE=XXXX
DB_USERNAME=XXXX 
DB_PASSWORD=XXXX

にセットすることで解決できました…!

LaravelでAuth::routes()の処理はどこに記述されているのか。

routeを確認してみましょう。
routes/web.php

Auth::routes();
と記載されています。
こちらを参照して、route設定が行われております。

このrouteの中身は下記に記載されています。
laravel/vendor/laravel/framework/src/Illuminate/Routing/Router.php

で、下記の記述を見ると
RegisterControllerにメソッドを指定しているように書かれています。
    $this->get(‘register’, ‘Auth\RegisterController@showRegistrationForm’)->name(‘register’);
    $this->post(‘register’, ‘Auth\RegisterController@register’);

しかし、
RegisterControllerの中にメソッドが記載されていません。

register・showRegistrationFormなどのメソッドはどこから呼び出されているかというと
下記です。

use Illuminate\Foundation\Auth\RegistersUsers;

laravelでデータ取得時にNULLかどうかを判別する方法

laravelでMySQLとデータ通信をしていることを前提とします。

クエリビルダーを活用して、laravelからデータを抽出した際に、NULLのときと、データがある場合でviewの表示方法を変える方法です。

controllerから  compact(‘Answer’) というカタチで、
データベースの返り値をAnswer変数にて渡します。

viewでの書き方は

@if ($questions->first() === NULL ) 
  AAA
@else
  BBB
@endif