com
Daftar Isi
Lisensi .................................................................................................................... 9
Pendahuluan ...................................................................................................... 10
a. Framework ........................................................................................... 10
c. Laravel ................................................................................................... 11
Daftar Gambar
Petunjuk Membaca
Tentang Penulis
Sumber kode
Lisensi
Copy (PDF, EPUB, MOBI) buku ini diberikan kepada pemilik akun
situs leanpub.com melalui mekanisme penjualan yang dilakukan
pada situs leanpub.com. Adapun copy buku ini yang diperoleh tidak
melalui cara yang telah disebutkan maka dianggap telah
melakukan pembajakan.
Pendahuluan
a. Framework
b. Mengapa framework?
fleksibel.
• Menguji dan debugging kode dengan lebih mudah.
c. Laravel
.
Gambar 4 Tren PHP Framework di Dunia
a. Desain sistem
a. Environment configuration
refreshenv
php -version
php -m
2. Composer (https://getcomposer.org/).
• Pastikan Composer dapat diakses melalui terminal dengan
mengecek pada terminal:
composer --version
⚫ Homestead (https://laravel.com/docs/5.7/homestead).
⚫ XAMPP 7.2.* for Windows.
b. Persiapan Laravel
> Illuminate\Foundation\ComposerScripts::postAutoloadDump
> @php artisan package:discover
...
Package manifest generated successfully.
> @php artisan key:generate
Application key set successfully.
Oleh karena itu, perlu dikonfigurasi default string length pada file
AppServiceProvider.php di folder app/Providers:
use Illuminate\Support\Facades\Schema;
...
public function boot()
{
Schema::defaultStringLength(191);
}
...
4. Untuk Linux dapat melalui instalasi Apache, PHP & MySQL via
package manager (apt/yum/rpm/dll.) dengan konfigurasi
VirtualHost.
c. Pemasangan Autentikasi
controller tersebut.
1. Authentication Scaffold
Untuk membuat authentication scaffold tersebut pada pustarel
ketik:
php artisan make:auth
Auth::routes();
...
d. Migrasi database
2018_11_19_234139_create_pustarel_tables
3. Mengeksekusi migration
Untuk menerapkan migration yang sudah dibuat ke dalam
database ketik perintah berikut di terminal:
php artisan migrate
Buka database manager dan lihat table sudah dibuat oleh Laravel
sesuai kode yang ditulis.
namespace App;
use Illuminate\Database\Eloquent\Model;
<?php
...
public function run()
{
$this->call(QuestionsTableSeeder::class);
}
...
menjadi kode php dan disimpan di dalam cache dan hampir tidak
menambahkan beban pada aplikasi. File blade disimpan di folder
resources/views dengan penamaan misalnya untuk file
app.blade.php yang disimpan di resources/views/layouts akan
diberi nama view layouts.app.
Dengan kode:
...
<link rel="stylesheet"
href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-
B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU"
crossorigin="anonymous">
...
</td>
</tr>
@endforeach
</tbody>
</table>
</div>
<div class="mx-auto">
{{ $paginated->links() }}
</div>
</div>
</div>
</div>
</div>
@endsection
Penjelasan kode:
Penjelasan kode:
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Question;
/**
* Show the form for creating a new resource.
*
* @return \Illuminate\Http\Response
*/
public function create()
{
//
}
/**
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
* @return \Illuminate\Http\Response
*/
public function store(Request $request)
{
//
}
/**
/**
* Show the form for editing the specified resource.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function edit($id)
{
//
}
/**
* Update the specified resource in storage.
*
* @param \Illuminate\Http\Request $request
* @param int $id
* @return \Illuminate\Http\Response
*/
public function update(Request $request, $id)
{
//
}
/**
* Remove the specified resource from storage.
*
* @param int $id
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
//
}
}
Penjelasan kode:
Penjelasan kode:
Penjelasan kode:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
//
];
}
}
}
...
public function rules()
{
return [
];
return [
'text' => 'required|min:5|max:255',
'a' => 'required|max:255',
'b' => 'required|max:255',
'c' => 'required|max:255',
'd' => 'required|max:255',
'e' => 'required|max:255',
'answer' => 'required|max:255',
];
}
...
use App\Question;
Use App\Http\Requests\StoreQuestionRequest;
...
return redirect()
->route('questions.index')
->with('flash_notification', [
'level' => 'success',
'message' => 'Berhasil menyimpan Question! (ID: ' . $question->id . ')'
]);
}
...
Penjelasan kode:
...
Route::get('questions', 'QuestionController@index')->name('questions.index');
Route::get('questions/create', 'QuestionController@create')->name('questions.create');
Route::post('questions', 'QuestionController@store')->name('questions.store');
Penjelasan kode:
</div>
@endforeach
</div>
</div>
<div class="btn-group mb-3" role="group">
<input class="btn btn-primary" type="submit" value="Edit">
</div>
</form>
</div>
</div>
</div>
</div>
@endsection
Penjelasan kode:
Penjelasan kode:
...
use App\Http\Requests\UpdateQuestionRequest;
...
public function update(UpdateQuestionRequest $request, $id)
{
$question = Question::find($id);
$question->text = $request->input('text');
$question->a = $request->input('a');
$question->b = $request->input('b');
$question->c = $request->input('c');
$question->d = $request->input('d');
$question->e = $request->input('e');
$question->answer = $request->input('answer');
$question->save();
return redirect()
->route('questions.index')
->with('flash_notification', [
'level' => 'success',
'message' => 'Berhasil mengubah Question! (ID: ' . $question->id . ')'
]);
}
...
Penjelasan kode:
$question->delete();
return redirect()
->route('questions.index')
->with('flash_notification', [
'level' => 'warning',
'message' => 'Berhasil menghapus Question! (ID: ' . $question->id . ')'
]);
}
...
...
Route::get('questions/{id}/edit', 'QuestionController@edit')->name('questions.edit');
Route::put('questions/{id}', 'QuestionController@update')->name('questions.update');
Route::delete('questions/{id}', 'QuestionController@destroy')
->name('questions.destroy');
placeholder="Search"
name="keyword"
value="{{ $keyword }}">
<button class="btn btn-success" type="submit">
Search
</button>
</div>
</form>
Penjelasan kode:
if(is_null($keyword)) {
$paginated = Question::paginate();
} else {
$paginated = Question::where('text', 'like', '%' . $keyword .'%')
->orWhere('a', 'like', '%' . $keyword .'%')
->orWhere('b', 'like', '%' . $keyword .'%')
->orWhere('c', 'like', '%' . $keyword .'%')
->orWhere('d', 'like', '%' . $keyword .'%')
->orWhere('e', 'like', '%' . $keyword .'%')
->paginate();
$paginated->appends($request->only('keyword'));
}
Penjelasan kode:
2. Menambah constraint
Selain method all(), Eloquent dapat menambahkan constraint ke
dalam query-nya dan menggunakan method get() untuk menerima
hasilnya.
$question = Question::where('answer', 'a')
->orderBy('text', 'desc')
->get();
sepuluh record pertama dari hasil yang didapatkan. SQL query yang
ekuivalen adalah SELECT * FROM questions WHERE answer = 'a' ORDER
BY text DESC.
...
public function show($id)
{
public function show(Question $question)
{
...
public function edit($id)
{
$question = Question::find($id);
public function edit(Question $question)
{
...
public function update($id, Question $question)
{
$question = Question::find($id);
public function update(UpdateQuestionRequest $request, Question $question)
{
...
public function destroy($id)
{
$question = Question::find($id);
public function destroy(Question $question)
{
...
Route::get('questions/{id}/edit', 'QuestionController@edit')->name('questions.edit');
Route::put('questions/{id}', 'QuestionController@update')->name('questions.update');
Route::delete('questions/{id}', 'QuestionController@destroy')-
>name('questions.destroy');
Route::resource('questions', 'PhotoController')->except(['show']);
<div class="form-group">
{!! Form::label('text', 'Text') !!}
{!! Form::text('text', null, [
'class' => 'form-control' . ($errors->has('text')?' is-invalid':''),
'id' => 'text',
'placeholder' => 'Enter question text'
]) !!}
<div class="invalid-feedback"> {{ $errors->first('text') }} </div>
</div>
<div class="form-group">
{!! Form::label(null, 'Answer') !!}
<div>
@foreach (range('a','e') as $alphabet)
<div class="form-check form-check-inline">
{!! Form::radio('answer', $alphabet,
($alphabet == old('answer')? true:false), [
'class' => 'form-check-input' . ($errors->has('answer')?' is-
invalid':''),
'id' => 'inlineRadio' . $alphabet
]) !!}
<label class="form-check-label" for="inlineRadio{{ $alphabet }}">
{{ $alphabet }}
</label>
</div>
@endforeach
</div>
</div>
Penjelasan kode:
Penjelasan kode:
Question::searchKeywordLike($k)
}
...
$question->c = $request->input('c');
$question->d = $request->input('d');
$question->e = $request->input('e');
$question->answer = $request->input('answer');
$question->save();
$question->update($request->all());
...
namespace App\Exports;
use App\Question;
use Maatwebsite\Excel\Concerns\FromCollection;
pada QuestionController.php:
use PDF;
...
public function pdf()
{
$data = Question::all();
$pdf = PDF::loadView('questions._pdf', compact('data'));
return $pdf->download('questions-' . date('YmdHis') . '.pdf');
}
...
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Examination;
use App\Http\Requests\StoreExaminationRequest;
use App\Http\Requests\UpdateExaminationRequest;
use Illuminate\Support\Facades\Auth;
if(is_null($keyword))
$paginated = Examination::paginate();
else {
$paginated = Examination::searchKeywordLike($keyword)
->paginate();
$paginated->appends($request->only('keyword'));
}
return redirect()
->route('examinations.index')
->with('flash_notification', [
'level' => 'success',
'message' => 'Berhasil menyimpan Examination! (ID: '
. $examination->id . ')'
]);
}
return redirect()
->route('examinations.index')
->with('flash_notification', [
'level' => 'success',
'message' => 'Berhasil mengubah Examination! (ID: '
. $examination->id . ')'
]);
return redirect()
->route('examinations.index')
->with('flash_notification', [
'level' => 'warning',
'message' => 'Berhasil menghapus Examination! (ID: '
. $examination->id . ')'
]);
}
}
Penjelasan kode:
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
}
}
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class="btn btn-primary">Add</a>
</div>
</div>
<div class="d-inline p-2 float-lg-right">
<form action="{{ route('examinations.index') }}"
method="GET">
<div class="btn-group mb-3" role="group">
<input class="form-control mr-sm-2"
type="search"
placeholder="Search"
name="keyword"
value="{{ $keyword }}">
<button class="btn btn-success" type="submit">
Search
</button>
</div>
</form>
</div>
</div>
<table class="table">
<thead>
<tr>
<th scope="col">ID</th>
<th scope="col">Name</th>
<th scope="col">Start</th>
<th scope="col">Duration</th>
<th scope="col"></th>
</tr>
</thead>
<tbody>
@foreach ($paginated as $question)
<tr>
<th scope="row">{{ $question->id }}</th>
<td> {{ $question->name }} </td>
<td>{{ $question->start }}</td>
<td>{{ $question->duration }}</td>
<td>
<a href="{{ route('examinations.edit', ['id' =>
$question->id]) }}"
class="btn btn-sm btn-light">
<i class="fa fa-edit"></i>
</a>
<form action="{{ route('examinations.destroy', ['id'
=> $question->id]) }}"
method="POST">
@method('DELETE')
{{ csrf_field() }}
<button type="submit" value="x"
</div>
</div>
@endsection
<div class="form-group">
{!! Form::label('name', 'Text') !!}
{!! Form::text('name', null, [
'class' => 'form-control' . ($errors->has('name')?' is-invalid':''),
'id' => 'name',
'placeholder' => 'Enter examination name'
]) !!}
<div class="invalid-feedback"> {{ $errors->first('name') }} </div>
</div>
<div class="form-group">
{!! Form::label('start', 'Start') !!}
{!! Form::text('start', null, [
'class' => 'form-control' . ($errors->has('start')?' is-invalid':''),
'id' => 'start',
'placeholder' => 'Enter examination start (Y-m-d H:i:s)'
]) !!}
<div class="invalid-feedback">{{ $errors->first('start') }}</div>
</div>
<div class="form-group">
{!! Form::label('duration', 'Duration') !!}
{!! Form::text('duration', null, [
'class' => 'form-control' . ($errors->has('duration')?' is-invalid':''),
'id' => 'name',
'placeholder' => 'Enter examination duration (number only)'
]) !!}
<div class="invalid-feedback">{{ $errors->first('duration') }}</div>
</div>
hubungan dua table dimana satu record pada sebuah model dapat
memiliki satu atau lebih record pada model lainnya. Pada desain
Pustarel, satu record users dapat memiliki satu atau lebih record
examinations.
},
},
App\Question {#2991
id: 2,
text: "Cumque id voluptatem consequatur quasi qui aliquid ratione magni
?",
a: "Tempora nulla explicabo consequuntur.",
b: "Reprehenderit laboriosam magnam.",
c: "Facilis animi itaque totam.",
d: "Rerum quia et.",
e: "Velit dicta dignissimos animi.",
answer: "b",
created_at: "2018-12-01 22:43:21",
updated_at: "2018-12-01 22:43:21",
pivot: Illuminate\Database\Eloquent\Relations\Pivot {#2988
examination_id: 1,
question_id: 2,
created_at: "2019-01-01 00:00:00",
updated_at: "2019-01-01 00:00:00",
},
},
...
...
public function attachQuestion(AttachExaminationQuestionRequest $request,
Examination $examination)
{
$question = Question::find($request->input('question_id'));
$examination->questions()->attach($question);
return redirect()
->route('examinations.questions.index', ['id' => $examination->id])
->with('flash_notification', [
'level' => 'success',
'message' => sprintf('Berhasil memasang Question (ID:%u) '
. 'pada Examination (ID:%u)', $question->id, $examination->id)
]);
}
return redirect()
->route('examinations.questions.index', ['id' => $examination->id])
->with('flash_notification', [
'level' => 'warning',
'message' => sprintf('Berhasil melepas Question (ID:%u) '
. 'dari Examination (ID:%u)', $question->id, $examination->id)
]);
}
...
Penjelasan kode:
...
public function rules()
{
return [];
}
public function rules()
{
// $this->examination == $this->route('examination')
return [
'question_id' => [
'required',
Rule::unique('examination_question')->where(function ($query){
$query->where('examination_id', $this->route('examination')->id);
})
],
];
}
...
{
return false;
}
public function authorize()
{
return true;
}
...
public function rules()
{
return [];
}
public function rules()
{
// $this->examination == $this->route('examination')
return [
'question_id' => [
'required',
Rule::exists('examination_question')->where(function ($query){
$query->where('examination_id', $this->route('examination')->id);
})
]
];
}
...
Penjelasan kode:
</div>
</div>
</div>
</div>
@endsection
permission.
2. Instalasi laravel-permission
Selain menyediakan layanan autentikasi (Authentication) secara
out of the box, Laravel juga menyediakan cara sederhana untuk
mengotorisasi (Authorization) tindakan pengguna terhadap
resource yang dilayani. Seperti halnya autentikasi, pendekatan
--provider="Spatie\Permission\PermissionServiceProvider" ⏎
--tag="migrations"
use Illuminate\Database\Seeder;
use Spatie\Permission\Models\Role;
use Spatie\Permission\Models\Permission;
$role->givePermissionTo([
'browse examinations',
'create examinations',
'edit examinations',
'delete examinations',
]);
$role->givePermissionTo('browse results');
Maka seeder akan mengisi table permissions dan roles sesuai yang
disebutkan di atas.
},
},
],
},
}
...
Route::resource('questions', 'QuestionController')->except(['show']);
Route::get('questions/export/excel', 'QuestionController@excel');
Route::get('questions/export/pdf', 'QuestionController@pdf');
Route::resource('examinations', 'ExaminationController')->except(['show']);
Route::post('examinations/{examination}/questions',
'ExaminationController@attachQuestion')
->name('examinations.questions.attach');
Route::delete('examinations/{examination}/questions',
'ExaminationController@detachQuestion')
->name('examinations.questions.detach');
});
Penjelasan kode:
Gambar 37 Student tidak memiliki role untuk dapat mengakses halaman questions
...
<ul class="navbar-nav mr-auto">
</ul>
@role('lecturer')
<li class="nav-item">
<a class="nav-link" href="{{ route('questions.index') }}">{{ __('Question')
}}</a>
</li>
<li class="nav-item">
<a class="nav-link" href="{{ route('examinations.index') }}">{{
__('Examination') }}</a>
</li>
@endrole
@role('student')
<li class="nav-item">
<a class="nav-link" href="">{{ __('Take Examination') }}</a>
</li>
@endrole
@can('browse results')
<li class="nav-item">
<a class="nav-link" href="">{{ __('Browse Results') }}</a>
</li>
@endcan
@endauth
</ul>
...
Penjelasan kode: