Laravel 5.2 Auth::user() に他テーブルのJOINしたデータを追加する。

先の記事で、標準の認証機能を使用したが、認証情報に他テーブルのデータも保持しおきたいと思い、調べてみましたがちょっとやり方が違うのか手こずりました。

クライアント環境:Windows10 XAMPP(PHP7.0.4) Eclipse 4.5.2(Mars) Laravel5.2.39

サーバ環境:CentOS7 MariaDB5.5.47

公式(https://laravel.com/

調べてみる!

Google先生に「laravel5 auth user join」で聞いてみた。

http://ja.stackoverflow.com/questions/11271/laravel-5-の-authuser-のプロパティにjoinしたデータを追加したい

おぉ!stackoverflow先生まで日本語版が出てきたのね。と思いながらそのままやってみる。
ダメだった!まぁそんなもんです。日本語版が無いときもそんなもんです。いい線は行くのは間違いないので、stackoverflow先生も必要なんですよ。そのものズバリってのは面白く無い!(工数の問題はともかくとして…)

結果

私の愚痴なんてどうでもいいので、結果はこんな感じ。

まずは、認証クラスをオーバーライドして発行されるSQLを変更するために、プロバイダを作る。

<?php
namespace App\Providers;

use Illuminate\Auth\EloquentUserProvider;

class AuthUserProvider extends EloquentUserProvider
{
	public function retrieveById($identifier) {
		$result = $this->createModel()->newQuery()
			->leftJoin('corps', 'users.corp_id', '=', 'corps.id')
			->leftJoin('shops', 'users.shop_id', '=', 'shops.id')
			->select(['users.*', 'corps.name as corp_name', 'shops.name as shop_name'])
			->find($identifier);
		return $result;
	}

}

そのユーザの所属している法人名と店舗名をJOINした結果を取得する感じですね。

次、上記のクラスを認証ドライバとして追加します。

<?php
namespace App\Providers;

use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;

use App\Providers\AuthUserProvider;
use Auth;

class AuthServiceProvider extends ServiceProvider
{
	/**
	 * The policy mappings for the application.
	 *
	 * @var array
	 */
	protected $policies = [
		'App\Model' => 'App\Policies\ModelPolicy',
	];

	/**
	 * Register any application authentication / authorization services.
	 *
	 * @param  \Illuminate\Contracts\Auth\Access\Gate  $gate
	 * @return void
	 */
	public function boot(GateContract $gate)
	{
		$this->registerPolicies($gate);

		//
	}

	public function register() {

		Auth::provider('auth_ex', function($app) {
			// スタックオーバーフロー先生はこれで取れると書いてあるんだけど、モデルが取れない…
			// $model = $this->app['config']['auth.model'];
			$model = $app['config']['auth.providers.users.model'];
			return new AuthUserProvider($app['hash'], $model);
		});

	}

}

register()メソッドは無いので追加してあげます。
モデルの取得があれでいいのかはだいぶ微妙な書き方だなと。もうちょっと良いやり方があれば教えてください。

次、’auth_ex’を定義してあげないといけません。

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

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

		// 'users' => [
		//     'driver' => 'database',
		//     'table' => 'users',
		// ],
	],
<<省略>>

以上、これで「Auth::user()->shop_name」ってやると店舗名が取得できたりします。