##0.はじめに
本記事ではLaravel 5.8 での開発で得たものを取り上げております。
なぜ本記事を作成しようかと思ったのか、
Laravelの学習で ORM を用いてECサイトの注文履歴の表示画面を作っていた時に、
「リレーション先のさらに先」の情報を取得して表示させる必要がありましたが、
「データベースからの情報取得方法」を書いた記事は多く見つけられるものの、
「取得したデータの "表示" の仕方」についての記事はあまり見つけられなかったからです。
(探し方が良くなかったのかもしれませんが^^;)
「dd()で取得したレコードの確認までは出来ているが、表示させるのにエラーが出てうまくいかない!」
自分はこれで時間をだいぶ消費してしまいましたので、他の初学者がよりスムーズに開発の学習が行えるよう記事を作成いたしました。
おかしい所がありましたら、ぜひご指摘いただければと思います。
##1.注文履歴表示画面に関わる情報
###・各モデル
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Order extends Model
{
protected $table = 't_orders';
public function user()
{
return $this->belongsTo('App\User');
}
public function orderDetails()
{
return $this->hasMany('App\OrderDetail' , 'order_id');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class OrderDetail extends Model
{
protected $table = 't_order_details';
public $timestamps = false;
protected $fillable = [
'product_id',
'order_id',
'shipment_status_id',
'order_quantity',
];
public function order()
{
return $this->belongsTo('App\Order','order_id');
}
public function shipmentStatuses()
{
return $this->belongsTo('App\ShipmentStatus', 'shipment_status_id');
}
public function products()
{
return $this->belongsTo('App\Product', 'id');
}
}
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class ShipmentStatus extends Model
{
protected $table = 'm_shipment_statuses';
protected $fillable = [
'shipment_status_name',
];
public function orderDetails()
{
return $this->hasMany('App\OrderDetail','id');
}
}
<?php
namespace App;
use Illuminate\Notifications\Notifiable;
use Illuminate\Contracts\Auth\MustVerifyEmail;
use Illuminate\Foundation\Auth\User as Authenticatable;
class User extends Authenticatable
{
use Notifiable;
protected $table = 'm_users';
/**
* The attributes that are mass assignable.
*
* @var array
*/
protected $fillable = [
'last_name',
'first_name',
'zipcode',
'prefecture',
'municipality',
'address',
'apartments',
'email',
'phone_number',
'password',
'company_name'
];
/**
* The attributes that should be hidden for arrays.
*
* @var array
*/
protected $hidden = [
'password', 'remember_token',
];
/**
* The attributes that should be cast to native types.
*
* @var array
*/
protected $casts = [
'email_verified_at' => 'datetime',
];
public function orders()
{
return $this->hasMany('App\Order');
}
public function products()
{
return $this->hasMany('App\Product', 'user_id');
}
}
※Laravelの認証機能を使用しています。
(この機能を利用してログイン中のユーザーIDを取得し注文情報の検索を行います。)
###・コントローラー
class OrderController extends Controller
{
public function getHistory (Request $request)
{
//ログイン中のユーザーIDをもとに注文情報を取得する
$orderInformations = Order::where('user_id', Auth::id())
->with(['user', 'orderDetails.shipmentStatuses'])
->orderBy('order_date', 'desc')
->paginate(3);
###・現在データベースに収容されている情報(各seederより抜粋)
DB::table('t_orders')->insert([
[
'user_id' => 1,
'order_number' => 1,
'order_date' => date('2020-10-22 13:55:19'),
],
[
'user_id' => 1,
'order_number' => 2,
'order_date' => date('2020-05-03 16:32:52'),
],
DB::table('t_order_details')->insert([
[
'products_id' => 1,
'order_id' => 1,
'shipment_status_id' => 2,
'order_quantity' => 1,
'shipment_date' => date('2020-10-23 20:55:19'),
],
[
'products_id' => 2,
'order_id' => 1,
'shipment_status_id' => 2,
'order_quantity' => 2,
'shipment_date' => date('2020-10-23 20:55:19'),
],
[
'products_id' => 3,
'order_id' => 2,
'shipment_status_id' => 1,
'order_quantity' => 3,
'shipment_date' => date('Y-m-d H:i:s'),
],
DB::table('m_shipment_statuses')->insert([
[
'shipment_status_name' => '準備中',
],
[
'shipment_status_name' => '発送済',
],
[
'shipment_status_name' => '入荷待ち',
],
[
'shipment_status_name' => 'キャンセル',
],
DB::table('m_users')->insert([
[
'password' => bcrypt('sample1'),
'last_name' => '太郎',
'first_name' => '田中',
'zipcode' => '1200003',
'prefecture' => '東京都',
'municipality' => '足立区',
'address' => '1-1-1',
'apartments' => '101号室',
'email' => 'sample1@sample.com',
'phone_number' => '11111111111',
'user_classification_id' => '2',
'company_name' => '株式会社A',
'delete_flag' => '0',
],
##2.コントローラーからデータベース(以下DB)へ情報を要求
class OrdersController extends Controller
{
public function getHistory (Request $request)
{
//ログイン中のユーザーIDをもとに注文情報を取得する
$orderInformations = Order::where('user_id', Auth::id())
->with(['user', 'orderDetails.shipmentStatuses'])
->orderBy('order_date', 'desc')
->paginate(3);
まずは、ログイン中のユーザーの注文情報があるか、注文/t_ordersテーブル の検索を行います。
検索でログイン中のIDを取得してt_ordersテーブルの user_id カラムを検索します。
その際に with() を用いて情報を一括で取得しペジネーションの形にします。
##3.取得できたデータを表示するには
データの表示について解説を行っていきます。
今回表示する注文履歴のデータは、
田中 太郎 さんが
2021-03-18 16:32:52 に商品を1個、
2020-10-23 20:55:19 に商品を2個 購入した履歴です。
最後発送日と、【 発送済 】という状態の表示まで行います。
まず、dd()を行って $orderInformations の中身を見てみましょう。
\#items:
に値が入ってきました。
データベースからの情報の取得は成功です。
それを開いていくと..
\#attributes:
の中にt_ordersテーブルの情報が入ってきています。
注文の履歴が2個あるので、配列で2つ並んでますね。
では例としてorder_dateを表示させます。
表示するためには一度$orderInformationsを foreach する必要があります。
@foreach ($orderInformations as $order)
注文日時:{{ $order->order_date }}<br>
@endforeach
では foreach すると何が変わるのでしょうか?
$order
の中がどうなっているのか dd() してみます。
@foreach ($orderInformations as $order)
注文日時:{{ $order->order_date }}<br>
@endforeach
@php dd($order) @endphp
▼ 結果
\#items:
の中身だけになり、データがモデルオブジェクトになりました。
App\Order
この状態なら #attributes から取り出すことができます。
それで以下の形になります。
{{ $order->( #attributes の取り出したいカラム名) }}
では次の階層の表示に移っていきます。
m_users テーブルと、t_order_detailsテーブル の情報です。
両テーブルの情報は\#relations:
の中に入っています。
ですが、m_users テーブルと、t_order_detailsテーブルでは入り方に違いがあります。
"user"
はApp\User
であるのに対し、"orderDetails"
はilluminat…\Collection
となっています。
上記から、
"user"
= m_users テーブルの情報 は、$order
を foreach
せずとも表示することができる。
"orderDetails"
= t_order_details テーブルの情報 は、$order
を foreach
しないと表示が出来ない。
と、表示するのにforeach
の要否の違いが出ます。
では、先に手間の少ないm_users テーブルの情報の情報の表示から解説を行います。
今回は、ユーザーの氏名を表示してみます。
bladeでの表示方法は以下の様になります。
@foreach ($orderInformations as $order)
注文日時:{{ $order->order_date }}<br>
@endforeach
{{ $order->user->first_name }} {{ $order->user->last_name }}
▼ 結果
上記の方法で表示が行えます。
\#relations:
の中に入っている情報で、このようにforeach
しなくて良いのはApp\User
のパターンです。
モデルの繋がりからいくと親テーブルの情報を引き出すときです。(belongsToで引っ張ってきた情報)
では、次にt_order_details テーブルの情報の表示の解説です。
既にやり方が浮かんできている方も多いと思います。
発送日(shipment_date)の表示を行っていきます。
@foreach ($orderInformations as $order)
注文日時:{{$order->order_date}}<br>
@endforeach
{{ $order->user->first_name }} {{ $order->user->last_name }}<br>
@foreach ($orderInformations as $order)
@foreach ($order->orderDetails as $orderDetail)
発送日:{{ $orderDetail->shipment_date }}<br>
@endforeach
@endforeach
▼ 結果
表示が出来ました!
\#relations:
のなかに入っている情報を表示したくてforeach
を行う際は、
「$order
の中のorderDetails
をforeach
」 = foreach ($order->orderDetails as $orderDetail)
というように**$order
の中のforeach
するものを指定してあげます。**
これが一番最初に行った $orderInformations
のforeach
との違いです。
私はここでだいぶ時間を消費してしまいました^^;
ではでは、もうひとつ深い階層の表示を行ってみましょう。
次は m_shipment_statuses
テーブルの情報です。
これまでと同じようにdd()の結果から表示のさせ方を確認していきます。
今回のm_shipment_statuses
テーブルの情報の場合、
App\shipmentStatuses
モデルオブジェクトになっているのでforeach
は不要です。
では表示していきましょう。
@foreach ($orderInformations as $order)
注文日時:{{$order->order_date}}<br>
@endforeach
{{ $order->user->first_name }} {{ $order->user->last_name }}<br>
@foreach ($orderInformations as $order)
@foreach ($order->orderDetails as $orderDetail)
発送日:{{ $orderDetail->shipment_date }}【 {{ $orderDetail->shipmentStatuses->shipment_status_name }} 】<br>
@endforeach
@endforeach
##まとめ
illuminat…\Collection
でコレクションオブジェクトになっていれば、要foreach
App\〇〇
でモデルオブジェクトになっていれば、foreach不要
以上となります。
最後までご覧頂き、誠にありがとうございました。