0% menganggap dokumen ini bermanfaat (0 suara)
121 tayangan62 halaman

Yii2 Hidayat 365

Dokumen tersebut membahas tentang migrasi database di Yii untuk melacak perubahan struktur database, melakukan upgrade atau downgrade struktur database. Dokumen tersebut juga menjelaskan cara menggunakan fitur migrasi di Yii untuk membuat migrasi pada 4 tabel (items, transaction_types, transactions, transaction_details) beserta hubungan antar tabelnya."

Diunggah oleh

Mas Harjo
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
0% menganggap dokumen ini bermanfaat (0 suara)
121 tayangan62 halaman

Yii2 Hidayat 365

Dokumen tersebut membahas tentang migrasi database di Yii untuk melacak perubahan struktur database, melakukan upgrade atau downgrade struktur database. Dokumen tersebut juga menjelaskan cara menggunakan fitur migrasi di Yii untuk membuat migrasi pada 4 tabel (items, transaction_types, transactions, transaction_details) beserta hubungan antar tabelnya."

Diunggah oleh

Mas Harjo
Hak Cipta
© © All Rights Reserved
Kami menangani hak cipta konten dengan serius. Jika Anda merasa konten ini milik Anda, ajukan klaim di sini.
Format Tersedia
Unduh sebagai DOCX, PDF, TXT atau baca online di Scribd
Anda di halaman 1/ 62

Migrasi Database (Database Migration)

Selama proses pengembangan aplikasi database, struktur database yang digunakan juga ikut berubah dan
berkembang seperti halnya kode sumber (source code) aplikasi kita. Misalnya, membuat tabel baru,
menambahkan kolom baru, menambahkan indeks untuk meningkatkan kinerja query, dan sebagainya. Karena
perubahan struktur database sering membutuhkan beberapa perubahan kode sumber, Yii menyediakan fitur
migrasi database yang memungkinkan Anda untuk melacak perubahan database, melakukan upgrade struktur
database, atau downgrade struktur database jika diperlukan. Referensi lengkap tentang migrasi database di Yii
bisa dilihat di laman ini.

Untuk memulai menggunakan fitur migration di Yii, pastikan kita sudah membuat forlder migrations di
dalam folder framework yii kita. Sesuai dengan desain database yang sudah kita buat sebelumnya, maka kita
perlu membuat migrasi untuk 4 (empat) buat tabel, yaitu items, transaction_types, transactions,
dan transaction_details.

Jalankan perintah berikut untuk membuat migrasi table items.

yii migrate/create create_table_items

Yii kemudian akan menanyakan apakah kita benar akan membuat migrasi, jawablah dengan yes.

Setelah itu, buka folder migrations maka kamu akan melihat sebuah file yang di-generate oleh Yii. Bukalah
dan isikan kode untuk membuat tabel items, seperti kode sumber di bawah ini.

public function up()

$this->createTable('items', [

'id' => Schema::TYPE_PK,

'code' => Schema::TYPE_STRING . ' NOT NULL',

'name' => Schema::TYPE_STRING . ' NOT NULL',


'quantity' => Schema::TYPE_INTEGER . ' DEFAULT 0',

'remarks' => Schema::TYPE_STRING,

]);

public function down()

$this->dropTable('items');

Berikutnya kita buatkan migrasi untuk tabel transaction_types dengan menjalankan perintah ini

yii migrate/create create_table_transaction_types

Kemudian tambahkan kode berikut ini untuk membuat tabel transaction_types. Karena kita
menggunakan tabel transaction_types ini untuk membedakan transaksi barang masuk dan transaksi barang
keluar, maka kita juga harus menambahkan beberapa record ke tabel ini.

public function up()

$this->createTable('transaction_types', [

'id' => Schema::TYPE_PK,

'code' => Schema::TYPE_STRING . ' NOT NULL',

'name' => Schema::TYPE_STRING . ' NOT NULL',


]);

// default data

$this->insert('transaction_types', [

'id' => 1,

'code' => 'IN',

'name' => 'Barang Masuk',

]);

$this->insert('transaction_types', [

'id' => 2,

'code' => 'OUT',

'name' => 'Barang Keluar',

]);

public function down()

$this->dropTable('transaction_types');

Berikutnya kita buatkan migrasi untuk tabel transactions dengan menjalankan perintah ini

yii migrate/create create_table_transactions


Kemudian tambahkan kode berikut ini. Karena tabel transactions ini memiliki relasi dengan tabel
transaction_types, maka kita juga perlu menambahkan kode untuk men-generate relasi foreign key
seperti tampak pada kode di bawah ini.

public function up()

$this->createTable('transactions', [

'id' => Schema::TYPE_PK,

'trans_code' => Schema::TYPE_STRING . ' NOT NULL',

'trans_date' => Schema::TYPE_DATE . ' NOT NULL DEFAULT 0',

'type_id' => Schema::TYPE_INTEGER . ' NOT NULL',

'remarks' => Schema::TYPE_STRING,

]);

// foreign keys

$this->addForeignKey(

'fk_transactions_types',

'transactions', 'type_id',

'transaction_types', 'id',

'restrict', 'cascade');

public function down()

