#20-Laravel-Eloquent Relation One to Many

Seperti yang sudah kita pelajari sebelumnya, Eloquent memiliki fitur untuk membuat relasi antar table dengan mudah. relasi one to many adalah relasi antar table yang mana satu buah table bisa memiliki banyak relasi ke record data yang ada di table yang satunya.

One to Many Relationship

Akan saya contohkan dengan table customers, dan table orders. seorang customer bisa memiliki banyak order, dan banyak order bisa dimiliki oleh seorang customer. jadinya one to many atau many to one. 1 .. n atau n .. 1.

Persiapan

Kita akan membuat dua buah table, yaitu table customers, dan table orders. dimana nantinya akan kita buat relasi table one to many (satu customer bisa memiliki banyak order).

Buat model untuk dua table tersebut + migrations

Buat model Customer + Migrations

php artisan make:model Customer -m

buka file database/migrations/xxxx_create_customers_table.php modifikasi function up() seperti di bawah ini:

public function up()
{
    Schema::create('customers', function (Blueprint $table) {
        $table->increments('id');
        $table->string('fullname');
        $table->string('email');
        $table->text('address');
        $table->timestamps();
    });
}

Buat model Order + Migrations

php artisan make:model Order -m

buka file database/migrations/xxxx_create_orders_table.php modifikasi function up() seperti di bawah ini:

public function up()
{
    Schema::create('orders', function (Blueprint $table) {
        $table->increments('id');
        $table->date('order_date');
        $table->integer('total_price');
        $table->integer('paid');
        $table->integer('customer_id');
        $table->timestamps();
    });
}

Migrate Table

php artisan migrate

Buka database anda, hasilnya sbb:

New table customers & orders

Modifikasi Model One to Many

Edit model app/Customer.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Customer extends Model
{
    //
    public function order(){
    	return $this->hasMany('App\Order');
    }
}

Edit model app/Order.php

<?php

namespace App;

use Illuminate\Database\Eloquent\Model;

class Order extends Model
{
    //
    public function customer(){
    	return $this->belongsTo('App\Customer');
    }
}

Membuat template master

Setelah database siap, kita akan membuat master template pada resources/views/template.blade.php

<html>
    <head>
        <meta charset="utf-8">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <meta name="csrf-token" content="{{ csrf_token() }}">
        <title>{{$title}}</title>
        <link rel="stylesheet" type="text/css" href="{{ asset('/css/app.css') }}">
    </head>
    <body>
        <nav class="navbar navbar-expand-lg navbar-dark bg-dark">
            <a class="navbar-brand" href="#">Navbar</a>
            <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarNav" aria-controls="navbarNav" aria-expanded="false" aria-label="Toggle navigation">
              <span class="navbar-toggler-icon"></span>
            </button>
            <div class="collapse navbar-collapse" id="navbarNav">
              <ul class="navbar-nav">
                <li class="nav-item">
                  <a class="nav-link" href="/customer">Customer <span class="sr-only">(current)</span></a>
                </li>
                <li class="nav-item">
                  <a class="nav-link" href="/order">Orders</a>
                </li>
              </ul>
            </div>
        </nav>
        <div class="container-fluid">
            @yield('main')
        </div>
        <footer class="container-fluid">
            <p>&copy; <a href="https://ombagoes.com">ombagoes.com</a>. 2019 - 2020</p>
        </footer>
    </body>
    <script src="{{ asset('js/app.js') }}"></script>
</html>

Buat Route, Controller & View Customer

Tambahkan baris berikut pada routes/web.php

// route customer
Route::get('customer', 'CustomerController@index');
Route::get('customer/search', 'CustomerController@search');
Route::match(array('GET','POST'),'customer/create', 'CustomerController@create');
Route::match(array('GET','POST'),'customer/edit/{id}', 'CustomerController@edit');
Route::get('customer/delete/{id}', 'CustomerController@delete');
Route::get('customer/trash', 'CustomerController@trash');
Route::get('customer/restore/{id}', 'CustomerController@restore');
Route::get('customer/restore_all', 'CustomerController@restore_all');
Route::get('customer/delete_permanent/{id}', 'CustomerController@delete_permanent');
Route::get('customer/delete_permanent_all', 'CustomerController@delete_permanent_all');

