Pada tulisan ini saya akan membuat series mengenai pemrograman dengan Yii Framework. Series ini akan disusun untuk membuat sebuah program sederhana yang memanfaatkan fitur-fitur umum yang sangat mungkin digunakan di banyak kasus. Tulisan ini akan menggunakan Basic Template Yii2 (yang menurut saya penggunaannya sedikit lebih sulit daripada advance template Yii2).

Secara garis besar (dan mungkin akan bertambah sesuai keperluan yang mungkin terjadi) outline dari seri tulisan ini akan terdiri dari hal berikut.

  1. Prainstalasi
  2. Instalasi YiiFramework 2.0
  3. Login
  4. Login dengan Database pada Yii2
  5. Bekerja dengan Gii
  6. Module pada Yii2
  7. Layout dasar dan Manipulasinya pada Yii2
  8. Costum Asset dan Asset Bundle pada Yii2
  9. Alias pada Yii2
  10. Bekerja dengan Form
  11. Timestamp, Blameable, dan Sluggable Behavior pada Yii2
  12. Menggunakan Rich Text Input CkEditor dan Alternatifnya pada Yii2
  13. Gridview dan Listview
  14. SEO Friendly Url dengan slug
  15. Scenario pada Model Yii2
  16. Retrieve data pada Yii2
  17. Relasi Database pada Yii2
  18. Menggunakan Bootstrap4
  19. Widget Kartik dan Kartik Gridview
  20. Select2 dengan Kartik Ekstension
  21. Dependent Dropdown pada Yii2
  22. Bekerja dengan Modals
  23. Membuat Costum Template untuk Gii
  24. Mengupload File
  25. Mengupload File dengan Kartik Widget
  26. Gridview atau Datatables?
  27. Session dan Cookie pada Yii2
  28. Menggunakan AdminLTE pada Yii2
  29. Membuat Themes pada Yii2
  30. Menggunakan GoogleMaps API pada Yii2
  31. Menggunakan Socket.io pada Yii2
  32. Handling Error
  33. Bekerja dengan AuthClient
  34. Menggunakan Amazon S3 pada Yii2
  35. Mengirim Email dengan Swiftmailer pada Yii2
  36. Middleware pada Yii2
  37. Mengenal RBAC pada Yii2
  38. Implementasi RBAC pada Yii2
  39. Notifikasi Real Time dengan Socket.io pada Yii2

Anda dapat mengunduh dan memantau progress dari series ini lewat repositori Github belajararief-yii2series. Silahkan bintangi (star) untuk dapat lebih mudah memantau perkembangan repositori.

Requirement

Untuk memudahkan anda dalam memahami petunjuk ini, maka beberapa hal yang perlu diperhatikan diantaranya:

  1. Sistem Operasi yang saya gunakan adalah Windows 10 64bit dengan terminal menggunakan powershell terminal (beberapa command seperti cd dapat berbeda dengan command prompt biasa), namun saya akan berusaha sebisa mungkin mencontohkan perintah pada sistem operasi lain jika memunkinkan.
  2. Stack yang digunakan adalah Wamp Server (Apache 2.2, MySQL, PHP 7).
  3. Yii yang digunakan adalah Yii 2.0 dengan catatan jquery yang digunakan bukan jquery3. Beberapa perintah jquery akan berbeda pada jquery3, dan beberapa extensions yang saya gunakan sepertinya belum mendukung jquery3

Mengenal Select2

Jika pada form standar kita mengenal dropdown list, maka select2 merupakan salah satu optimasi dari dropdown list agar lebih enak dilihat dan mudah digunakan. Sebagai pengganti select box maka select2 memberikan banyak kemudahan bagi kita dalam memberikan pengalaman pengguna yang lebih baik bagi pengguna aplikasi kita. Lebih lanjut mengenai select2 dapat anda lihat pada https://select2.org/.

Menginstall Kartik Select2

