Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得
Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使って一覧ページのデータをデータベースから取得する方法をご紹介します。
(Laravelバージョン6)CLOSE
Contents
- 2つのテーブル構造
 - Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するModelの記述
 - Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するControllerの記述
 - Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するview(一覧ページ)の記述
 - Routeの記述
 
ディスプレイ広告
2つのテーブル構造
商品名が登録されてるlistpagesテーブルと、listpagesテーブルから商品を登録したユーザーが登録されてるusersテーブル(子)の2つのテーブルを用意しました。
listpagesテーブル(親)
| 名前 | 説明 | 
|---|---|
| id | 主キー | 
| product_name | 商品名 | 
| user_id | 商品登録ユーザーID=usersテーブルのid ※usersテーブルのテーブル名から「s」を除いた名前「user」とusersテーブルの主キー「id」にアンダーバー「_」を付けた名前「user_id」にする必要があります。こうすることでusersテーブルからidが一致したデータを取得することができます。  | 
usersテーブル(子)
| 名前 | 説明 | 
|---|---|
| id | 主キー | 
| name | ユーザー名 | 
| メールアドレス | 
Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するModelの記述
※ListpageモデルにUserモデルのデータを取得する記述をします。
class Listpage extends Model
{
	public function user()
	{
		//Userモデルのデータを取得する
	    return $this->belongsTo('App\User');
	}
}
Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するControllerの記述
※listpagesテーブルのuser_idと一致するusersテーブルからidとnameを取得します。検索条件としてlistpagesテーブルのproduct_name(商品名)をlike検索します。
内部結合(join)を使ってデータを取得する場合
※内部結合とは2つのテーブルを結合して指定したそれぞれのテーブルのカラムの値が一致するデータだけを取得する方法です。単純なselectだと「INNER JOIN」を使用します。
以下の「->join(‘users’,’users.id’,’=’,’listpages.user_id’)」箇所が内部結合の処理になります。「usersのid」と「listpagesのuser_id」が一致するデータのみを取得します。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;   //Userモデルを使用
use App\Listpage;   //Listpageモデルを使用
    public function listdata(Request $request)
    {
        $sort = 'listpages.id';
        $order = 'desc';
        $sql = '1=1';
        $product_name = "";
        if(!empty($request->product_name)){
            $product_name = $request->product_name;
            $sql .= " AND listpages.product_name like '%".$request->product_name."%'";
        }
	//listpagesテーブルのuser_idと一致するusersテーブルからidとnameを取得。検索条件としてlistpagesテーブルのproduct_name(商品名)をlike検索。
        $listpages = Listpage::with(['user:id,name'])
        ->join('users','users.id','=','listpages.user_id')	//内部結合
        ->select('listpages.*','users.id as uid')
        ->whereRaw($sql)
        ->orderBy($sort, $order)->paginate(20);
	//検索条件listpagesテーブルのproduct_name(商品名)とをparamとしてviewに渡す。
        return view('listpages', [
            'listpages' => $listpages,
            'product_name' => $product_name,
            'param' => [
                'product_name' => $product_name,
            ],
        ]);
    }
外部結合(leftJoin)を使ってデータを取得する場合
※外部結合とは内部結合と同じく2つのテーブルでそれぞれ結合の対象となるカラムを指定し、各カラムに同じ値が格納されているデータを結合して取得します。
 内部結合の場合は一致するデータのみ取得しますが、外部結合は片方どちらかのテーブルに一致しないデータも取得します。
以下の「->leftJoin(‘users’,’users.id’,’=’,’listpages.user_id’)」箇所が外部結合(leftJoin)の処理になります。「usersのid」と「listpagesのuser_id」が一致するデータと一致しなくても「listpagesテーブル」に存在するデータは全て取得します。
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;   //Userモデルを使用
use App\Listpage;   //Listpageモデルを使用
    public function listdata(Request $request)
    {
        $sort = 'listpages.id';
        $order = 'desc';
        $sql = '1=1';
        $product_name = "";
        if(!empty($request->product_name)){
            $product_name = $request->product_name;
            $sql .= " AND listpages.product_name like '%".$request->product_name."%'";
        }
	//listpagesテーブルのuser_idと一致するusersテーブルからidとnameを取得。検索条件としてlistpagesテーブルのproduct_name(商品名)をlike検索。
        $listpages = Listpage::with(['user:id,name'])
        ->leftJoin('users','users.id','=','listpages.user_id')	//外部結合(leftJoin)
        ->select('listpages.*','users.id as uid')
        ->whereRaw($sql)
        ->orderBy($sort, $order)->paginate(20);
	//検索条件listpagesテーブルのproduct_name(商品名)とをparamとしてviewに渡す。
        return view('listpages', [
            'listpages' => $listpages,
            'product_name' => $product_name,
            'param' => [
                'product_name' => $product_name,
            ],
        ]);
    }
外部結合(rightJoin)を使ってデータを取得する場合
「leftJoin」とは逆のテーブル(usersテーブル)に存在するデータを取得する場合は「rightJoin」を使用します。
記述内容は
「->leftJoin(‘users’,’users.id’,’=’,’listpages.user_id’)」
を
「->rightJoin(‘users’,’users.id’,’=’,’listpages.user_id’)」
にするだけです。
Laravelで内部結合(join)、外部結合(leftJoin、rightJoin)を使ってデータを取得するview(一覧ページ)の記述
※内部結合(join)または外部結合(leftJoin、rightJoin)で取得したデータを表示します。
		<form enctype="multipart/form-data" action="{{ url('listpages') }}" method="GET">
	            	@csrf
			<label for="product_name">商品名</label>
			<input type="text" name="product_name" value="{{ old('product_name', $product_name) }}">
			<br>
			<button type="submit">検索</button>
        	</form>
                <div align="center">
                    {{ $listpage->appends($param)->links()}}
                </div>
                <table>
                    <thead>
                        <th>商品名</th>
                        <th>登録ユーザー</th>
                    </thead>
                    <tbody>
                        @foreach ($listpages as $listpage)
                            <tr>
                                <!-- 商品名 -->
                                <td class="table-text">
                                    <div>{{ $listpage->product_name }}</div>
                                </td>
                                <!-- 登録ユーザー -->
                                <td class="table-text">
                                    <div>{{ $listpage->user->name }}</div>
                                </td>
                            </tr>
                        @endforeach
                    </tbody>
                </table>
Routeの記述
※ページURLは必要に応じて変更して下さい。
Route::get('/listpages', 'ListpagesController@listdata');
 
 
※流用される場合は自己責任でお願いします。
関連記事LaravelLaravelでmaatwebsite/excelインストールとエクセル出力方法2022-10-24Laravel【Laravel】子、孫を含めた3つのテーブルからリレーションデータを取得する方法(Eloquentリレーション、ネスト)2022-06-16LaravelLaravelで直前のページURLを取得し前のページに戻るボタンを作成【url()->previous()】2023-10-01JavaScriptPHPを使用して動的に外部JSファイルを生成・読み込む実践ガイド