Buat Controller Customer

php artisan make:controller CustomerController

Modifikasi file app/http/controllers/CustomerController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Customer;

class CustomerController extends Controller
{
    public function index()
    {
    	$customer = Customer::paginate(5);
        $data['title']='Data Customer';
        $data['data']=$customer;
    	return view('customer', $data);
    }
    public function search(Request $request){
		$search_fullname = $request->search_fullname;

        $customer=Customer::when($search_fullname, function ($query, $search_fullname) {
                    return $query->where('fullname','like',"%".$search_fullname."%");
                })
            ->paginate(5);
        
		$data['data'] = $customer;
        $data['title']="Hasil Pencarian ..";
		return view('customer',$data);
	}
    public function create(Request $request){
        if($request->btnSubmit){
            $this->validate($request,[
                'fullname' => 'required',
                'email' => 'required|email',
                'address' => 'required',
            ]);
            
            Customer::create([
                'fullname' => $request->fullname,
                'email' => $request->email,
                'address' => $request->address,
            ]);
            return redirect('/customer');
        }
        $data['title']='Tambah Customer';
        return view('customer_form', $data);
    }
    public function edit(Request $request, $id){
        if($request->btnSubmit){
            $this->validate($request,[
                'fullname' => 'required',
                'email' => 'required|email',
                'address' => 'required',
            ]);
            $customer = Customer::find($id);
            $customer->fullname = $request->fullname;
            $customer->email = $request->email;
            $customer->address = $request->address;
            $customer->save();
            return redirect('/customer');
        }
        $data['title']='Ubah Customer';
        $data['edit']= Customer::find($id);
        return view('customer_form', $data);
    }
    public function delete($id){
        $customer = Customer::find($id);
        $customer->delete();
        return redirect(url()->previous());
    }
    public function trash(){
        $data['title']='Tempat Sampah';
        $data['data'] = Customer::onlyTrashed()->get();
        return view('customer_trash', $data);
    }
    public function restore($id){
        $customer = Customer::onlyTrashed()->where('id',$id);
        $customer->restore();
        return redirect('/customer/trash');
    }
    public function restore_all(){
    		
    	$customer = Customer::onlyTrashed();
    	$customer->restore();
 
    	return redirect('/customer/trash');
    }
    public function delete_permanent($id){
    	$customer = Customer::onlyTrashed()->where('id',$id);
    	$customer->forceDelete();
    	return redirect('/customer/trash');
    }
    public function delete_permanent_all(){
    	$customer = Customer::onlyTrashed();
    	$customer->forceDelete();

    	return redirect('/customer/trash');
    }
}

Buat View untuk CustomerController

  1. customer.blade.php, untuk menamplikan isi table customer dan navigasi tambah, ubah, & hapus.
  2. customer_form.blade.php, untuk menampilkan form tambah/ubah customer.
  3. customer_trash.blade.php, untuk menampilkan data yang sudah dihapus(temporary) Soft Deletes.