Sekali lagi pada tulisan ini kita akan menggunakan select2 yang telah di-wrapper khusus untuk yii2 oleh kartik. Tambahkan baris berikut pada file composer.json anda kemudian lanjutkan dengan menjalankan perintah composer update pada terminal.

    "require": {
"php": ">=5.4.0",
"yiisoft/yii2": "~2.0.5",
"yiisoft/yii2-bootstrap4": "~2.0.0",
"yiisoft/yii2-swiftmailer": "~2.0.0",
"yiisoft/yii2-jui": "~2.0.0",
"2amigos/yii2-ckeditor-widget": "^2.1"
"kartik-v/yii2-widgets": "dev-master",
"kartik-v/yii2-grid": "dev-master",
"kartik-v/yii2-bootstrap4-dropdown": "@dev",
"kartik-v/yii2-widget-select2": "dev-master"
},

Kostumasi Tabel Blog dengan Pilihan Kategori

Kemudian kita akan membuat skenario berikut. Kita akan membuat tabel baru yaitu tabel Category, kemudian mengisi tabel Category dengan isi standar berupa kategori articles, terakhir kita tambahkan kolom category_id pada tabel blog. Semua itu kita lakukan terlebih dahulu dengan membuat migration. Jalankan perintah berikut pada terminal untuk membuat file migration.

yii migrate/create create_category_table   
yii migrate/create create_category_seed
yii migrate/create add_category_id_column_in_blog_table

Selanjutnya modifikasi file migration tadi sehingga tampak seperti di bawah ini.

create_category_table.php

    public function safeUp()
{
$tableOptions = null;
if ($this->db->driverName === 'mysql') {
$tableOptions = 'CHARACTER SET utf8 COLLATE utf8_unicode_ci ENGINE=InnoDB';
}

$this->createTable('{{%category}}', [
'id' => $this->primaryKey(),
'name' => $this->string(512)->notNull(),
'created_at' => $this->integer(),
'updated_at' => $this->integer(),
'created_by' => $this->integer(),
'updated_by' => $this->integer(),
], $tableOptions);
}

public function safeDown()
{
$this->dropTable('{{%category}}');
}

seed_category_table

    public function safeUp()
{
$this->insert('category', [
'name' => 'Articles',
'created_at' => 'now()',
'created_by' => 1,
'updated_by' => 1
]);
$this->insert('category', [
'name' => 'News',
'created_at' => 'now()',
'created_by' => 1,
'updated_by' => 1
]);

}

public function safeDown()
{
echo "m190629_105242_create_category_seed cannot be reverted.\n";

return false;
}

add_category_id_column_in_blog_table.php

    public function safeUp()
{
$this->addColumn('{{%blog}}', 'category_id', 'integer');

}

public function safeDown()
{
echo "m190629_105304_add_category_id_column_in_blog_table cannot be reverted.\n";

return false;
}

Selanjutnya jalankan perintah berikut di terminal.

yii migrate

Implementasi Select2 pada Form

Sebelum kita akan mengubah form, kita akan terlebih dahulu memodifikasi model. Pertama silakan buat model untuk tabel Category dengan bantuan Gii. Selanjutnya modifikasi file \app\models\Blog.php sehingga menjadi seperti di bawah ini.

<?php

namespace app\models;

use Yii;
use yii\behaviors\TimestampBehavior;
use yii\behaviors\BlameableBehavior;
use yii\behaviors\SluggableBehavior;

