how to update a record with file uploaded already? - file-upload

I want to UPDATE record without losing the File that i have uploaded. Below is my create action.
public function actionCreate()
{
$model = new Page;
if (isset($_POST['Page']))
{
$model->attributes = $_POST['Page'];
$model->filename = CUploadedFile::getInstance($model, 'filename');
if ($model->save())
{
if ($model->filename !== null)
{
$dest = Yii::getPathOfAlias('application.uploads');
$model->filename->saveAs($dest . '/' . $model->filename->name);
$model->save();
}
$this->redirect(array('view', 'id' => $model->id));
}
}
$this->render('create', array(
'model' => $model,
));
}

In yii, update method is designed to update the values that you are posting from your form. It will not update all Model properties.
For suppose, your Page model has 4 model properties, assume all are mandatory.
title
description
keywords
image
Since you don't want to update image field, you can make it non mandatory field by setting scenario for image field in your Page model rules.
class Page extends CActiveRecord
{
/*
Coding
*/
public function rules()
{
return array(
array('title, description,keywords', 'required'),
array('image', 'file', 'types'=>'jpg, png'),
array('image', 'required', 'on' => 'insert'),
// => You need image field to be entered on Create, not on Update
.................
}
}
So, Show file input in your form on Create, Hide on Update action so that image field won't submit.
//Your page form
<?php if($model->isNewRecord):?>
echo $form->labelEx($model, 'image');
echo $form->fileField($model, 'image');
echo $form->error($model, 'image');
<?php endif;?>
Since your are using Yii-2 you can use skippOnEmpty validator for the same.

Related

Required Rule on specific condition

I need to apply rule on a form. I have a country and dependent drop down of state.
I need to apply required rule on state field.
But if i choose India from drop down then required rule should be remove from the form.
I have enabled clientsidevalidation true in cactiveform.
View form:
<?php $form = $this->beginWidget('CActiveForm', array(
'id' => 'cart',
'enableAjaxValidation' => false,
'enableClientValidation'=>true,
'clientOptions'=>array('validateOnSubmit'=>true),
// we need the next one for transmission of files in the form.
'htmlOptions' => array('enctype' => 'multipart/form-data'),
));
echo $form->dropDownList($modelUser, 'country', Countries::getcountrylistwithcode(),
array('options' => array($currentCountry=>array('selected'=>true)),
'empty'=>'Select Country',
'class'=>'form-control input-lg',
));
echo $form->error($modelUser,'country');
echo $form->labelEx($modelUser,'state',array('class'=>"col-md-30"));
echo $form->dropDownList($modelUser, 'state', $stateList,array('class'=>"form-control input-lg",'prompt'=>'Select State'));
echo $form->error($modelUser,'state');
$this->endWidget();
?>
And model rules are like this:
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('city,country,state,address_line_one,postcode', 'required'),
You can achieve this by adding a custom rule to your model.
Change your rules function to something like this
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('city,country,address_line_one,postcode', 'required'),
array('state', 'validateState'),
)
}
Next up would be to create the custom validation rule. This would look something like this
public function validateState ($attribute, $params)
{
$aCountriesWithState = array('USA');
if (in_array($this->$attribute, $aCountriesWithState) && empty($this->$attribute))
{
$this->addError($attribute, 'State is missing');
}
}

How to upload multiple file at a time using TbActiveForm?

I am using TbActiveForm. I want upload multiple file at a time, Please help me.Thanks
In your TbActiveForm you have to use a widget for multiple file upload. You could write it yourself or use widget like CMultiFileUpload.
Here is reference for CMultiFileUpload.
Example for view:
<?php
$this->widget('CMultiFileUpload', array(
'model'=>$model,
'attribute'=>'photos',
'accept'=>'jpg|gif|png',
'options'=>array(),
'denied'=>'File is not allowed',
'max'=>10, // max 10 files
));
?>
Example for controller:
public function actionCreate()
{
$model = new Photo;
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
$type = isset($_GET['type']) ? $_GET['type'] : 'post';
if (isset($_POST['Photo'])) {
$model->attributes = $_POST['Photo'];
$photos = CUploadedFile::getInstancesByName('photos');
// proceed if the images have been set
if (isset($photos) && count($photos) > 0) {
// go through each uploaded image
foreach ($photos as $image => $pic) {
echo $pic->name.'<br />';
if ($pic->saveAs(Yii::getPathOfAlias('webroot').'/photos/path/'.$pic->name)) {
// add it to the main model now
$img_add = new Photo();
$img_add->filename = $pic->name; //it might be $img_add->name for you, filename is just what I chose to call it in my model
$img_add->topic_id = $model->id; // this links your picture model to the main model (like your user, or profile model)
$img_add->save(); // DONE
}
else{
echo 'Cannot upload!'
}
}
}
if ($model->save())
$this->redirect(array('update', 'id' => $model->id));
}
$this->render('create', array(
'model' => $model,
));
}
Source reference.

passing value from Yii CController class to CForm (Form Builder) config array