resources/views/customer.blade.php

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="{{url()->current()}}/create" class="btn btn-primary">Tambah Baru</a>
         | <a href="{{url()->current()}}/trash">Tong Sampah <i class="fa fa-trash" aria-hidden="true"></i></a>
        <br/>
        <br/>
        <p>Cari :</p>
        <form class="form-inline" action="{{url()->current()}}/search" method="GET">
            <label class="sr-only" for="inlineFormInputFullname">Nama Lengkap</label>
            <input name="search_fullname" type="text" class="form-control mb-2 mr-sm-2" id="inlineFormInputFullname" placeholder="Nama Lengkap .." value="{{ old('search_fullname') }}">
            <button type="submit" class="btn btn-primary mb-2">Submit</button>
        </form>
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>Nama</th>
                    <th>Email</th>
                    <th>Alamat Tinggal</th>
                    <th width="175">Aksi</th>
                </tr>
            </thead>
            <tbody>
                @foreach($data as $row)
                <tr>
                    <td>{{ $row->fullname }}</td>
                    <td>{{ $row->email }}</td>
                    <td>{{ $row->address }}</td>
                    <td>
                        <a href="{{url()->current()}}/edit/{{ $row->id }}" class="btn btn-warning">Ubah</a>
                        <a href="{{url()->current()}}/delete/{{ $row->id }}" class="btn btn-danger">Hapus</a>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
        <br/>
        Halaman : {{ $data->currentPage() }} <br/>
        Jumlah Data : {{ $data->total() }} <br/>
        Data Per Halaman : {{ $data->perPage() }} <br/>
    
    
        {{ $data->links() }}
    </div>
</div>
@endsection

resources/views/customer_form.blade.php

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="/customer" class="btn btn-primary">Kembali</a>
        <br/>
        <br/>
        
        <form method="post" action="{{url()->current()}}">
            {{ csrf_field() }}
            <div class="form-group">
                <label>Nama Lengkap</label>
                <input type="text" name="fullname" class="form-control" placeholder="Nama Lengkap .."
                value="{{@$edit->fullname}}" >

                @if($errors->has('fullname'))
                    <div class="text-danger">
                        {{ $errors->first('fullname')}}
                    </div>
                @endif

            </div>
            <div class="form-group">
                <label>Email</label>
                <input type="text" name="email" class="form-control" placeholder="Email .."
                value="{{@$edit->email}}">

                @if($errors->has('email'))
                    <div class="text-danger">
                        {{ $errors->first('email')}}
                    </div>
                @endif

            </div>
                
            <div class="form-group">
                <label>Alamat</label>
                <textarea name="address" class="form-control" placeholder="Alamat ..">{{@$edit->address}}</textarea>

                 @if($errors->has('address'))
                    <div class="text-danger">
                        {{ $errors->first('address')}}
                    </div>
                @endif

            </div>

            <div class="form-group">
                <input name="btnSubmit" type="submit" class="btn btn-success" value="Simpan">
            </div>

        </form>

    </div>
</div>
@endsection
customer_form.blade

resources/views/customer_trash.blade.php

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="/customer" class="btn btn-primary">Kembali</a>
        <br/>
        <br/>
        <a href="/customer/restore_all">Kembalikan Semua</a>|<a href="/customer/delete_permanent_all">Hapus Permanen Semua</a>
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>Nama</th>
                    <th>Email</th>
                    <th>Alamat</th>
                    <th width="175">Aksi</th>
                </tr>
            </thead>
            <tbody>
                @foreach($data as $row)
                <tr>
                    <td>{{ $row->fullname }}</td>
                    <td>{{ $row->email }}</td>
                    <td>{{ $row->address }}</td>
                    <td>
                        <a href="/customer/restore/{{ $row->id }}" class="btn btn-success btn-sm">Restore</a>
                        <a href="/customer/delete_permanent/{{ $row->id }}" class="btn btn-danger btn-sm">Hapus Permanen</a>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
    </div>
</div>
@endsection

customer_trash.blade

Buat Route, Controller & View Order

Tambahkan baris berikut pada routes/web.php

// route order
Route::get('order', 'OrderController@index');
Route::get('order/search', 'OrderController@search');
Route::match(array('GET','POST'),'order/create', 'OrderController@create');
Route::match(array('GET','POST'),'order/edit/{id}', 'OrderController@edit');
Route::get('order/delete/{id}', 'OrderController@delete');

Buat Controller Order

php artisan make:controller OrderController

Modifikasi file app/http/controllers/OrderController.php

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Order;
use App\Customer;