/**
* This is the model class for table "blog".
*
* @property int $id
* @property string $slug
* @property string $title
* @property string $body
* @property int $created_at
* @property int $updated_at
* @property int $created_by
* @property int $updated_by
*/
class Blog extends \yii\db\ActiveRecord
{
/**
* @inheritdoc
*/
public static function tableName()
{
return 'blog';
}

/**
* @inheritdoc
*/
public function rules()
{
return [
[['slug', 'title', 'body'], 'required', 'on' => 'default'],
[['body'], 'required', 'on' => 'editByOther'],
[['body'], 'string'],
[[ 'created_by', 'updated_by', 'category_id'], 'integer'],
['created_at', 'date', 'timestampAttribute' => 'created_at'],
['updated_at', 'date', 'timestampAttribute' => 'updated_at'],
[['slug'], 'string', 'max' => 2048],
[['title'], 'string', 'max' => 512],
];
}

/**
* @inheritdoc
*/
public function attributeLabels()
{
return [
'id' => 'ID',
'slug' => 'Slug',
'title' => 'Title',
'body' => 'Body',
'category_id' => 'Category',
'created_at' => 'Created At',
'updated_at' => 'Updated At',
'created_by' => 'Created By',
'updated_by' => 'Updated By',
];
}

public function behaviors()
{
return [
TimestampBehavior::class,
BlameableBehavior::class,
'slug' => [
'class' => SluggableBehavior::class,
'attribute' => 'title',
'ensureUnique' => true,
'immutable' => true
]
];
}

/**
* declare relations in created_by to user model
*/
public function getUserCreator()
{
return $this->hasOne(User::class, ['id' => 'created_by']);
}


/**
* declare relations in updated_by to user model
*/
public function getUserUpdater()
{
return $this->hasOne(User::class, ['id' => 'updated_by']);
}

/**
* declare relations in category_id to Category model
*/
public function getCategory()
{
return $this->hasOne(Category::class, ['id' => 'category_id']);
}

/**
* return a list of available category from Category model
*/
public function getCategoryList()
{
return Category::find()->all();
}
}

Selanjutnya kita akan mengubah form pada create dan update blog pada file \app\modules\administrator\views\blog\_form.php dan modifikasi sehingga menjadi seperti di bawah ini.

<?php

use yii\helpers\Html;
use yii\widgets\ActiveForm;
use dosamigos\ckeditor\CKEditor;
use kartik\select2\Select2;
use yii\helpers\ArrayHelper;

/* @var $this yii\web\View */
/* @var $model app\models\Blog */
/* @var $form yii\widgets\ActiveForm */
?>

<div class="blog-form">

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

<?= $form->field($model, 'title')->textInput(['maxlength' => true, 'disabled' => $model->scenario == 'editByOther' ? true : false]) ?>

<?= $form->field($model, 'category_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map($model->categoryList, 'id', 'name'),
'options' => ['placeholder' => 'Select a category ...'],
'pluginOptions' => [
'allowClear' => true
],
]) ?>

<?= $form->field($model, 'body')->widget(CKEditor::class, [
'options' => ['rows' => 6],
'preset' => 'basic'
]) ?>

<div class="form-group">
<?= Html::submitButton('Save', ['class' => 'btn btn-success']) ?>
</div>

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

</div>

Implementasi Select2 pada Filter GridView

Halaman view blog kita tidak lengkap jika tidak muncul pada laman management blog. Untuk itu kita akan menambahkan kolom Kategori pada halaman index, kemudian menggunakan select2 untuk memberikan filter blog lewat kategori. Buka dan modifikasi file \app\modules\administrator\views\blog\index.php sehingga terlihat seperti di bawah ini.

<?php

use yii\helpers\Html;
use kartik\grid\GridView;
use yii\widgets\Pjax;
use app\assets\ChartJsAsset;
use yii\helpers\Json;
use yii\helpers\StringHelper;
use yii\helpers\ArrayHelper;
use kartik\select2\Select2;

/* @var $this yii\web\View */
/* @var $searchModel app\modules\administrator\models\BlogSearch */
/* @var $dataProvider yii\data\ActiveDataProvider */

$this->title = 'Blogs';
$this->params['breadcrumbs'][] = $this->title;

// Register ChartJsAsset
ChartJsAsset::register($this);
?>
<div class="blog-index">
<div class="row">

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

