Memulai Pembuatan Aplikasi Web dengan Yii2 (END): Penanganan Upload File
Muhammad Arslan 17 Oktober 2016
Kadangkala kita membutuhkan bagaimana suatu gambar dapat diunggah agar dapat tampil di slideshow atau menjadi gambar sampul dari suatu halaman profil. Yii2 memiliki penanganan upload file yang cukup mudah, semisal untuk mengunggah suatu gambar dengan ekstensi tertentu seperti PNG, JPG, ataupun SVG. Di tutorial ini kita akan mencoba bagaimana mengunggah sebuah gambar dan akan muncul di sebuah slideshow yang dihasilkan oleh widget bawaan Yii2.
Persiapan Coding
Karena kita masih akan menggunakan source code dari tutorial sebelumnya yang membahas pembuatan CRUD sendiri di Yii2, maka kita akan menambahkan tabel bernama team_galleries yang akan digunakan untuk menyimpan berbagai gambar dan informasinya yang terkait dengan suatu tim sepakbola. Berikut adalah sql untuk membuat tabel team_galleries plus dengan pembuatan foreign key-nya.Bilamana Anda belum memiliki tabel - tabel sebelumnya, dapat melihat tutorial "Memulai Pembuatan Aplikasi Web dengan Yii2: CRUD Dasar ke MySQL".CREATE TABLE IF NOT EXISTS `team_galleries` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(200) NOT NULL, `description` text NOT NULL, `filepath` text NOT NULL, `team_id` int(11) NOT NULL, PRIMARY KEY (`id`), KEY `fk_teams_team_galleries` (`team_id`) ) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=19 ;
ALTER TABLE
team_galleries
ADD CONSTRAINTfk_teams_teams_galleries
FOREIGN KEY (team_id
) REFERENCESteams
(id
) ON DELETE CASCADE ON UPDATE CASCADE;
Membuat Model untuk Tabel Galeri Tim
Untuk mediasi ke MySQL, kita membutuhkan sebuah model yang bernama TeamGalleries. Silahkan buat kode berikut dan simpan di dalam sebuah file dengan nama TeamGalleries.php di folder models:Sekarang perbaiki juga model Teams agar dapat mengambil galeri dengan menambahkan method getGallery():<?php
namespace app\models;
use yii\db\ActiveRecord;
class TeamGalleries extends ActiveRecord { public $teamsCount;
public static function tableName() { return 'team_galleries'; } public function getTeam(){ return $this->hasOne(Teams::className(), ['id' => 'team_id']); }
}
<?php
namespace app\models;
use yii\db\ActiveRecord;
class Teams extends ActiveRecord
{
public $teamsCount;
public static function tableName()
{
return 'teams';
}
public function getLeague(){
return $this->hasOne(Leagues::className(), ['id' => 'league_id']);
}
public function getGallery(){
return $this->hasMany(TeamGalleries::className(), ['team_id' => 'id']);
}
}
Membuat Daftar Galeri untuk Tim Sepak Bola
Karena kita tidak akan membuat controller baru, kita akan gunakan lagi HelloCrudController. Silahkan buat action baru dengan nama actionGallery dan tambahkan penggunaan class TeamGalleries seperti pada kode berikut dibawah ini:Sekarang buat views untuk halaman daftar galeri saat melihat galeri dari suatu tim. Buat kode berikut di dalam file gallery.php dan taruh di folder views/hello-crud:<?php
namespace app\controllers;
use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\helpers\Url; use yii\web\UploadedFile;
use app\models\Teams; use app\models\Leagues; use app\models\TeamsForm; use app\models\TeamGalleries;
class HelloCrudController extends Controller {
public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'rules' => [ [ 'actions' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'allow' => true, 'roles' => ['@'], ], ], ], ]; } ...................................................................... public function actionGallery($id) { $team = Teams::findOne(['id' => $id]); $galleries = TeamGalleries::find()->where(['team_id' => $id])->orderBy('id')->all(); return $this->render('gallery', ['team'=>$team, 'galleries'=>$galleries]); }
}
<?php
use yii\widgets\Breadcrumbs;
use yii\helpers\Url;
use yii\helpers\Html;
$this->title = "Hello CRUD";
?>
<div class="row">
<div class="col-md-12">
<h1><?php echo $team['name'] ?> Gallery</h1>
<hr/>
<?php
echo Breadcrumbs::widget([
'itemTemplate' => "<li>{link}</li>\n", // template for all links
'links' => [
['label' => 'Team List', 'url' => ['hello-crud/index']],
['label' => $team['name'], 'url' => ['hello-crud/detail', 'id'=>$team['id']]],
'Gallery',
],
]);
?>
</div>
</div>
<div>
<div class="col-md-2">
<div class="list-group">
<a href="<?php echo Url::to(['hello-crud/add-photo', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-eye-open"></i> Add New</a>
</div>
</div>
<div class="col-md-10">
<table class="table table-striped">
<thead>
<tr>
<th>Name</th>
<th>Description</th>
<th>File Path</th>
<th>Action</th>
</tr>
</thead>
<tbody>
<?php if (count($galleries) > 0) { ?>
<?php foreach ($galleries as $item): ?>
<tr>
<td><?= Html::encode("{$item['name']}") ?></td>
<td><?= Html::encode("{$item['description']}") ?></td>
<td><?= Html::encode("{$item['filepath']}") ?></td>
<td style="width:15%;text-align:center;">
<a class="btn btn-success btn-sm" href="<?php echo Url::to(['hello-crud/edit-photo', 'id'=>$team['id'], 'gal_id'=>$item['id']]); ?>"><i class="glyphicon glyphicon-pencil"></i></a>
<a class="btn btn-danger btn-sm" href="<?php echo Url::to(['hello-crud/delete-photo', 'id'=>$team['id'], 'gal_id'=>$item['id']]); ?>"><i class="glyphicon glyphicon-trash"></i></a>
</td>
</tr>
<?php endforeach; ?>
<?php } else { ?>
<tr>
<td style="text-align:center;font-size:15px;padding:25px;" colspan="5">No data found...</td>
</tr>
<?php } ?>
</tbody>
</table>
</div>
</div>
Untuk membuka halaman galeri suatu tim silahkan tambahkan link View Gallery di file views/hello-crud/detail.php:
..........................................................
<div>
<div class="col-md-2">
<div class="list-group">
<a href="<?php echo Url::to(['hello-crud/gallery', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-eye-open"></i> View Gallery</a>
<a href="<?php echo Url::to(['hello-crud/edit', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-pencil"></i> Edit Team</a>
<a href="<?php echo Url::to(['hello-crud/delete', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-trash"></i> Delete Team</a>
</div>
</div>
<div class="col-md-10">
..........................................................
Pastikan Anda sudah memiliki data tim sepakbola. Maka Anda akan melihat halaman kosong seperti ini terlebih dahulu:
Bila nanti tutorial ini sudah diselesaikan, maka akan muncul tampilan seperti berikut:
Membuat Form untuk Tambah Galeri Tim
Karena kita akan membuat fitur tambah galeri untuk suatu tim, kita membutuhkan Model untuk memvalidasi form tambah galeri. Silahkan buat sebuah file yang bernama TeamGalleriesForm.php dan taruh di folder models. Kemudian buat kode berikut:Pada kode diatas, nama file tidak boleh kosong dan maksimal 50 karakter, sedangkan deskripsi boleh diisi atau tidak. Enaknya lagi, kita dapat menentukan ekstensi file apa saja yang dapat diunggah oleh pengguna, dalam hal ini kita hanya memperbolehkan .png, .jpg, .gif dengan maksimal ukuran 1024 * 1024. Model form ini akan digunakan di proses validasi tambah galeri untuk suatu tim.<?php
namespace app\models;
use yii\base\Model;
class TeamGalleriesForm extends Model { public $name; public $description; public $photo; public $team_id;
public function rules() { return [ ['name', 'required','message' => 'Nama gambar gak boleh kosong'], ['name', 'string','max'=>'50'], ['description', 'string'], ['photo', 'file', 'extensions' => ['png', 'jpg', 'gif'], 'maxSize' => 1024*1024], ]; }
}
Membuat Tambah Galeri Tim
Masih di HelloCrudController, silahkan tambahkan model TeamGalleriesForm di bagian class import dan tambahkan juga actionAddPhoto untuk memfasilitasi proses penambahan galeri:Pada actionAddPhoto kita load terlebih dahulu model TeamGalleriesForm, kemudian kita lakukan validasi terhadap post data yang datang. Apabila lolos validasi maka gambar akan disimpan di folder upload dan informasinya akan disimpan oleh model TeamGalleries. Bila tidak lolos validasi dan request adalah GET, maka akan ditampilkan lagi halaman tambah galeri.<?php
namespace app\controllers;
use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\helpers\Url; use yii\web\UploadedFile;
use app\models\Teams; use app\models\Leagues; use app\models\TeamsForm; use app\models\TeamGalleries; use app\models\TeamGalleriesForm;
class HelloCrudController extends Controller {
public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'rules' => [ [ 'actions' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'allow' => true, 'roles' => ['@'], ], ], ], ]; } ...................................................................... public function actionAddPhoto($id) { $forms = new TeamGalleriesForm(); if ($forms->load(Yii::$app->request->post()) && $forms->validate()) { $request = Yii::$app->request; $forms->photo = UploadedFile::getInstance($forms, 'photo'); $team = new TeamGalleries(); $team->name = $request->post('TeamGalleriesForm')['name']; $team->description = $request->post('TeamGalleriesForm')['description']; $team->team_id = $id; $team->save(); $filepath = 'upload/'.$forms->photo->baseName.'_'.sha1($team->id).'.'.$forms->photo->extension; $forms->photo->saveAs($filepath); $team->filepath = $filepath; $team->save(); return $this->redirect(Url::to(['hello-crud/gallery', 'id'=>$id])); } else { $team = Teams::findOne(['id' => $id]); return $this->render('add_photo', ['team'=>$team, 'forms'=>$forms]); } }
}
Berikut adalah kode untuk views tambah galeri. Buat kode berikut di dalam file views/hello-crud/add_photo.php:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Breadcrumbs;
use yii\helpers\Url;
$this->title = "Hello CRUD";
?>
<div class="row">
<div class="col-md-12">
<h1><?php echo $team['name'] ?> Gallery</h1>
<hr/>
<?php
echo Breadcrumbs::widget([
'itemTemplate' => "<li>{link}</li>\n", // template for all links
'links' => [
['label' => 'Team List', 'url' => ['hello-crud/index']],
['label' => $team['name'], 'url' => ['hello-crud/detail', 'id'=>$team['id']]],
['label' => 'Gallery', 'url' => ['hello-crud/gallery', 'id'=>$team['id']] ],
'Add New',
],
]);
?>
</div>
</div>
<div>
<div class="col-md-12">
<?php $form = ActiveForm::begin([
'id' => 'teams-form',
'options' => ['class' => 'form-horizontal', 'enctype' => 'multipart/form-data']
])
?>
<div class="form-group">
<div class="col-lg-8">
<?= $form->field($forms, 'photo')->fileInput(); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-8">
<?= $form->field($forms, 'name')->hint('Diisi dengan nama yang terdiri dari angka, huruf kecil atau huruf besar'); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-8">
<?= $form->field($forms, 'description')->TextArea(); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-8">
<?= Html::submitButton('Simpan', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
Berikut adalah beberapa tampilan dari kode - kode diatas:
Membuat Edit Galeri Tim
Sekarang kita akan membuat proses dimana kita dapat mengubah nama dan deskripsi foto yang diunggah. Silahkan tambahkan actionEditPhoto() di dalam controllers/HelloCrudController.php:Prosesnya hampir sama dengan tambah foto. Hanya saja kita ambil terlebih dahulu foto yang akan kita edit melalui model TeamGalleries. Kemudian kita ubah nama dan deskripsinya sesuai dengan data yang kita kirimkan melalui form edit foto. Bila berhasil halaman akan diarahkan ke halaman daftar galeri, bila validasi gagal atau request adalah GET maka kita tampilkan form edit foto.<?php
namespace app\controllers;
use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\helpers\Url; use yii\web\UploadedFile;
use app\models\Teams; use app\models\Leagues; use app\models\TeamsForm; use app\models\TeamGalleries; use app\models\TeamGalleriesForm;
class HelloCrudController extends Controller {
public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'rules' => [ [ 'actions' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'allow' => true, 'roles' => ['@'], ], ], ], ]; } ...................................................................... public function actionEditPhoto($id, $gal_id) { $forms = new TeamGalleriesForm(); if ($forms->load(Yii::$app->request->post()) && $forms->validate()) { $request = Yii::$app->request; $photo = TeamGalleries::findOne(['id'=>$gal_id]); $photo->name = $request->post('TeamGalleriesForm')['name']; $photo->description = $request->post('TeamGalleriesForm')['description']; $photo->save(); return $this->redirect(Url::to(['hello-crud/gallery', 'id'=>$id])); } else { $team = Teams::findOne(['id' => $id]); $photo = TeamGalleries::findOne(['id'=>$gal_id]); return $this->render('edit_photo', ['team'=>$team, 'forms'=>$forms, 'photo'=>$photo]); } }
}
Sedangkan kode dibawah ini adalah kode untuk views edit foto. Silahkan buat kode berikut di dalam file views/hello-crud/edit_photo.php:
<?php
use yii\helpers\Html;
use yii\widgets\ActiveForm;
use yii\widgets\Breadcrumbs;
use yii\helpers\Url;
$this->title = "Hello CRUD";
?>
<div class="row">
<div class="col-md-12">
<h1>Edit Photo</h1>
<hr/>
<?php
echo Breadcrumbs::widget([
'itemTemplate' => "<li>{link}</li>\n", // template for all links
'links' => [
['label' => 'Team List', 'url' => ['hello-crud/index']],
['label' => $team['name'], 'url' => ['hello-crud/detail', 'id'=>$team['id']]],
['label' => 'Gallery', 'url' => ['hello-crud/gallery', 'id'=>$team['id']] ],
'Edit ',
],
]);
?>
</div>
</div>
<div>
<div class="col-md-12">
<?php $form = ActiveForm::begin([
'id' => 'teams-form',
'options' => ['class' => 'form-horizontal', 'enctype' => 'multipart/form-data']
])
?>
<div class="form-group">
<div class="col-lg-8">
<?= $form->field($forms, 'name')->textInput(['value'=>$photo['name']])->hint('Diisi dengan nama yang terdiri dari angka, huruf kecil atau huruf besar'); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-8">
<?= $form->field($forms, 'description')->TextArea(['value'=>$photo['description']]); ?>
</div>
</div>
<div class="form-group">
<div class="col-lg-8">
<?= Html::submitButton('Simpan', ['class' => 'btn btn-primary']) ?>
</div>
</div>
<?php ActiveForm::end(); ?>
</div>
</div>
Berikut adalah beberapa tampilan dari kode - kode diatas:
Membuat Hapus Galeri Tim Sepak Bola
Untuk proses penghapusan salah satu foto dari galeri, cukup mudah. Kita cari dulu foto mana yang akan dihapus dengan menggunakan findOne() kemudian foto yang terpilih kita hapus dengan method delete(), lalu kita arahkan kembali ke halaman daftar galeri. Silahkan tambahkan actionDeletePhoto() di dalam controller controllers/HelloCrudController.php:<?php
namespace app\controllers;
use Yii; use yii\filters\AccessControl; use yii\web\Controller; use yii\helpers\Url; use yii\web\UploadedFile;
use app\models\Teams; use app\models\Leagues; use app\models\TeamsForm; use app\models\TeamGalleries; use app\models\TeamGalleriesForm;
class HelloCrudController extends Controller {
public function actions() { return [ 'error' => [ 'class' => 'yii\web\ErrorAction', ], ]; } public function behaviors() { return [ 'access' => [ 'class' => AccessControl::className(), 'only' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'rules' => [ [ 'actions' => ['index', 'detail', 'add', 'edit', 'delete', 'delete-all', 'gallery', 'add-photo', 'edit-photo', 'delete-photo'], 'allow' => true, 'roles' => ['@'], ], ], ], ]; } ...................................................................... public function actionDeletePhoto($id, $gal_id) { $photo = TeamGalleries::findOne(['id'=>$gal_id]); unlink($photo->filepath); $photo->delete(); return $this->redirect(Url::to(['hello-crud/gallery', 'id'=>$id])); }
}
Menampilkan Galeri di Halaman Detail Tim Sepak Bola
Karena kita sudah membuat CRUD untuk galeri tim sepak bola, sekarang kita tampilkan galerinya tersebut dengan carousel di halaman detail tim sepakbola. Silahkan ubah views/hello-crud/detail.php menjadi kode seperti berikut:Dan berikut adalah contoh screenshot setelah halaman detail tim sepakbolah memiliki sejumlah foto:<?php
use yii\widgets\Breadcrumbs; use yii\helpers\Url; use yii\bootstrap\Carousel;
$this->title = "Hello CRUD";
?>
<div class="row"> <div class="col-md-12"> <h1><?php echo $team['name'] ?></h1> <hr/>
<?php echo Breadcrumbs::widget([ 'itemTemplate' => "<li>{link}</li>\n", // template for all links 'links' => [ ['label' => 'Team List', 'url' => ['hello-crud/index']], $team['name'], ], ]); ?> </div>
</div>
<div>
<div class="col-md-2"> <div class="list-group"> <a href="<?php echo Url::to(['hello-crud/gallery', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-eye-open"></i> View Gallery</a> <a href="<?php echo Url::to(['hello-crud/edit', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-pencil"></i> Edit Team</a> <a href="<?php echo Url::to(['hello-crud/delete', 'id'=>$team['id']]); ?>" class="list-group-item"><i class="glyphicon glyphicon-trash"></i> Delete Team</a> </div> </div> <div class="col-md-10"> <div class="col-md-4"> <?php$items = []; foreach ($team->gallery as $item){ $items[] = [ 'content' => '<img style="width:300px;" src="'.$item->filepath.'"/>', 'caption' => '<h4>'.$item->name.'</h4><p>'.$item->description.'</p>', ]; } echo Carousel::widget([ 'items' => $items, ]); ?> </div> <div class="col-md-8"> <p><b>League</b>: <?php echo $team->league['name'] ?></p> <p><b>Country</b>: <?php echo $team->country ?></p> <p><?php echo $team['description'] ?></p> </div>
</div>
Penutup
Setelah mempelajari bagian akhir dari seri tutorial ini, diharapkan Anda sudah dapat membuat aplikasi web sendiri menggunakan Yii2. Di tutorial berikutnya, Anda akan mempelajari teknik - teknik lainnya yang dapat dilakukan di Yii2. Semoga bermanfaat, terima kasih telah mengikuti seri tutorial ini :D.(codepolitan/yiiframework)