class OrderController extends Controller
{
    public function index()
    {
    	$order = Order::paginate(5);
        $data['title']='Data Order';
        $data['data']=$order;
    	return view('order', $data);
    }
    public function search(Request $request){
		$search_fullname = $request->search_fullname;
        $order=Order::leftJoin('customers','customers.id','customer_id')
            ->when($search_fullname, function ($query, $search_fullname) {
                    return $query->where('fullname','like',"%".$search_fullname."%");
                })
            ->paginate(5);
		$data['data'] = $order;
        $data['title']="Hasil Pencarian ..";
		return view('order',$data);
	}
    public function create(Request $request){
        if($request->btnSubmit){
            $this->validate($request,[
                'customer_id' => 'required',
                'order_date' => 'required',
                'total_price' => 'required',
                'paid' => 'required',
            ]);
            
            Order::create([
                'customer_id' => $request->customer_id,
                'order_date' => $request->order_date,
                'total_price' => $request->total_price,
                'paid' => $request->paid,
            ]);
            return redirect('/order');
        }
        $data['title']='Tambah Order';
        return view('order_form', $data);
    }
    public function edit(Request $request, $id){
        if($request->btnSubmit){
            $this->validate($request,[
                'customer_id' => 'required',
                'order_date' => 'required',
                'total_price' => 'required',
                'paid' => 'required',
            ]);
            $order = Order::find($id);
            $order->customer_id = $request->customer_id;
            $order->order_date = $request->order_date;
            $order->total_price = $request->total_price;
            $order->paid = $request->paid;
            $order->save();
            return redirect('/order');
        }
        $data['title']='Ubah Order';
        $data['edit']= Order::find($id);
        return view('order_form', $data);
    }
    public function delete($id){
        $order = Order::find($id);
        $order->delete();
        return redirect(url()->previous());
    }
}

Buat View untuk OrderController

  1. order.blade.php, untuk menamplikan isi table order dan navigasi tambah, ubah, & hapus.
  2. order_form.blade.php, untuk menampilkan form tambah/ubah order.

Karena Order bukan merupakan table master saya rasa kita tidak perlu menyiapkan temporari hapus.

resources/views/order.blade.php

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="{{url()->current()}}/create" class="btn btn-primary">Tambah Baru</a>
        <br/>
        <br/>
        <p>Cari :</p>
        <form class="form-inline" action="/order/search" method="GET">
            <label class="sr-only" for="inlineFormInputFullname">Nama Lengkap</label>
            <input name="search_fullname" type="text" class="form-control mb-2 mr-sm-2" id="inlineFormInputFullname" placeholder="Nama Lengkap .." value="{{ old('search_fullname') }}">
            <button type="submit" class="btn btn-primary mb-2">Submit</button>
        </form>
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>Nama</th>
                    <th>Tgl. Order</th>
                    <th>Tagihan</th>
                    <th>Dibayar</th>
                    <th width="175">Aksi</th>
                </tr>
            </thead>
            <tbody>
                @foreach($data as $row)
                <tr>
                    <td>{{ $row->customer->fullname }}</td>
                    <td>{{ $row->order_date }}</td>
                    <td>{{ $row->total_price }}</td>
                    <td>{{ $row->paid }}</td>
                    <td>
                        <a href="{{url()->current()}}/edit/{{ $row->id }}" class="btn btn-warning">Ubah</a>
                        <a href="{{url()->current()}}/delete/{{ $row->id }}" class="btn btn-danger">Hapus</a>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
        <br/>
        Halaman : {{ $data->currentPage() }} <br/>
        Jumlah Data : {{ $data->total() }} <br/>
        Data Per Halaman : {{ $data->perPage() }} <br/>
    
    
        {{ $data->links() }}
    </div>
</div>
@endsection
order.blade.php