{
$this->dropTable('transactions');

Berikutnya kita buatkan migrasi untuk tabel transaction_details dengan menjalankan perintah ini

yii migrate/create create_table_transaction_details

Kemudian tambahkan kode berikut ini. Karena kita transaction_details ini memiliki relasi dengan
tabel transactions dan tabel items maka kita juga perlu menambahkan kode untuk men-
generate relasi foreign key seperti tampak pada kode di bawah ini.

public function up()

$this->createTable('transaction_details', [

'id' => Schema::TYPE_PK,

'trans_id' => Schema::TYPE_INTEGER . ' NOT NULL',

'item_id' => Schema::TYPE_INTEGER,

'quantity' => Schema::TYPE_DECIMAL . '(15,2) NOT NULL DEFAULT 0',

'remarks' => Schema::TYPE_STRING,

]);

// foreign keys

$this->addForeignKey(

'fk_transaction_details_transactions',
'transaction_details', 'trans_id',

'transactions', 'id',

'restrict', 'cascade');

$this->addForeignKey(

'fk_transaction_details_items',

'transaction_details', 'item_id',

'items', 'id',

'restrict', 'cascade');

public function down()

$this->dropTable('transaction_details');

Jangan lupa ditambahkan baris berikut ini di setaip file migration, karena kita menggunakan class Schema
untuk mendefinisikan tipe data field.

use yii\db\Schema;

Setelah semua migrasi kita siapkan, maka yang perlu kita lakukan adalah mengeksekusi migrasi tersebut.
Caranya sangat mudah cukup dengan menjalankan perintah

yii migrate

Contoh hasil eksekusinya tampak pada screenshot di bawah ini.


Kode sumber (source code) bisa dilihat di laman ini.

Generate Models Menggunakan Gii


Yii menyediakan extension Gii untuk memudahkan kita men-generate code untuk models, forms, CRUD,
modules dan sebagainya. Gii bisa diakses melalui URL

http://localhost/path/to/index.php?r=gii

Atau jika kamu sudah menggunakan fitur pretty URL, maka Gii dapat diakses di

http://localhost/path/to/index.php/gii
Berikutnya silakan buka Model Generator agar kita bisa men-generate models untuk database kita. Seperti
tampak pada screenshot di bawah ini.

Show Generate Models

Isikan Table Name dengan nama table yang ingin kita generate code models-nya dan biarkan Model Class di-
generate secara otomatis oleh Gii. Biarkan semua opsi lainnya sesuai default-nya saja. Perhatikan field
namespace terisi dengan app\models maka nanti Fully Qualified Class Name dari models yang kita buat
menjadi app\models\Items. Fully Qualified Class Name ini perlu kita ingat karena akan berguna pada
saat kita men-generate form CRUD.

Selanjutnya tekan tombol [Preview] agar Gii membuat preview hasil code generation-nya, seperti tampak pada
screenshot di bawah ini.

Show Generate Models

Karena ini sifatnya hanya preview, tujuannya adalah agar Gii tidak sampai menimpa file yang mungkin
sudah kita ubah sebelumnya. Jika action yang tampil adalah create maka langsung saja tekan tombol
[Generate] agar Gii benar-benar men-generate file yang kita inginkan.

Show Generate Models


Lakukanlah hal yang sama untuk semua table di aplikasi ini, sehingga semua table yang ada di database
tersedia file model-nya

Selamat mencoba.....!
Generate CRUD Menggunakan Gii
Yii menyediakan extension Gii untuk memudahkan kita men-generate code untuk models, forms, CRUD,
modules dan sebagainya. Keberadaan extension ini sangat membantu para programmer untuk mempercepat
proses pengembangan aplikasi, karena template untuk CRUD sudah dibuatkan sehingga kita cukup
memodifikasi sesuai keperluan saja. Gii bisa diakses melalui URL

http://localhost/path/to/index.php?r=gii

Atau jika kamu sudah menggunakan fitur pretty URL, maka Gii dapat diakses di

http://localhost/path/to/index.php/gii

Berikutnya yang perlu kita lakukan adalah men-generate form CRUD untuk master barang dengan base
table items. Pilihlah option CRUD Generator yang disediakan oleh Gii, dan kemudian isikan form di bawah
seperti tampak pada screenshot di bawah ini.

ShowGenerate CRUD
Yang perlu diperhatikan pada saat mengisi form CRUD Generator ini antara lain

 Perhatikan bahwa separator untuk namespace dan class menggunakan tanda garis miring terbalik (backslash)
sedangkan separator folder untuk Views Path menggunakan garis miring biasa (slash) karena textbox Views
Path berisikan folder lokasi views akan disimpan.
 Nama Model Class harus lengkap, meliputi namespace dan nama class model bersangkutan, dalam hal ini
adalah app\models\Items. Untuk mengetahui namespace dan nama class caranya cukup dengan
membuka file code model bersangkutan saja, di file tersebut sudah tersedia namespace dan nama class-nya.
 Nama model untuk Search Model Class cukup kita salin saja dari Model Class dan kemudian kita tambahkan
"Search" dibelakangnya. Dalam hal ini adalah app\models\ItemsSearch.
o Nama Controller Class kita ikuti konvensi yang digunakan oleh Yii2 yaitu menggunakan akhiran "Controller"
di akhir nama class. Namespace yang dipakai adalah app\controllers, sehingga field ini kita isikan
dengan app\controllers\ItemController. Perhatikan bahwa kita hanya menggunakan Item saja
tanpa akhiran plural "s"
 Kemudian isikan Views Path dengan @app/views/item karena kita ingin menyimpan berkas-berkas views
ini di dalam folder views/item. Perhatikan bahwa kita menggunakan garis miring biasa (slash) untuk
memisahkan nama folder.
 Silakan beri centang pada option "Enable l18n" dan "Enable Pjax" jika diinginkan.
 Biarkan field lainnya sesuai default.

Langkan selanjutnya adalah menekan tombol Preview agar kita bisa memastikan tidak menimpa berkas coding
yang sudah kita buat sebelumnya jika ada. Hasil preview tampak seperti screenshot di bawah ini.

ShowGenerate CRUD
Kemudian tekan tombol generate untuk memastikan Gii membuat kita memastikan semuanya sesuai
keinginkan kita.
Modifikasi List Master Barang
Karena kita tidak perlu menampilkan fiel ID dalam List Barang, maka kita hapus saja field ID dari setting
GridView , menjadi tampak seperti code di bawah ini

<?= GridView::widget([
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'yii\grid\SerialColumn'],

'code',
'name',
'quantity',
'remarks',

['class' => 'yii\grid\ActionColumn'],


],
]); ?>