<h1><?= Html::encode($this->title) ?></h1>

</div>

</div>

<div class="row">

<div class="col-md-6">

<p>
<?= Html::a('Create Blog', ['create'], ['class' => 'btn btn-success']) ?>
</p>

<?= GridView::widget([
'id' => 'kv-grid-demo',
'dataProvider' => $dataProvider,
'filterModel' => $searchModel,
'columns' => [
['class' => 'kartik\grid\SerialColumn'],
'title',
// [
// 'attribute' => 'body',
// 'format' => 'raw',
// 'value' => function ($model){
// return StringHelper::truncateWords(strip_tags($model->body, "<image>"), 30, "", true);
// }
// ],
[
'attribute' => 'category_id',
'value' => 'category.name',
'filter' => Select2::widget([
'model' => $searchModel,
'attribute' => 'category_id',
'data' => ArrayHelper::map(\app\models\Category::find()->all(), 'id', 'name'),
'options' => ['placeholder' => 'Category ...'],
'pluginOptions' => [
'allowClear' => true
],
])
],
[
'attribute' => 'created_by',
'value' => 'userCreator.username'
],
'created_at:date',
// 'userCreator.username',

[
'class' => 'kartik\grid\ActionColumn',
'noWrap' => true,
],
],
'containerOptions' => ['style' => 'overflow: auto'], // only set when $responsive = false
'headerRowOptions' => ['class' => 'kartik-sheet-style'],
'filterRowOptions' => ['class' => 'kartik-sheet-style'],
'pjax' => true, // pjax is set to always true for this demo
// set your toolbar
'toolbar' => [
[
'content' =>
Html::a('<i class="fas fa-redo"></i>', ['grid-demo'], [
'class' => 'btn btn-outline-secondary',
'title'=> 'Reset Grid',
'data-pjax' => 0,
]),
'options' => ['class' => 'btn-group mr-2']
],
'{export}',
'{toggleData}',
],
'toggleDataContainer' => ['class' => 'btn-group mr-2'],
// set export properties
'export' => [
'fontAwesome' => true
],
// parameters from the demo form
'bordered' => true,
'striped' => true,
'condensed' => true,
'responsive' => true,
'hover' => true,
'showPageSummary' => true,
'panel' => [
'type' => GridView::TYPE_PRIMARY,
'heading' => $this->title,
],
'persistResize' => false,
'toggleDataOptions' => ['minCount' => 10],
// 'itemLabelSingle' => 'book',
// 'itemLabelPlural' => 'books'
]) ?>

</div>

<div class="col-md-6">

<canvas id="blogCountByMonthChart"></canvas>

</div>

</div>

</div>
<?php
// first with convert our php array object to json
$blogCountByMonthJson = Json::encode($blogCountByMonth);

// then register our Js
$this->registerJs(<<<JS
// we create function for generate count per month first
function generateDataCount(month, blogCount){
var result = blogCount.find(o => o.month == month);
if(result == null) return 0;
return result.count;
}

var blogCount = $blogCountByMonthJson; // blogCount json
var ctx = document.getElementById('blogCountByMonthChart').getContext('2d'); //ctx, you can replace it with jQuery if you have one

// Then we generate data with some simple looping
var i = 0;
data = [];
while(i < 12)
{
data[i] = generateDataCount(i+1, blogCount);
i++;
}

// and then generate to chartJs
var chart = new Chart(ctx, {
type: 'bar',
data: {
labels: ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"],
datasets: [{
label: "Blog Count By Month",
backgroundColor: 'rgb(255, 99, 132)',
borderColor: 'rgb(255, 99, 132)',
data: data,
}]
},
options: {}
});
JS
);
?>

Selanjutnya laman manajemen blog anda akan menampilkan kategori dan filter by kategori. Namun jangan lupa ubah data blog agar memiliki kategori terlebih dahulu.


Demikian tulisan ini semoga bermanfaat dan Happy Coding!