resources/views/order_form.blade.php

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="/customer" class="btn btn-primary">Kembali</a>
        <br/>
        <br/>
        
        <form method="post" action="{{url()->current()}}">
            {{ csrf_field() }}
            
            <div class="form-group">
                <label>Nama Lengkap</label>
                <select class="form-control" name="customer_id">
                <option>Select Customer</option> 
                @foreach (App\Customer::select('id','fullname')->get() as $customer)
                    <option value="{{ $customer->id }}" {{ ( $customer->id == @$edit->customer_id) ? 'selected' : '' }}> 
                        {{ $customer->fullname }} 
                    </option>
                @endforeach    
              </select>

                @if($errors->has('customer_id'))
                    <div class="text-danger">
                        {{ $errors->first('customer_id')}}
                    </div>
                @endif

            </div>
            <div class="form-group">
                <label>Tgl. Order</label>
                <input type="date" name="order_date" class="form-control" placeholder="Tgl. Order .."
                value="{{(@$edit->order_date?$edit->order_date:date("Y-m-d"))}}" >
                @if($errors->has('order_date'))
                    <div class="text-danger">
                        {{ $errors->first('order_date')}}
                    </div>
                @endif
                
            </div>
                
            <div class="form-group">
                <label>Total Tagihan</label>
                <input type="number" name="total_price" class="form-control" placeholder="Total Tagihan .."
                value="{{@$edit->total_price}}" >

                @if($errors->has('total_price'))
                    <div class="text-danger">
                        {{ $errors->first('total_price')}}
                    </div>
                @endif
                
            </div>
                
            <div class="form-group">
                <label>Total Pembayaran</label>
                <input type="number" name="paid" class="form-control" placeholder="Total Pembayaran .."
                value="{{@$edit->paid}}" >
            </div>

            <div class="form-group">
                <input name="btnSubmit" type="submit" class="btn btn-success" value="Simpan">
            </div>

        </form>

    </div>
</div>
@endsection
order_form.blade.php

Tambahkan beberapa Order untuk Customer, lalu ubah resources/views/customer.blade.php untuk menampilkan jumlah order

@extends('template')
@section('main')
<div class="card mt-5">
    <div class="card-header text-center">
        {{$title}}
    </div>
    <div class="card-body">
        <a href="{{url()->current()}}/create" class="btn btn-primary">Tambah Baru</a>
        &nbsp;|&nbsp;<a href="{{url()->current()}}/trash">Tong Sampah <i class="fa fa-trash" aria-hidden="true"></i></a>
        <br/>
        <br/>
        <p>Cari :</p>
        <form class="form-inline" action="{{url()->current()}}/search" method="GET">
            <label class="sr-only" for="inlineFormInputFullname">Nama Lengkap</label>
            <input name="search_fullname" type="text" class="form-control mb-2 mr-sm-2" id="inlineFormInputFullname" placeholder="Nama Lengkap .." value="{{ old('search_fullname') }}">
            <button type="submit" class="btn btn-primary mb-2">Submit</button>
        </form>
        <table class="table table-bordered table-hover table-striped">
            <thead>
                <tr>
                    <th>Nama</th>
                    <th>Email</th>
                    <th>Alamat Tinggal</th>
                    <th>Jml. Order</th>
                    <th width="175">Aksi</th>
                </tr>
            </thead>
            <tbody>
                @foreach($data as $row)
                <tr>
                    <td>{{ $row->fullname }}</td>
                    <td>{{ $row->email }}</td>
                    <td>{{ $row->address }}</td>
                    <td>{{ $row->order->count() }}</td>
                    <td>
                        <a href="{{url()->current()}}/edit/{{ $row->id }}" class="btn btn-warning">Ubah</a>
                        <a href="{{url()->current()}}/delete/{{ $row->id }}" class="btn btn-danger">Hapus</a>
                    </td>
                </tr>
                @endforeach
            </tbody>
        </table>
        <br/>
        Halaman : {{ $data->currentPage() }} <br/>
        Jumlah Data : {{ $data->total() }} <br/>
        Data Per Halaman : {{ $data->perPage() }} <br/>
    
    
        {{ $data->links() }}
    </div>
</div>
@endsection

Tampilannya akan sbb:

Jml Order/Customer

Perhatikan Jml. Order, menampilkan jml order dari Customer. One To Many berarti satu Customer bisa melakukan beberapa Order sementara satu Order hanya bisa dimiliki oleh satu Customer.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes:

<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <s> <strike> <strong>