ShowPenampakan
Modifikasi Form Master Barang
Yii sudah menyediakan validasi terhadap input yang kita berikan ke form ini. Validasi tersebut ada di dalam
codeModel yang memastikan bahwa - misalkan - field Quantity harus diisikan dengan angka integer. Namun
kita akan tambahkan sebuah link yang akan mengarahkan pengguna ke List Master Barang sebagai antisipasi
jika kita memilih untuk membatalkan proses input data. Code yang kita tambahkan adalah,

<?= Html::a(Yii::t('app', 'Back to List'), ['index'], ['class' => 'btn btn-warning']) ?>

Menjadi seperti tampak pada source code di bawah ini.

<?php $form = ActiveForm::begin(); ?>

<?= $form->field($model, 'code')->textInput(['maxlength' => true]) ?>


<?= $form->field($model, 'name')->textInput(['maxlength' => true]) ?>
<?= $form->field($model, 'quantity')->textInput() ?>
<?= $form->field($model, 'remarks')->textInput(['maxlength' => true]) ?>

<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app', 'Update'),
['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
<?= Html::a(Yii::t('app', 'Back to List'), ['index'], ['class' => 'btn btn-warning']) ?>
</div>

<?php ActiveForm::end(); ?>

ShowPenampakan
Modifikasi View Master Barang
Pada source code hasil auto-generate, Yii masih menapilkan field ID yang sebenarnya tidak kita perlukan,
maka kita hapus saja dari code. Berikutnya kita tambahkan sebuah link yang akan mengarahkan pengguna ke
List Master Barang memudahkan pengguna kembali ke halaman List Barang. Code yang kita tambahkan
adalah,

?
<?= Html::a(Yii::t('app', 'Back to List'), ['index'], ['class' => 'btn btn-warning']) ?>

Menjadi seperti tampak pada source code di bawah ini.

<p>
<?= Html::a(Yii::t('app', 'Update'), ['update', 'id' => $model->id], ['class' => 'btn btn-primary'])
?>
<?= Html::a(Yii::t('app', 'Delete'), ['delete', 'id' => $model->id], [
'class' => 'btn btn-danger',
'data' => [
'confirm' => Yii::t('app', 'Are you sure you want to delete this item?'),
'method' => 'post',
],
]) ?>
<?= Html::a(Yii::t('app', 'Back to List'), ['index'], ['class' => 'btn btn-warning']) ?>
</p>

<?= DetailView::widget([
'model' => $model,
'attributes' => [
'code',
'name',
'quantity',
'remarks',
],
]) ?>

ShowPenampakan
Penutup
Demikianlah tutrial untuk membuat Master Barang dalam Aplikasi Inventory ini. Semoga berguna!
Aplikasi Persediaan Barang (Sistem Inventory) Menggunakan Yii2 - Part #4

Posted By: nurhidayat

Top of Form

Code Factory | Sistem Inventory atau Aplikasi Persediaan Barang adalah salah satu aplikasi yang umum
dan cukup menantang terutama bagi para programmer pemula yang sedang mengasah
skill programming-nya. Artikel ini merupakan lanjutan dari artikel ketiga yang membahas Pembuatan
Form Master Barang. Artikel ini akan melanjutkan pembuatan form transaksi dengan desain master-
detail menggunakan bantun extension dynamic-form, dan kita buat sederhana saja sehingga akan cukup
mudah dipahami para programmer pemula.

Extension Tambahan

Untuk memudahkan kita membangun user interface yang cukup nyaman maka kita memerlukan dua
buah extension tambahan, yaitu datepicker untuk memilih tanggal, dan dynamic-form untuk form CRUD
master-detail. Gunakan perintah composer berikut ini untuk instalasi-nya.

1 composer require kartik-v/yii2-widget-datepicker "*"

2 composer require wbraganca/yii2-dynamicform "*"

HideInstalasi Extension
Generate CRUD Menggunakan Gii

Silakan generate CRUD untuk Table Transactions dan TransactionDetails dengan cara yang sama seperti
saat membuat form master barang.

HideGenerate CRUD Transactions


HideGenerate CRUD TransactionDetails
Modifikasi List Transaksi Barang

Hasil generate CRUD dari Yii sangat membantu kita mempercepat proses pengerjaan aplikasi ini, namun
masih perlu beberapa penyesuaian dari code standard Gii yang dihasilkan,

?
1 'columns' => [

2 ['class' => 'yii\grid\SerialColumn'],

3 'id',

4 'trans_code',

5 'trans_date',

6 'type_id',

7 'remarks',

8 ['class' => 'yii\grid\ActionColumn'],

9 ],

Kita dapat menghapus field id yang hanya field identity sehingga tidak penting untuk ditampilkan. Kita
juga dapat mengubah field type_id menjadi type.name agar data yang ditampilkan adalah nama jenis
transaksinya dan bukan angka id-nya sehingga hasilnya menjadi seperti di bawah ini

1 'columns' => [

2 ['class' => 'yii\grid\SerialColumn'],

3 'trans_code',

4 'trans_date',

5 'type.name',

6 'remarks',

7 ['class' => 'yii\grid\ActionColumn'],

8 ],

HideGridView Transaksi
Hasilnya cukup user-friendly. Namun sayangnya dengan cara di atas, kita tidak bisa melakukan filter
terhadap jenis transaksi. Oleh karena itu kita perlu melakukan perubahan agar filter terhadap jenis
transaksi barang kita kita lakukan, filter menggunakan dropdown list. Pertama yang kita lakukan adalah
mengambil data semua jenis transaksi yang ada di dalam database menggunakan code berikut,

1 $typeList = ArrayHelper::map(TransactionTypes::find()->asArray()->all(), 'id', 'name');

Kemudian ubah setting column type.name di GridView dengan menambahkan atribut setting filter dan
value barupa Closure yang bentuknya spesifik untuk GridView, sehingga menjadi seperti di bawah ini

?
1 'columns' => [

2 ['class' => 'yii\grid\SerialColumn'],

3 'trans_code',

4 'trans_date',

5 [ 'attribute' => 'type_id',

6 'filter' => $typeList,

7 'label' => 'Transaction Type',

8 'value' => function ($model, $index, $widget) { return $model->type->name; }

9 ],

10 'remarks',

11 ['class' => 'yii\grid\ActionColumn'],

12 ],

HideGridView Transaksi dengan Filter Dropdown


Modifikasi Form Transaksi Barang

Form input transaksi barang melibatkan dua buah table yaitu transactions dan transaction_details
sehingga kita memerlukan extension dynamic-form untuk membuatnya. Instalasi dengan menggunakan
perintah composer di bawah ini.

1 composer require wbraganca/yii2-dynamicform "*"

Yang perlu kita lakukan kemudian adalah

Membuat class Model untuk memudahkan kita membuat beberapa row TransactionDetails dalam satu
baris code saja.
Modifikasi ActionCreate di TransactionController untuk proses pembuatan transaksi baru

Modifikasi ActionUpdate di TransactionController untuk proses pembuatan transaksi yang sudah ada di
database

Modifikasi ActionDelete di TransactionController untuk proses penghapusan transaksi

Modifikasi form untuk Create dan Update.

Class Model

Class Model ini merupakan turunan dari class yii\base\Model namun kita menambahkan sebuah
function createMultiple untuk memudahkan kita membuat beberapa
row TransactionDetails berdasarkan isi dari variable POST menggunakan satu baris code saja.

HideClass Model

1 namespace app\models;

3 use Yii;

4 use yii\helpers\ArrayHelper;

6 class Model extends \yii\base\Model

7 {

8 /**

9 * Creates and populates a set of models.

10 * @param string $modelClass

11 * @param array $multipleModels

12 * @return array

13 */

14 public static function createMultiple($modelClass, $multipleModels = [])


15 {

16 $model = new $modelClass;

17 $formName = $model->formName();

18 $post = Yii::$app->request->post($formName);

19 $models = [];

20

21 if (! empty($multipleModels)) {

22 $keys = array_keys(ArrayHelper::map($multipleModels, 'id', 'id'));

23 $multipleModels = array_combine($keys, $multipleModels);

24 }

25

26 if ($post && is_array($post)) {

27 foreach ($post as $i => $item) {

28 if (isset($item['id']) && !empty($item['id']) && isset($multipleModels[$item['id']])) {

29 $models[] = $multipleModels[$item['id']];

30 } else {

31 $models[] = new $modelClass;

32 }

33 }

34 }

35

36 unset($model, $formName, $post);

37 return $models;

38 }
39 }

Modifikasi ActionCreate

Saat melakukan proses penyimpanan data transaksi baru ke database, kita mengikuti algoritma berikut
ini,

Load master record

Load semua detail records

Assign foreign key field di detail records

Validate master record

Validate detail record

Jika validasi berhasil

Mulai transaksi database

Simpan master record

Simpan detail record satu-persatu

Jika berhasil semua, commit

Jika gagal rollback

Tampilkan hasilnya

HideActionCreate

1 /**

2 * Creates a new Transactions model.

3 * If creation is successful, the browser will be redirected to the 'view' page.

4 * @return mixed

5 */

6 public function actionCreate()


7 {

8 $model = new Transactions();

9 $details = [ new TransactionDetails ];

10

11 // proses isi post variable

12 if ($model->load(Yii::$app->request->post())) {

13 $details = Model::createMultiple(TransactionDetails::classname());

14 Model::loadMultiple($details, Yii::$app->request->post());

15

16 // assign default transaction_id

17 foreach ($details as $detail) {

18 $detail->trans_id = 0;

19 }

20

21 // ajax validation

22 if (Yii::$app->request->isAjax) {

23 Yii::$app->response->format = Response::FORMAT_JSON;

24 return ArrayHelper::merge(

25 ActiveForm::validateMultiple($details),

26 ActiveForm::validate($model)

27 );

28 }

29

30 // validate all models


31 $valid1 = $model->validate();

32 $valid2 = Model::validateMultiple($details);

33 $valid = $valid1 && $valid2;

34

35 // jika valid, mulai proses penyimpanan

36 if ($valid) {

37 // mulai database transaction

38 $transaction = \Yii::$app->db->beginTransaction();

39 try {

40 // simpan master record

41 if ($flag = $model->save(false)) {

42 // kemudian simpan detail records

43 foreach ($details as $detail) {

44 $detail->trans_id = $model->id;

45 if (! ($flag = $detail->save(false))) {

46 $transaction->rollBack();

47 break;

48 }

49 }

50 }

51 if ($flag) {

52 // sukses, commit database transaction

53 // kemudian tampilkan hasilnya

54 $transaction->commit();
55 return $this->redirect(['view', 'id' => $model->id]);

56 } else {

57 return $this->render('create', [

58 'model' => $model,

59 'details' => $details,

60 ]);

61 }

62 } catch (Exception $e) {

63 // penyimpanan galga, rollback database transaction

64 $transaction->rollBack();

65 throw $e;

66 }

67 } else {

68 return $this->render('create', [

69 'model' => $model,

70 'details' => $details,

71 'error' => 'valid1: '.print_r($valid1,true).' - valid2: '.print_r($valid2,true),

72 ]);

73 }

74

75 } else {

76 // inisialisai id

77 // diperlukan untuk form master-detail

78 $model->id = 0;
79 // render view

80 return $this->render('create', [

81 'model' => $model,

82 'details' => $details,

83 ]);

84 }

85 }

Modifikasi ActionUpdate

Saat melakukan proses penyimpanan perubahan data transaksi ke database. Agak sedikit berbeda
dengan proses pyimpanan transaksi baru, untuk proses edit, kita menghapus semua detail record yang
sudah ada sebelumnya di database dan kemudian melakukan insert ulang sebagai record baru.
Algoritma-nya adalah seperti berikut ini,

Load master record

Load semua detail records

Assign foreign key field di detail records

Validate master record

Validate detail record

Jika validasi berhasil

Mulai transaksi database

Simpan master record

Delete semua detail record yang sudah ada di database

Simpan detail record satu-persatu

Jika berhasil semua, commit

Jika gagal rollback

Tampilkan hasilnya

HideActionUpdate
?

1 /**

2 * Updates an existing Transactions model.

3 * If update is successful, the browser will be redirected to the 'view' page.

4 * @param integer $id

5 * @return mixed

6 */

7 public function actionUpdate($id)

8 {

9 $model = $this->findModel($id);

10 $details = $model->transactionDetails;

11

12 if ($model->load(Yii::$app->request->post())) {

13

14 $oldIDs = ArrayHelper::map($details, 'id', 'id');

15 $details = Model::createMultiple(TransactionDetails::classname(), $details);

16 Model::loadMultiple($details, Yii::$app->request->post());

17 $deletedIDs = array_diff($oldIDs, array_filter(ArrayHelper::map($details, 'id', 'id')));

18

19 // assign default transaction_id

20 foreach ($details as $detail) {

21 $detail->trans_id = $model->id;

22 }

23
24 // ajax validation

25 if (Yii::$app->request->isAjax) {

26 Yii::$app->response->format = Response::FORMAT_JSON;

27 return ArrayHelper::merge(

28 ActiveForm::validateMultiple($details),

29 ActiveForm::validate($model)

30 );

31 }

32

33 // validate all models

34 $valid1 = $model->validate();

35 $valid2 = Model::validateMultiple($details);

36 $valid = $valid1 && $valid2;

37

38 // jika valid, mulai proses penyimpanan

39 if ($valid) {

40 // mulai database transaction

41 $transaction = \Yii::$app->db->beginTransaction();

42 try {

43 // simpan master record

44 if ($flag = $model->save(false)) {

45 // delete dahulu semua record yang ada

46 if (! empty($deletedIDs)) {

47 TransactionDetails::deleteAll(['id' => $deletedIDs]);


48 }

49 // kemudian, simpan details record

50 foreach ($details as $detail) {

51 $detail->trans_id = $model->id;

52 if (! ($flag = $detail->save(false))) {

53 $transaction->rollBack();

54 break;

55 }

56 }

57 }

58 if ($flag) {

59 // sukses, commit database transaction

60 // kemudian tampilkan hasilnya

61 $transaction->commit();

62 return $this->redirect(['view', 'id' => $model->id]);

63 }

64 } catch (Exception $e) {

65 // penyimpanan galga, rollback database transaction

66 $transaction->rollBack();

67 throw $e;

68 }

69 } else {

70 return $this->render('create', [

71 'model' => $model,


72 'details' => $details,

73 'error' => 'valid1: '.print_r($valid1,true).' - valid2: '.print_r($valid2,true),

74 ]);

75 }

76 }

77

78 // render view

79 return $this->render('update', [

80 'model' => $model,

81 'details' => (empty($details)) ? [new TransactionDetails] : $details

82 ]);

83 }

Modifikasi ActionDelete

Pada saat menghapus data transaksi maka yang perlu kita lakukan adalah terlebih dahulu menghapus
detail record sebelum menghapus master/parent record. Algoritma-nya adalah sebagai berikut

Mulai transaksi database

Delete semua detail record satu-persatu

Delete master record

Jika berhasil semua, commit

Jika gagal rollback

Tampilkan index transaksi barang

HideActionDelete

1 /**
2 * Deletes an existing Transactions model.

3 * If deletion is successful, the browser will be redirected to the 'index' page.

4 * @param integer $id

5 * @return mixed

6 */

7 public function actionDelete($id)

8 {

9 $model = $this->findModel($id);

10 $details = $model->transactionDetails;

11

12 // mulai database transaction

13 $transaction = \Yii::$app->db->beginTransaction();

14 try {

15 // pertama, delete semua detail records

16 foreach ($details as $detail) {

17 $detail->delete();

18 }

19 // kemudian, delete master record

20 $model->delete();

21 // sukses, commit transaction

22 $transaction->commit();

23

24 } catch (Exception $e) {

25 // gagal, rollback database transaction


26 $transaction->rollBack();

27 }

28

29 return $this->redirect(['index']);

30 }

Modifikasi create.php

Kita perlu menambahkan variable $details agar dapat dikenali di dalam _form.php

1 <?= $this->render('_form', [

2 'model' => $model,

3 'details' => $details,

4 ]) ?>

Modifikasi update.php

Kita juga perlu menambahkan variable $details agar dapat dikenali di dalam _form.php

1 <?= $this->render('_form', [

2 'model' => $model,

3 'details' => $details,

4 ]) ?>

Modifikasi _form.php

Code lengkapnya adalah seperti berikut ini

HideCode HTML form transaksi

?
<div class="transactions-form">
1

2
<?php $form = ActiveForm::begin(['id' => 'transactions-form']); ?>
3

4
<div class="row">
5
<div class="col-sm-4 col-md-6">
6
<?= $form->field($model, 'trans_code')->textInput(['maxlength' => true]) ?>
7
</div>
8
<div class="col-sm-4 col-md-3">
9
<?php
10
echo '<label class="control-label" for="transactions-trans_date">Transaction
11
Date</label>';
12
echo DatePicker::widget([
13
'id' => 'transactions-trans_date',
14
'name' => 'Transactions[trans_date]',
15
'type' => DatePicker::TYPE_COMPONENT_APPEND,
16
'value' => date('Y-m-d'),
17
'pluginOptions' => [
18
'autoclose'=>true,
19
'format' => 'yyyy-mm-dd'
20
]
21
]);
22
?>
23
</div>
24
<div class="col-sm-4 col-md-3">
25 <?= $form->field($model, 'type_id')->dropDownList(

26 ArrayHelper::map(TransactionTypes::find()->all(), 'id', 'name'),

27 ['prompt'=>'* Pilih Transaksis *']

28 ); ?>

29 </div>

30 <div class="col-sm-12 col-md-12">

31 <?= $form->field($model, 'remarks')->textInput(['maxlength' => true]) ?>

32 </div>

33 </div><!-- .row -->

34

35 <div class="panel panel-default">

36 <div class="panel-heading"><h4><i class="glyphicon glyphicon-th-list"></i> Transaction


Details</h4></div>
37
<div class="panel-body">
38
<?php DynamicFormWidget::begin([
39
'widgetContainer' => 'dynamicform_wrapper', // required: only alphanumeric
40 characters plus "_" [A-Za-z0-9_]
41 'widgetBody' => '.container-items', // required: css class selector
42 'widgetItem' => '.item', // required: css class
43 'limit' => 999, // the maximum times, an element can be cloned
44 (default 999)

45 'min' => 1, // 0 or 1 (default 1)

46 'insertButton' => '.add-item', // css class

47 'deleteButton' => '.remove-item', // css class

48 'model' => $details[0],


49 'formId' => 'transactions-form',

50 'formFields' => [

51 'trans_id',

52 'item_id',

53 'quantity',

54 'remarks',

55 ],

56 ]); ?>

57

58 <div class="container-items"><!-- widgetContainer -->

59 <?php foreach ($details as $i => $detail): ?>

60 <div class="item row">

61 <?php

62 // necessary for update action.

63 if (! $detail->isNewRecord) {

64 echo Html::activeHiddenInput($detail, "[{$i}]id");

65 }

66 ?>

67 <div class="col-sm-8 col-md-4">

68 <?= $form->field($detail, "[{$i}]item_id")->dropDownList(

69 ArrayHelper::map(Items::find()->all(), 'id', 'name'), // Flat array ('id'=>'label')

70 ['prompt'=>'* Pilih Barang *'] // options

71 ); ?>

72 </div>
73 <div class="col-sm-4 col-md-2">

74 <?= $form->field($detail, "[{$i}]quantity")->textInput(['maxlength' => true]) ?>

75 </div>

76 <div class="col-sm-10 col-md-5">

77 <?= $form->field($detail, "[{$i}]remarks")->textInput(['maxlength' => true]) ?>

78 </div>

79 <div class="col-sm-2 col-md-1 item-action">

80 <div class="pull-right">

81 <button type="button" class="add-item btn btn-success btn-xs">

82 <i class="glyphicon glyphicon-plus"></i></button>

83 <button type="button" class="remove-item btn btn-danger btn-xs">

84 <i class="glyphicon glyphicon-minus"></i></button>

85 </div>

86 </div>

87 </div><!-- .row -->

88

89 <?php endforeach; ?>

90 </div>

91

92 <?php DynamicFormWidget::end(); ?>

93 </div>

94 </div>

95

96
97 <div class="form-group">

98 <?= Html::submitButton($model->isNewRecord ? Yii::t('app', 'Create') : Yii::t('app',


'Update'), ['class' => $model->isNewRecord ? 'btn btn-success' : 'btn btn-primary']) ?>
99
</div>
100

101
<?php ActiveForm::end(); ?>

</div>

ShowForm Transaksi Barang


Membuat View Transaksi Barang

Untuk menampilkan data master-detail, maka kita harus record master dan semua record detail yang
berelasi, sehingga kita perlu mengubah ActionView menjadi seperti ini

HideCode ActionView
?

1 /**

2 * Displays a single Transactions model.

3 * @param integer $id

4 * @return mixed

5 */

6 public function actionView($id)

7 {

8 return $this->render('view', [

9 'model' => $this->findModel($id),

10 'details' => $this->findDetails($id),

11 ]);

12 }

13

14 /**

15 * Finds the Transactions model based on its primary key value.

16 * If the model is not found, a 404 HTTP exception will be thrown.

17 * @param integer $id

18 * @return Transactions the loaded model

19 * @throws NotFoundHttpException if the model cannot be found

20 */

21 protected function findModel($id)

22 {

23 if (($model = Transactions::findOne($id)) !== null) {


24 return $model;

25 } else {

26 throw new NotFoundHttpException('The requested page does not exist.');

27 }

28 }

29

30 /**

31 * Finds the TransactionDetails model based on its foreign key value.

32 * @param integer $id

33 * @return data provider TransactionDetails for GridView

34 */

35 protected function findDetails($id)

36 {

37 $detailModel = new TransactionDetailsSearch();

38 return $detailModel->search(['TransactionDetailsSearch'=>['trans_id'=>$id]]);

39 }

Dan jangan lupa mengubah view.php agar menampilkan data yang didapat dari controller. Kita akan
menggunakan DetailView untuk master row, dan menggunakan GridView untuk menampilkan detail
row.

HideHTML Code View Transaksi

1 <?= DetailView::widget([

2 'model' => $model,

3 'attributes' => [
4 'trans_code',

5 [

6 'attribute' => 'trans_date',

7 'format' => [ 'date', 'php: d-M-Y' ],

8 'labelColOptions' => [ 'style'=>'width:30%; text-align:right;' ]

9 ],

10 'type.name',

11 'remarks',

12 ],

13 ]) ?>

14

15 <div class="item panel panel-info">

16 <div class="panel-heading">

17 <h3 class="panel-title pull-left"><i class="glyphicon glyphicon-barcode"></i> Transaction Line


Item</h3>
18
<div class="clearfix"></div>
19
</div>
20
<div class="panel-body">
21
<?= GridView::widget([
22
'dataProvider' => $details,
23
'columns' => [
24
['class' => 'yii\grid\SerialColumn'],
25

26
[
27
'attribute' => 'item_id',
28 'value' => 'item.code',

29 'header' => 'Item Code',

30 ],

31 [

32 'attribute' => 'item_id',

33 'value' => 'item.name',

34 'header' => 'Item Name',

35 ],

36 'quantity',

37 'remarks',

38 ],

39 ]); ?>

40 </div>

41 </div>

HidePenampakan View Transaksi Barang


Simpulan

Mudah-mudahan tutorial ini dapat membantu teman-teman yang sedang belajar membuat aplikasi
inventory, khususnya yang menggunakan Yii Framework. Source code aplikasi ini dapat dilihat di
GitHub, silakan digunakan untuk keperluan pembelajaran saja.

Bottom of Form
Aplikasi Persediaan Barang (Sistem Inventory)
Menggunakan Yii2 - Part #5
 Posted By: nurhidayat
 Comments: 0

Code Factory | Sistem Inventory atau Aplikasi Persediaan Barang adalah salah satu aplikasi yang umum dan
cukup menantang terutama bagi para programmer pemula yang sedang mengasah skill programming-nya.
Artikel ini merupakan lanjutan dari artikel keempat yang membahas Pembuatan Form Transaksi
Barang dan merupakan bagian terakhir dari serial artikel Aplikasi Persediaan Barang Menggunakan Yii2.
Artikel ini membahas pembuatan laporan kartu stok yang merupakan laporan yang wajib tersedia dalam
sebuah aplikasi inventory, dan kita buat sederhana saja sehingga akan cukup mudah dipahami para
programmer pemula.

Modifikasi ItemController
Kartu Stok pada dasarnya adalah daftar transaksi masing-masing barang, dengan mencantumkan jumlah
masuk, jumlah keluar, dan saldo barang yang tersedia. dengan begitu kita bisa melihat pergerakan dan
perubahan stok dari barang bersangkutan. Untuk mencapai hal ini, kita cukup melakukan join terhadap table
barang (items) dan table transaksi (transactions dan transaction_details) untuk mendapatkan
laporan yang kita inginkan.

Untuk itu kita bisa melakukan query dan memberikan hasil query tersebut ke view agar dapat ditampilkan
dalam bentuk GridView. Untuk itu kita lakukan modifikasi terhadap fungsi actionView yang ada di
dalam class ItemController. Dengan mengubah actionView, maka setiap kali kita membuka/melihat detil
informasi barang maka di bawahnya akan terlihat history transaksinya. Perubahannya adalah sebagai berikut,

/**
* Displays a single Items model.
* @param integer $id
* @return mixed
*/
public function actionView($id)
{
// query kartu stok
$sql_list = "
SELECT t.id AS trans_id
, t.trans_code AS trans_code
, t.trans_date AS trans_date
, a.id AS detail_id, a.item_id AS item_id
, trim(concat(t.remarks,' - ',a.remarks)) AS remarks
, b.code AS item_code, b.name AS item_name
, CASE
WHEN t.type_id=1 THEN a.quantity
WHEN t.type_id=2 THEN -a.quantity
ELSE 0 END
AS quantity
, @sal := @sal + CASE
WHEN t.type_id=1 THEN a.quantity
WHEN t.type_id=2 THEN -a.quantity
ELSE 0 END
AS saldo
FROM transactions t
JOIN transaction_details a ON t.id = a.trans_id
JOIN items b ON a.item_id = b.id
JOIN ( SELECT @sal:=0 ) v
WHERE b.id = :id
ORDER BY t.trans_date, t.id, a.id
";
// query total data di kartu stok
$sql_count = "
SELECT count(*)
FROM transactions t
JOIN transaction_details a ON t.id = a.trans_id
JOIN items b ON a.item_id = b.id
ORDER BY t.trans_date, t.id, a.id;
";
// count data
$count = Yii::$app->db->createCommand($sql_count, [':id' => $id])->queryScalar();
// data provider untuk ditampilkan di view
$dataProvider = new SqlDataProvider([
'sql' => $sql_list,
'params' => [':id' => $id],
'totalCount' => $count,
'pagination' => [
'pageSize' => 20,
],
]);
// render view
return $this->render('view', [
'model' => $this->findModel($id),
'dataProvider' => $dataProvider,
]);
}

Jika teman-teman perhatikan, dalam query di atas terdapat variable @sal yang kita gunakan untuk men-
generate kolom saldo berdasarkan perhitungan penambahan/pengurangan transaksi barang. Dalam query
tersebut juga terdapat klausa CASE yang berfungsi sebagai logika percabangan untuk membedakan transaksi
barang masuk dan barang keluar, karena barang masuk harus menambah saldo, sedangkan barang keluar harus
mengurangi saldo.

Modifikasi View Barang


Dan untuk menampilkannya, caranya cukup mudah, yaitu langsung saja kita tambahkan code GridView di
bawah DetailView yang sebelumnya sudah ada di dalam file view.php menjadi seperti di bawah ini

<?= DetailView::widget([
'model' => $model,
'attributes' => [
'code',
'name',
'quantity',
'remarks',
],
]) ?>

<h3>Stock Card</h3>
<?= GridView::widget([
'dataProvider' => $dataProvider,
'columns' => [
['class' => 'yii\grid\SerialColumn'],
'trans_code',
'trans_date',
'item_code',
'item_name',
'quantity',
'saldo',
'remarks',
],
]); ?>

Berikut ini salah satu contoh penampakan kartu stok-nya.

Simpulan dan Saran


Sesuai dengan judulnya, aplikasi ini masih sangat sederhana. Banyak ide yang bisa dikembangkan dari aplikasi
ini, misalkan

 Dukungan transaksi multi-warehouse.


 Penambahan laporan-laporan periodik, seperti laporan mutasi stok bulanan, dan sebagainya.
 Integrasi dengan aplikasi Point of Sales.

Dan masih banyak ide-ide lain yang bisa kita kembangkan.

Mudah-mudahan tutorial ini dapat membantu teman-teman yang sedang belajar membuat aplikasi inventory,
khususnya yang menggunakan Yii Framework. Source code aplikasi ini dapat dilihat di GitHub, silakan
digunakan untuk keperluan pembelajaran saja. Jika teman-teman ingin menggunakan source code tersebut
untuk keperluan komersil, diwajibkan untuk mendapatkan izin tertulis dari penulis.

Anda mungkin juga menyukai