I'm new to Yii, and I'm trying to do my initial project the "right" way. I've created a CFormModel class that needs three fields to query for some data, a CForm config to construct the form, and a CController to tie it together (all given below).
The data request needs an account, and this can come from a couple of different places. I think retrieving it should be in the controller. However, I don't know how to get it into the form's hidden "account" field from the controller, so that it makes it to the arguments assigned to the CFormModel after submission. More generally, I know how to pass from CController to view script, but not to CForm. Is the registry (Yii::app()->params[]) my best bet?
I suppose I can just leave it out of the form (and required fields) and wait to populate it in the submit action (actionSummaries). Does that break the intention of CForm? Is there a best practice? Even taking this solution, can someone address the first issue, in case it comes up again?
Any other, gentle critique is welcome.
models/SummariesForm.php
class SummariesForm extends CFormModel
{
public $account;
public $userToken;
public $year;
public function rules () {...}
public function fetchSummary () {...}
static public function getYearOptions () {...}
}
views/account/select.php
<?php
$this->pageTitle=Yii::app()->name;
?>
<div class="form">
<?php echo $form->render(); ?>
</div>
controllers/AccountController.php
class AccountController extends CController
{
public $layout = 'extranet';
public function actionSelect ()
{
$model = new SummariesForm();
// retrieve account
require_once 'AccountCookie.php';
/*
*
* Here, I insert the account directly into the
* model used to build the form, but $model isn't
* available to selectForm.php. So, it doesn't
* become part of the form, and this $model doesn't
* persist to actionSummaries().
*
*/
$model->account = AccountCookie::decrypt();
if ($model->account === false) {
throw new Exception('Unable to retrieve account.');
}
$form = new CForm('application.views.account.selectForm', $model);
$this->render('select', array(
'form' => $form,
'account' => $model->account,
));
}
public function actionSummaries ()
{
$model = new SummariesForm();
if (isset($_POST['SummariesForm'])) {
$model->attributes = $_POST['SummariesForm'];
/*
*
* Should I just omit "account" from the form altogether
* and fetch it here? Does that break the "model"?
*
*/
if ($model->validate() === true) {
try {
$summaries = $model->fetchSummary();
} catch (Exception $e) {
...
CApplication::end();
}
if (count($summaries) === 0) {
$this->render('nodata');
CApplication::end();
}
$this->render('summaries', array('model' => $model, 'summaries' => $summaries));
} else {
throw new Exception('Invalid year.');
}
}
}
}
views/account/selectForm.php
<?php
return array(
'title' => 'Select year',
'action' => Yii::app()->createUrl('Account/Summaries'),
'method' => 'post',
'elements' => array(
'account' => array(
'type' => 'hidden',
'value' => $account,
),
'userToken' => array(
'type' => 'hidden',
'value' => /* get token */,
),
'year' => array(
'type' => 'dropdownlist',
'items' => SummariesForm::getYearOptions(),
),
),
'buttons' => array(
'view' => array(
'type' => 'submit',
'label' => 'View summaries',
),
),
);
The answer is NO to do what you asked. You can see $form variable which acted almost like array when it was passed from controller to view. The solution is you add more property $account into selectForm model and treat it like other elements. I don't think leaving the new field outside the form will be properly way if you want to submit its value also.
Edited:

Validate data in renderPartial in Yii

I just created this a renderPartial():
renderPartial('/users/_form', array('model'=>new Users), true, true); ?>
the problem that the data entered doesn't validated.
Did I miss something ?
it's not clear from your question exactly WHEN you want to validate.
If on client side you need something like this:
<?php $form=$this->beginWidget('CActiveForm', array(
'id'=>'your-form',
'enableAjaxValidation'=>true,
'clientOptions' => array(
'validateOnSubmit'=>true,
),
)); ?>
Plus this in your controller in the post action:
$this->performAjaxValidation($model);
Along with a controller method like:
/**
* Performs the AJAX validation.
* #param CModel the model to be validated
*/
protected function performAjaxValidation($model)
{
if(isset($_POST['ajax']) && $_POST['ajax']==='saferides-registered-form')
{
echo CActiveForm::validate($model);
Yii::app()->end();
}
}
If you only want to validate on post, something like this as part of your controller action that handles the post:
if ( $model->validate() && $model-save() )
{
..redirect to your view
}
Also consult the docs

PHP YII : HOW TO UPLOAD VIDEO

my model code:
public $image;
return array(
array('filename', 'required'),
array('image', 'file', 'types'=>''),
array('filename', 'length', 'max'=>11),
array('id, filename', 'safe', 'on'=>'search'),
);
my view code:
<?php echo CHtml::activeFileField($model, 'image'); ?>
my controller code:
$model = new TblUpload;
$model->attributes=$_POST['TblUpload'];
$img = CUploadedFile::getInstance($model,'image');
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
{
$model->filename = $img;
$model->save(false);
}
}
$this->render('uploadfile',array('model'=>$model));
}
hi friends using this code i am able to upload all types of files like images and documents, but i am unable to upload videos.... i have changed my php.ini file max_upload_size also...
In your form view, have you set the enctype for the form?
$form = $this->beginWidget(
'CActiveForm', array(
'id' => 'my-form',
'htmlOptions' => array(
'enctype' => 'multipart/form-data'
),
)
);
It could also possibly be the path to the folder you are trying to upload to doesn't exists or is incorrect. Try using getcwd(), eg:
$model->my_image->saveAs(getcwd()."/uploads/myfile.jpg");
This is most likely the problem, your path in your code above is:
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
The basepath and followed by the ../ probably wrong unless you areally are trying to upload in the directory before your root?
Finally i sorted out how to upload images...
Here is my controller code.....
public function actionUploadfile()
{
$model = new TblUpload;
if(isset($_POST['TblUpload']))
{
$model->image=CUploadedFile::getInstance($model,'image');
if($model->save())
{
$model->image->saveAs('/wamp/www/fileupload/images/'.$fileName);
}*/
$model->attributes=$_POST['TblUpload'];
$img = CUploadedFile::getInstance($model,'image');
if($img->saveAs(Yii::app()->basePath.'/../images/'.$img))
{
$model->filename = $img;
$model->save(false);
}
}
$this->render('uploadfile',array('model'=>$model));
}
this was the place i got mistaken... but now i am using uploadify extension to upload all kinds of files and edited it to be used for multiple upload at a time