เชื่อว่าหลายๆ คนคงเคยปวดหัวกับการสร้างฟอร์มเพื่อทำการอัพโหลดไฟล์ต่างๆ หรือไฟล์รูปภาพเองก็ตาม ถ้าเป็นฟอร์มอัพโหลดแบบธรรมดาก็คงไม่เท่าไหร่ แต่ถ้าเป็นแบบ ajax ก็คงจะปวดหัวไม่ใช่น้อย.. T_T' เดี่ยววันเราจะมาลองทำฟอร์ม Upload แบบ ajax กันซึ่งพระเอกของเราวันนี้คือ fileinput เป็น Widget ของ krajee เจ้าเก่า ซึ่งรวมอยู่ในแพ็คเก็จ Yii2 Widget อยู่แล้ว ติดตั้งทีเดียวได้ครบเลย ^
เราจะเพิ่มการอัพโหลดแบบ ajax คุณสมบัติหลักคือ - สามารถอัพโหลดได้ทันทีผ่าน ajax โดยไม่ต้องรอ create record - สามารถกดปุ่ม upload ajax ได้ หรือ กด submit ผ่านฟอร์มได้เช่นกัน - หากเป็นรูปภาพจะสร้าง thumbnail และ resize อัตโนมัติ - สามารถกดปุ่มลบรายการที่อัพโหลดได้ - เมื่อมีการลบ record จะตามไปลบข้อมูลทั้ง folder ด้วยและลบรายการทั้งหมดที่ตาราง uploads
ติดตั้ง extension เพิ่มเติม
เพิ่ม รายชื่อ extension เข้าไปที่ไฟล์ composer.json เพิ่มไว้ภายใต้แท็ก require จากนั้น cd เข้าไปที่ root project ของเราแล้วรันคำสั่ง composer update
"kartik-v/yii2-widgets": "*",
"yurkinx/yii2-image": "dev-master",
"2amigos/yii2-date-picker-widget" : "~1.0",
"2amigos/yii2-gallery-widget" : "*"
yii2-image ต้องเปิดใช้งานที่ config ในส่วนของ components เพิ่มการตั้งค่าเข้าไป
'image' => [
'class' => 'yii\image\ImageDriver',
'driver' => 'GD', //GD or Imagick
],
Gii Model และ Gii CRUD PhotoLibrary
ในตัวอย่างนี้เราจะสร้างระบบเก็บรูปภาพโดยใช้ตารางชื่อว่า photolibrary และสร้างตารางตามนี้
CREATE TABLE `photo_library` (
`id` int(11) NOT NULL AUTO_INCREMENT,
`ref` varchar(50) DEFAULT NULL COMMENT 'เลข fk กับ upload ใช้กับ upload ajax',
`event_name` varchar(255) DEFAULT NULL COMMENT 'ชื่องาน',
`detail` text COMMENT 'รายละเอียด',
`start_date` datetime DEFAULT NULL COMMENT 'วันที่เริ่มถ่ายภาพ',
`end_date` datetime DEFAULT NULL COMMENT 'วันที่ถ่ายภาพเสร็จ',
`location` varchar(255) DEFAULT NULL COMMENT 'สถานที่',
`customer_name` varchar(150) DEFAULT NULL COMMENT 'ชื่อลูกค้า',
`customer_mobile_phone` varchar(20) DEFAULT NULL COMMENT 'เบอร์โทร',
`province_id` int(11) DEFAULT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `ref` (`ref`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
CREATE TABLE `uploads` (
`upload_id` int(11) NOT NULL AUTO_INCREMENT,
`ref` varchar(50) DEFAULT NULL,
`file_name` varchar(150) DEFAULT NULL COMMENT 'ชื่อไฟล์',
`real_filename` varchar(150) DEFAULT NULL COMMENT 'ชื่อไฟล์จริง',
`create_date` timestamp NULL DEFAULT CURRENT_TIMESTAMP,
`type` int(11) DEFAULT NULL COMMENT 'ประเภท',
PRIMARY KEY (`upload_id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8
หลังจากสร้างตารางเรียบร้อย ให้ทำการ gii Model PhotoLibrary และ crud PhotoLibrary
สร้างฟอร์ม
หลังจากที่ได้ไฟล์จากการ gii crud แล้วเราจะทำการปรับปรุงฟอร์มเพิ่มเติมเพื่อให้สามารถ upload file ได้
เปิดไฟล์ views\photo-library\_form.php
เพิ่มแท็ก enctype
เข้าไป
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
แก้ไขฟิวด์ ref ให้เป็น hidenInput และเซ็ตค่า label เป็น false
<?= $form->field($model, 'ref')->hiddenInput(['maxlength' => 50])->label(false); ?>
ทำการเรียกใช้งาน Select2 widget เพื่อแสดงรายชื่อจังหวัดจาก model Province
โครงสร้างตาราง province ดูได้ที่นี่
เรียกใช้งาน
<?= $form->field($model, 'province_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(province::find()->all(),'PROVINCE_ID','PROVINCE_NAME'),
'options' => ['placeholder' => 'เลือกจังหวัด ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
เรียกใช้งาน DatePicker ของ kartik
<div class="row">
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'start_date')->widget(
DatePicker::className(), [
'language' => 'th',
'options' => ['placeholder' => 'Select issue date ...'],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'todayHighlight' => true
]
]);?>
</div>
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'end_date')->widget(
DatePicker::className(), [
'language' => 'th',
'options' => ['placeholder' => 'Select issue date ...'],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'todayHighlight' => true
]
]);?>
</div>
</div>
เรียกใช้งาน FileUpload เพื่อสร้างฟอร์ม upload ajax โดยตัวอย่างนี้จะใช้เฉพาะกับรูปภาพ ซึ่งจริงๆ แล้วเราสามารถกำหนดให้อัพโหลดเป็นไฟล์อะไรก็ได้
FileInput::widget()
มี property ที่จำเป็นดังนี้
- overwriteInitial
กำหนดให้สามารถเพิ่มไฟล์อัพโหลดใหม่เข้าไปได้โดยที่ไม่ลบรายการเก่าออกไป
- initialPreviewShowDelete
ถ้าโหลดไฟล์มาแสดงให้ทำการแสดงปุ่มลบด้วย
- initialPreview
รายการรูปภาพที่เราจะมาแสดงใน thumbnail ซึ่งรับค่าเป็น array html tag img
- initialPreviewConfig
ค่าคอนฟิกสำหรับตอนแสดง thumbnail เช่น url ที่ลบไฟล์
- uploadUrl
url ที่เราจะส่งไฟล์ไปอัพโหลดแบบ ajax
- uploadExtraData
เราสามารถส่งค่าตัวแปรแนบไปกับการอัพโหลดได้
<div class="form-group field-upload_files">
<label class="control-label" for="upload_files[]"> ภาพถ่าย </label>
<div>
<?= FileInput::widget([
'name' => 'upload_ajax[]',
'options' => ['multiple' => true,'accept' => 'image/*'], //'accept' => 'image/*' หากต้องเฉพาะ image
'pluginOptions' => [
'overwriteInitial'=>false,
'initialPreviewShowDelete'=>true,
'initialPreview'=> $initialPreview,
'initialPreviewConfig'=> $initialPreviewConfig,
'uploadUrl' => Url::to(['/photo-library/upload-ajax']),
'uploadExtraData' => [
'ref' => $model->ref,
],
'maxFileCount' => 100
]
]);
?>
</div>
</div>
ดูโค้ดที่ปรับแต่งทั้งหมด
<?php
use yii\helpers\Html;
use yii\helpers\Url;
use yii\widgets\ActiveForm;
use yii\helpers\ArrayHelper;
use app\models\Province;
use kartik\widgets\Select2;
use kartik\widgets\FileInput;
use kartik\date\DatePicker;
/* @var $this yii\web\View */
/* @var $model app\models\PhotoLibrary */
/* @var $form yii\widgets\ActiveForm */
?>
<div class="photo-library-form">
<?php $form = ActiveForm::begin(['options' => ['enctype' => 'multipart/form-data']]); ?>
<?=$form->errorSummary($model) ?>
<?= $form->field($model, 'ref')->hiddenInput(['maxlength' => 50])->label(false); ?>
<?= $form->field($model, 'event_name')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'detail')->textarea(['rows' => 3]) ?>
<div class="row">
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'start_date')->widget(
DatePicker::className(), [
'language' => 'th',
'options' => ['placeholder' => 'Select issue date ...'],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'todayHighlight' => true
]
]);?>
</div>
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'end_date')->widget(
DatePicker::className(), [
'language' => 'th',
'options' => ['placeholder' => 'Select issue date ...'],
'pluginOptions' => [
'format' => 'yyyy-mm-dd',
'todayHighlight' => true
]
]);?>
</div>
</div>
<?= $form->field($model, 'location')->textInput(['maxlength' => 255]) ?>
<?= $form->field($model, 'province_id')->widget(Select2::classname(), [
'data' => ArrayHelper::map(province::find()->all(),'PROVINCE_ID','PROVINCE_NAME'),
'options' => ['placeholder' => 'เลือกจังหวัด ...'],
'pluginOptions' => [
'allowClear' => true
],
]);
?>
<div class="row">
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'customer_name')->textInput(['maxlength' => 150]) ?>
</div>
<div class="col-sm-6 col-md-6">
<?= $form->field($model, 'customer_mobile_phone')->textInput(['maxlength' => 20]) ?>
</div>
</div>
<div class="form-group field-upload_files">
<label class="control-label" for="upload_files[]"> ภาพถ่าย </label>
<div>
<?= FileInput::widget([
'name' => 'upload_ajax[]',
'options' => ['multiple' => true,'accept' => 'image/*'], //'accept' => 'image/*' หากต้องเฉพาะ image
'pluginOptions' => [
'overwriteInitial'=>false,
'initialPreviewShowDelete'=>true,
'initialPreview'=> $initialPreview,
'initialPreviewConfig'=> $initialPreviewConfig,
'uploadUrl' => Url::to(['/photo-library/upload-ajax']),
'uploadExtraData' => [
'ref' => $model->ref,
],
'maxFileCount' => 100
]
]);
?>
</div>
</div>
<div class="form-group">
<?= Html::submitButton($model->isNewRecord ? 'Create' : 'Update', ['class' => ($model->isNewRecord ? 'btn btn-success' : 'btn btn-primary').' btn-lg btn-block']) ?>
</div>
<?php ActiveForm::end(); ?>
</div>
แก้ไขไฟล์ views/photo-library/create.php
เราจะทำการส่งค่า initialPreview
และ initialPreviewConfig
เป็น array ว่างๆ ไปเพราะในตอน create ยังไม่มีข้อมูลที่จะแสดง เราจึงจำเป็นต้องส่ง array ว่างๆ ไปก่อน
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model app\models\PhotoLibrary */
$this->title = 'Create Photo Library';
$this->params['breadcrumbs'][] = ['label' => 'Photo Libraries', 'url' => ['index']];
$this->params['breadcrumbs'][] = $this->title;
?>
<div class="photo-library-create">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'initialPreview'=>[],
'initialPreviewConfig'=>[]
]) ?>
</div>
แก้ไขไฟล์ views/photo-library/update.php
ใน actionUpdate เราจะทำการส่งค่า initialPreview
และ initialPreviewConfig
ไปเพื่อให้ widget แสดง thumbnail รูปภาพที่เคยอัพโหลดไปแล้ว แต่ในตอนนี้เรายังไม่ได้สร้างฟังชันเราจะส่ง array ว่างๆ ไปก่อน
<?php
use yii\helpers\Html;
/* @var $this yii\web\View */
/* @var $model app\models\PhotoLibrary */
$this->title = 'Update Photo Library: ' . ' ' . $model->id;
$this->params['breadcrumbs'][] = ['label' => 'Photo Libraries', 'url' => ['index']];
$this->params['breadcrumbs'][] = ['label' => $model->id, 'url' => ['view', 'id' => $model->id]];
$this->params['breadcrumbs'][] = 'Update';
?>
<div class="photo-library-update">
<h1><?= Html::encode($this->title) ?></h1>
<?= $this->render('_form', [
'model' => $model,
'initialPreview'=>[],
'initialPreviewConfig'=>[]
]) ?>
</div>
ลองทดสอบรันจะได้ฟอร์มตามตัวอย่างนี้
เพิ่ม function ใน Model PhotoLibrary
- UPLOAD_FOLDER เป็นตัวแปร static ให้เรากำหนดชื่อโฟลเดอร์ที่ต้องการอัพโหลดได้
- getUploadPath() เป็นฟังก์ชันไว้เรียกพาทไฟล์จริงใน server
- getUploadUrl() เป็นฟังก์ชันไว้เรียก url จริงของไฟล์
- getThumbnails() เป็นฟังก์ชันส่งข้อมูล array ให้ widget Gallry เพื่อแสดง thumbnail
- getProvince() เป็นการสร้าง relation ไปยังตาราง province ด้วยฟิวด์ province_id เพื่อดึงชื่อจังหวัดมาแสดง
ให้ทำการเพิ่ม function เข้าไปที่ไฟล์ models\PhotoLibrary.php
ดังนี้
const UPLOAD_FOLDER='photolibrarys';
// ..........
public static function getUploadPath(){
return Yii::getAlias('@webroot').'/'.self::UPLOAD_FOLDER.'/';
}
public static function getUploadUrl(){
return Url::base(true).'/'.self::UPLOAD_FOLDER.'/';
}
public function getThumbnails($ref,$event_name){
$uploadFiles = Uploads::find()->where(['ref'=>$ref])->all();
$preview = [];
foreach ($uploadFiles as $file) {
$preview[] = [
'url'=>self::getUploadUrl(true).$ref.'/'.$file->real_filename,
'src'=>self::getUploadUrl(true).$ref.'/thumbnail/'.$file->real_filename,
'options' => ['title' => $event_name]
];
}
return $preview;
}
public function getProvince()
{
return $this->hasOne(Province::className(),['PROVINCE_ID'=>'province_id']);
}
สร้าง Function ใน Controller PhotoLibrary สำหรับการอัพโหลด Ajax
Uploads()
ฟังก์ชันนี้มีหน้าทีรับไฟล์จาก ajax from แล้วส่งข้อมูลมาทำการอัพโหลดไฟล์ สามารถอัพได้ทั้งภาพและไฟล์ ถ้าเป็นภาพจะทำการ resize และสร้าง thumbnail ให้
private function Uploads($isAjax=false) {
if (Yii::$app->request->isPost) {
$images = UploadedFile::getInstancesByName('upload_ajax');
if ($images) {
if($isAjax===true){
$ref =Yii::$app->request->post('ref');
}else{
$Freelance = Yii::$app->request->post('Freelance');
$ref = $Freelance['ref'];
}
$this->CreateDir($ref);
foreach ($images as $file){
$fileName = $file->baseName . '.' . $file->extension;
$realFileName = md5($file->baseName.time()) . '.' . $file->extension;
$savePath = Freelance::UPLOAD_FOLDER.'/'.$ref.'/'. $realFileName;
if($file->saveAs($savePath)){
if($this->isImage(Url::base(true).'/'.$savePath)){
$this->createThumbnail($ref,$realFileName);
}
$model = new Uploads;
$model->ref = $ref;
$model->file_name = $fileName;
$model->real_filename = $realFileName;
$model->save();
if($isAjax===true){
echo json_encode(['success' => 'true']);
}
}else{
if($isAjax===true){
echo json_encode(['success'=>'false','eror'=>$file->error]);
}
}
}
}
}
}
getInitialPreview()
ฟังก์ชันนี้เอาไว้ดึงรายการข้อมูลของตาราง Uploads
เพื่อแสดงที่ thumbnail ตรงอัพโหลดในตอนที่มีการแก้ไขข้อมูล
private function getInitialPreview($ref) {
$datas = Uploads::find()->where(['ref'=>$ref])->all();
$initialPreview = [];
$initialPreviewConfig = [];
foreach ($datas as $key => $value) {
array_push($initialPreview, $this->getTemplatePreview($value));
array_push($initialPreviewConfig, [
'caption'=> $value->file_name,
'width' => '120px',
'url' => Url::to(['/freelance/deletefile-ajax']),
'key' => $value->upload_id
]);
}
return [$initialPreview,$initialPreviewConfig];
}
isImage()
ฟังก์ชันนี้เอาไว้แยกแยะระหว่างไฟล์และรูปภาพ
public function isImage($filePath){
return @is_array(getimagesize($filePath)) ? true : false;
}
getTemplatePreview()
เอาไว้เลือก template ที่จะแสดงผลว่าเป็น image หรือไฟล์อื่นๆ
private function getTemplatePreview(Uploads $model){
$filePath = Freelance::getUploadUrl().$model->ref.'/thumbnail/'.$model->real_filename;
$isImage = $this->isImage($filePath);
if($isImage){
$file = Html::img($filePath,['class'=>'file-preview-image', 'alt'=>$model->file_name, 'title'=>$model->file_name]);
}else{
$file = "<div class='file-preview-other'> " .
"<h2><i class='glyphicon glyphicon-file'></i></h2>" .
"</div>";
}
return $file;
}
createThumbnail()
เป็น function ที่เอาไว้สร้าง thumbnail เล็กๆ เพื่อให้สามารถแสดงผลได้เร็ว
private function createThumbnail($folderName,$fileName,$width=250){
$uploadPath = Freelance::getUploadPath().'/'.$folderName.'/';
$file = $uploadPath.$fileName;
$image = Yii::$app->image->load($file);
$image->resize($width);
$image->save($uploadPath.'thumbnail/'.$fileName);
return;
}
actionDeletefileAjax()
เป็น action ที่เอาไว้ลบไฟล์ในกรณีที่คลิกลบไฟล์ จาก thumbnail ในตัวอัพโหลด ajax
public function actionDeletefileAjax(){
$model = Uploads::findOne(Yii::$app->request->post('key'));
if($model!==NULL){
$filename = Freelance::getUploadPath().$model->ref.'/'.$model->real_filename;
$thumbnail = Freelance::getUploadPath().$model->ref.'/thumbnail/'.$model->real_filename;
if($model->delete()){
@unlink($filename);
@unlink($thumbnail);
echo json_encode(['success'=>true]);
}else{
echo json_encode(['success'=>false]);
}
}else{
echo json_encode(['success'=>false]);
}
}
เป็นฟังก์ชันลบ folder ที่ใช้เก็บไฟล์ เราจะใช้ในกรณีหากมีการลบ record ก็ให้ตามไปลบไฟล์ทั้งหมดด้วย
private function removeUploadDir($dir){
BaseFileHelper::removeDirectory(Freelance::getUploadPath().$dir);
}
สุดท้ายทำการปรับปรุง actionDelete() ซักเล็กน้อย โดยหากมีการลบ record ก็ให้ทำการลบโฟล์เดอร์ที่เก็บไฟล์นั้นด้วย โดยใช้ removeUploadDir()
ที่เราสร้างไว้แล้วก่อนหน้านี้
public function actionDelete($id)
{
$model = $this->findModel($id);
//remove upload file & data
$this->removeUploadDir($model->ref);
Uploads::deleteAll(['ref'=>$model->ref]);
$model->delete();
return $this->redirect(['index']);
}
สร้าง actionUploadAjax
เป็น function ที่เอาไว้รองรับการอัพโหลดไฟล์ผ่าน ajax ซึ่งเราจะใช้ Upload() ที่เราสร้างไว้ โดยรับค่า parameter 1 ตัวคือ $isAjax เพื่อไปเช็คว่าเป็นการอัพโหลดผ่าน ajax หรือผ่านการ submission form จากนั้นให้ทดลองทำการอัพโหลดไฟล์ลองดู
php
public function actionUploadAjax(){
$this->Uploads(true);
}
เรียกใช้งานที่ actionCreate และ actionUpdate
ปรับปรุงให้ action เดิมๆ สามารถรองรับการอัพโหลดจากฟอร์ม ajax ได้ เพราะหากเค้าไม่คลิกปุ่มอัพโหลด ajax แล้วข้อมูลจะยังไม่ถูกอัพโหลด เราจะแก้ไขโดยการเรียกใช้งาน function Upload() ที่เราได้สร้างไว้และใช้กับ actionUploadAjax() ซึ่งสามารถนำมาใช้กับ acionCreate และ actionUpdate ได้
โดยเพิ่ม this->Uploads(false);
เข้าไป
public function actionCreate()
{
$model = new PhotoLibrary();
if ($model->load(Yii::$app->request->post()) ) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
$model->ref = substr(Yii::$app->getSecurity()->generateRandomString(),10);
}
return $this->render('create', [
'model' => $model,
]);
}
ส่วน actionUpdate() เพิ่ม getInitialPreview() เข้ามาด้วยเพื่อใช้แสดง thumbnail ในตัว ajax upload
public function actionUpdate($id)
{
$model = $this->findModel($id);
list($initialPreview,$initialPreviewConfig) = $this->getInitialPreview($model->ref);
if ($model->load(Yii::$app->request->post())) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
'initialPreview'=>$initialPreview,
'initialPreviewConfig'=>$initialPreviewConfig
]);
}
และแก้ไขไฟล์เพิ่มเติม views/freelance/create.php
<?= $this->render('_form', [
'model' => $model,
'initialPreview'=> [],
'initialPreviewConfig'=> [],
]) ?>
และแก้ไขไฟล์ views/freelance/update.php
php
<?= $this->render('_form', [
'model' => $model,
'initialPreview'=>$initialPreview,
'initialPreviewConfig'=>$initialPreviewConfig
]) ?>
โค้ดทั้งหมด ใน PhotolibraryController()
<?php
namespace app\Controllers;
use Yii;
use app\models\Uploads;
use app\models\PhotoLibrary;
use app\models\PhotoLibrarySearch;
use yii\web\Controller;
use yii\web\NotFoundHttpException;
use yii\filters\VerbFilter;
use yii\helpers\Url;
use yii\helpers\html;
use yii\web\UploadedFile;
use yii\helpers\BaseFileHelper;
use yii\helpers\Json;
use yii\helpers\ArrayHelper;
/**
* PhotoLibraryController implements the CRUD actions for PhotoLibrary model.
*/
class PhotoLibraryController extends Controller
{
public function behaviors()
{
return [
'verbs' => [
'class' => VerbFilter::className(),
'actions' => [
'delete' => ['post'],
],
],
];
}
/**
* Lists all PhotoLibrary models.
* @return mixed
*/
public function actionIndex()
{
$searchModel = new PhotoLibrarySearch();
$dataProvider = $searchModel->search(Yii::$app->request->queryParams);
return $this->render('index', [
'searchModel' => $searchModel,
'dataProvider' => $dataProvider,
]);
}
/**
* Displays a single PhotoLibrary model.
* @param integer $id
* @return mixed
*/
public function actionView($id)
{
return $this->render('view', [
'model' => $this->findModel($id),
]);
}
/**
* Creates a new PhotoLibrary model.
* If creation is successful, the browser will be redirected to the 'view' page.
* @return mixed
*/
public function actionCreate()
{
$model = new PhotoLibrary();
if ($model->load(Yii::$app->request->post()) ) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
} else {
$model->ref = substr(Yii::$app->getSecurity()->generateRandomString(),10);
}
return $this->render('create', [
'model' => $model,
]);
}
/**
* Updates an existing PhotoLibrary model.
* If update is successful, the browser will be redirected to the 'view' page.
* @param integer $id
* @return mixed
*/
public function actionUpdate($id)
{
$model = $this->findModel($id);
list($initialPreview,$initialPreviewConfig) = $this->getInitialPreview($model->ref);
if ($model->load(Yii::$app->request->post())) {
$this->Uploads(false);
if($model->save()){
return $this->redirect(['view', 'id' => $model->id]);
}
}
return $this->render('update', [
'model' => $model,
'initialPreview'=>$initialPreview,
'initialPreviewConfig'=>$initialPreviewConfig
]);
}
/**
* Deletes an existing PhotoLibrary model.
* If deletion is successful, the browser will be redirected to the 'index' page.
* @param integer $id
* @return mixed
*/
public function actionDelete($id)
{
$model = $this->findModel($id);
//remove upload file & data
$this->removeUploadDir($model->ref);
Uploads::deleteAll(['ref'=>$model->ref]);
$model->delete();
return $this->redirect(['index']);
}
/**
* Finds the PhotoLibrary model based on its primary key value.
* If the model is not found, a 404 HTTP exception will be thrown.
* @param integer $id
* @return PhotoLibrary the loaded model
* @throws NotFoundHttpException if the model cannot be found
*/
protected function findModel($id)
{
if (($model = PhotoLibrary::findOne($id)) !== null) {
return $model;
} else {
throw new NotFoundHttpException('The requested page does not exist.');
}
}
/*|*********************************************************************************|
|================================ Upload Ajax ====================================|
|*********************************************************************************|*/
public function actionUploadAjax(){
$this->Uploads(true);
}
private function CreateDir($folderName){
if($folderName != NULL){
$basePath = PhotoLibrary::getUploadPath();
if(BaseFileHelper::createDirectory($basePath.$folderName,0777)){
BaseFileHelper::createDirectory($basePath.$folderName.'/thumbnail',0777);
}
}
return;
}
private function removeUploadDir($dir){
BaseFileHelper::removeDirectory(PhotoLibrary::getUploadPath().$dir);
}
private function Uploads($isAjax=false) {
if (Yii::$app->request->isPost) {
$images = UploadedFile::getInstancesByName('upload_ajax');
if ($images) {
if($isAjax===true){
$ref =Yii::$app->request->post('ref');
}else{
$PhotoLibrary = Yii::$app->request->post('PhotoLibrary');
$ref = $PhotoLibrary['ref'];
}
$this->CreateDir($ref);
foreach ($images as $file){
$fileName = $file->baseName . '.' . $file->extension;
$realFileName = md5($file->baseName.time()) . '.' . $file->extension;
$savePath = PhotoLibrary::UPLOAD_FOLDER.'/'.$ref.'/'. $realFileName;
if($file->saveAs($savePath)){
if($this->isImage(Url::base(true).'/'.$savePath)){
$this->createThumbnail($ref,$realFileName);
}
$model = new Uploads;
$model->ref = $ref;
$model->file_name = $fileName;
$model->real_filename = $realFileName;
$model->save();
if($isAjax===true){
echo json_encode(['success' => 'true']);
}
}else{
if($isAjax===true){
echo json_encode(['success'=>'false','eror'=>$file->error]);
}
}
}
}
}
}
private function getInitialPreview($ref) {
$datas = Uploads::find()->where(['ref'=>$ref])->all();
$initialPreview = [];
$initialPreviewConfig = [];
foreach ($datas as $key => $value) {
array_push($initialPreview, $this->getTemplatePreview($value));
array_push($initialPreviewConfig, [
'caption'=> $value->file_name,
'width' => '120px',
'url' => Url::to(['/photo-library/deletefile-ajax']),
'key' => $value->upload_id
]);
}
return [$initialPreview,$initialPreviewConfig];
}
public function isImage($filePath){
return @is_array(getimagesize($filePath)) ? true : false;
}
private function getTemplatePreview(Uploads $model){
$filePath = PhotoLibrary::getUploadUrl().$model->ref.'/thumbnail/'.$model->real_filename;
$isImage = $this->isImage($filePath);
if($isImage){
$file = Html::img($filePath,['class'=>'file-preview-image', 'alt'=>$model->file_name, 'title'=>$model->file_name]);
}else{
$file = "<div class='file-preview-other'> " .
"<h2><i class='glyphicon glyphicon-file'></i></h2>" .
"</div>";
}
return $file;
}
private function createThumbnail($folderName,$fileName,$width=250){
$uploadPath = PhotoLibrary::getUploadPath().'/'.$folderName.'/';
$file = $uploadPath.$fileName;
$image = Yii::$app->image->load($file);
$image->resize($width);
$image->save($uploadPath.'thumbnail/'.$fileName);
return;
}
public function actionDeletefileAjax(){
$model = Uploads::findOne(Yii::$app->request->post('key'));
if($model!==NULL){
$filename = PhotoLibrary::getUploadPath().$model->ref.'/'.$model->real_filename;
$thumbnail = PhotoLibrary::getUploadPath().$model->ref.'/thumbnail/'.$model->real_filename;
if($model->delete()){
@unlink($filename);
@unlink($thumbnail);
echo json_encode(['success'=>true]);
}else{
echo json_encode(['success'=>false]);
}
}else{
echo json_encode(['success'=>false]);
}
}
}
เพิ่ม Widget Gallery
เพื่อให้สามารถดูรูปภาพที่เราได้อัพโหลดไปแล้ว เราจะทำการเรียกใช้งาน widget Gallery
โดยเพิ่มที่ไฟล์ views\photo-library\view.php
เพิ่มการเรียกใช้งานเข้าไปด้านล่างสุด ซึ่งเราจะเรียกใช้งาน getThumbnails()
ที่เราได้สร้างไว้แล้วตอนแก้ไข Model PhotoLibrary
<div class="panel panel-default">
<div class="panel-body">
<?= dosamigos\gallery\Gallery::widget(['items' => $model->getThumbnails($model->ref,$model->event_name)]);?>
</div>
</div>
ลองใช้งาน
หน้าหลัก
การสร้างและแก้ไขข้อมูล
หน้า preview
เมื่อคลิกที่รูปภาพจะแสดงเป็น gallry
ดาวน์โหลด soucrecode ได้ที่นี่
ตัวอย่างอยู่ที่ PhotoLibraryController