I'm implementing some file uploading fields and i'm having some difficulties with it.
I was following this article and everything was perfect until I tried to update my model.
If I didn't fill the file field, it was cleared after save. I was googling and find this topic. I've modified my code, but now, when I try to modify another field, it isn't save, unless I modify the image field too.
Where's the problem?
My model code:
public function actionUpdate($id)
{
$model=$this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Company']))
{
$model->attributes=$_POST['Company'];
$the_image = CUploadedFile::getInstance($model,'image');
if (is_object($the_image) && get_class($the_image)==='CUploadedFile')
$model->image = $the_image;
if($model->save())
if (is_object($the_image))
$model->image->saveAs(Yii::getPathOfAlias('webroot') . '/upload/' . $model->image);
$this->redirect(array('view','id'=>$model->id));
}
$this->render('update',array(
'model'=>$model,
}
And these are the rules in my model:
array('name', 'required'),
array('type, number, rating, user_id', 'numerical', 'integerOnly'=>true),
array('name, image, address, site, mail', 'length', 'max'=>1000),
array('text', 'safe'),
array('image', 'file', 'types'=>'jpg, gif, png'),
array('image', 'unsafe'),
// The following rule is used by search().
// Please remove those attributes that should not be searched.
array('id, type, name, text, address, site, mail, number, rating, user_id', 'safe', 'on'=>'search'),
Please, help me. I have no clue why it isn't working.
Try modifying your image attribute rule on the Update scenario like this:
array('image', 'file', 'types'=>'jpg, gif, png','allowEmpty' => true, 'on'=>'update'),
I found this tip here, hope it works for you.
public function uploadMultifile ($model,$attr,$path)
{
if($sfile=CUploadedFile::getInstances($model, $attr)){
foreach ($sfile as $i=>$file){
$formatName=time().$i.'.'.$file->getExtensionName();
$file->saveAs(Yii::app()->basePath .DIRECTORY_SEPARATOR.'..'. $path.$formatName);
// $model->image->saveAs(Yii::app()->basePath . '/../studentimage/' . $date . $model->image);
$ffile[$i]=$formatName;
}
return ($ffile);
}
}
public function actionCreate()
{
$model=new Subject;
// $model->date_erected = date('Y-m-d');
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['Subject']))
{
$model->attributes=$_POST['Subject'];
if($filez=$this->uploadMultifile($model,'imagea','/../images/views/'))
{
$model->documents=implode(",", $filez);
}
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
$this->render('create',array(
'model'=>$model,
));
}
Related
I would like to upload an image and save the image name in database. I can create it and everything is ok, but update has problems. If i update the $model->img (image) value will be blank in db.
This is my model rules:
array('img', 'file','types'=>'jpg, gif, png, jpeg', 'allowEmpty'=>true, 'on'=>'update'),
array('title, img', 'length', 'max'=>255, 'on'=>'insert,update'),
And this is the controller:
public function actionUpdate($id)
{
$model=$this->loadModel($id);
$_SESSION['KCFINDER']['disabled'] = false;
$_SESSION['KCFINDER']['uploadURL'] = Yii::app()->baseUrl."/../images/"; // URL for the uploads folder
$_SESSION['KCFINDER']['uploadDir'] = Yii::app()->basePath."/../../images/"; // path to the uploads folder
// $this->performAjaxValidation($model);
if(isset($_POST['News']))
{
$_POST['News']['img'] = $model->img;
$model->attributes=$_POST['News'];
$model->img = $_POST['News']['img'];
$uploadedFile=CUploadedFile::getInstance($model,'img');
if($model->save()){
if(!empty($uploadedFile))
{
$uploadedFile->saveAs(Yii::app()->basePath.'/../../images/'.$model->img);
}
}
$this->redirect(array('view','id'=>$model->id));
}
$this->render('update',array(
'model'=>$model,
));
}
Before the save i check $model->img and it has value.
So i think something wrong with save() in update.
$_POST['News']['img'] = $model->img;
Why you did it? You must remove this line.
$model->attributes=$_POST['News'];
$model->img = $_POST['News']['img'];
I want to upload a image and change the original name then save it.
Model:
public function rules()
{
return array(
array('image', 'file', 'types'=>'jpg, gif, png'),
);
}
Controller:
$model->image = CUploadedFile::getInstanceByName('image');
If i save it without any other actions it will work.
But how could i change the name of image ? I try something like below:
$model->image->name = "xxx"; //CUploadedFile.name readonly
if($model->save())
$model->images->saveAs(some_path_else.newname); //the files's new name is different from database
$model->image = "abc.jpg"; //wont save it
Is the image attribute must be an instance of CUploadedFile?
Anyone help pls
do something like this
$uploadedFile = CUploadedFile::getInstance($model, 'image');
if (!empty($uploadedFile)) {
//new name will go here
$model->image = strtotime($this->getCurrentDateTime()) . '-' .$uploadedFile;
}
//this will save the image with new name
$uploadedFile->saveAs(Yii::app()->basePath.'/../public/images/user/' . $model->image);
Thanks for your answer.
I figured it out.
CUploadedFile.name is read only , so i can't change it.
The Model need a new public attribute :
public $file;
public function rules()
{
return array(
array('file', 'file', 'types'=>'jpg, gif, png'),
array('iamge', 'length'=>'255'),
);
}
Then in the controller:
$model->file = CUploadedFile::getInstanceByName('image');
$model->file->saveAs(Yii::app()->basePath.'/../public/images/user/' . $model->image);
$model->image = $model->file->name;
It's works fine.(it's not real code)
see here
Im trying to upload images and add to db file name and now Im stuck, because it wont add entry to db.
Error in debugger is Property "EeCarTypes.foto" is not defined.
controllers relavent code:
public function actionCreate()
{
$model=new EeCarTypes;
$path = Yii::app()->basePath . '/../images/upload/cartypes';
if (!is_dir($path)) {
mkdir($path);
}
if(isset($_POST['EeCarTypes']))
{
$model->attributes=$_POST['EeCarTypes'];
$model->image=CUploadedFile::getInstance($model,'image');
if($model->save())
{
$model->image->saveAs( $path . '/adsfasdfadf' );
}
}
$this->render('create', array('model'=>$model));
}
view code:
$form = $this->beginWidget(
'CActiveForm',
array(
'id' => 'upload-form',
'enableAjaxValidation' => false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)
);
// ...
echo $form->labelEx($model, 'image');
echo $form->fileField($model, 'image');
echo $form->error($model, 'image');
// ...
echo CHtml::submitButton('Submit');
$this->endWidget();
and model code:
public $image;
/**
* #return string the associated database table name
*/
public function tableName()
{
return 'ee_car_types';
}
/**
* #return array validation rules for model attributes.
*/
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array( 'image', 'file', 'types' => 'jpg, gif, png'),
array('car_type', 'length', 'max'=>255),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('id, car_type', 'safe', 'on'=>'search'),
);
}
I think anything else is irelevent here. Please help me :)
**Replace your view code**
echo $form->fileField($model, 'image');
with
<?php echo CHtml::activeFileField($model, 'image'); ?>
**In your controller file**
if(isset($_POST['EeCarTypes']))
{
$rnd = rand(0,9999);
$model->attributes=$_POST['EeCarTypes'];
$uploadedFile=CUploadedFile::getInstance($model,'image');
$fileName = "{$rnd}-{$uploadedFile}";
$model->image = $fileName;
$model->attributes=$_POST['EeCarTypes'];
if($model->save()){
$uploadedFile->saveAs(Yii::app()->basePath.'/../images/upload/cartypes'.$fileName);
$this->redirect(array('index'));
}
}
At your model you should create a name property for the image and the field at the database. Then assign the file name to this property at your action method before you call the save(), like this:
$file = CUploadedFile::getInstance($model,'image');
$model->image_name = $file->name;
//use this if you want to save the file type but first create the image_type property
$model->image_type = $file->type;
[...]
Create an attribute with the name foto in your model EeCarTypes and look here
How can i update, some field, forexample firstname or lastname or email without doing any change on password field
My model
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('username, salt, password, firstname, lastname, email', 'required', 'on' ),
array('superuser, status', 'numerical', 'integerOnly'=>true),
array('username, password, salt', 'length', 'max'=>32),
array('firstname, lastname,image', 'length', 'max'=>80),
array('email', 'length', 'max'=>128),
array('id, username, password, salt, firstname, lastname, email, superuser, status', 'safe', 'on'=>'search'),
);
}
AND in model i have
public function beforeValidate()
{
$this->salt = '1294455567';
return parent::beforeValidate();
}
you can do like this also...
public function beforeSave()
{
if(!$this->getIsNewRecord())
unset($this->password);
return parent::beforeSave();
}
Hope it may help you..
You can use Yii scenarions. For example in your model you has next validation rules:
public function rules()
{
return array(
array('username, salt, password, firstname, lastname, email', 'required', 'on' => 'create'),
array('email, username, firstname, lastname', 'someValidationRuleOrMethod', 'on' => 'update'),
);
}
When you need to create new user, need to set validation scenario:
$model = new User('create');
//some code
$model->validate();
Or:
$model = new User();
$model->scenario = 'create';
//some code
$model->validate();
When you need update exists user - use update scenario instead create:
$model = User::model()->findByPk($someId);
$model->scenarion = 'update';
//some code
$model->validate();
Also, I found this receipt on Russian Yii blog.
UPD You can use static method to hash password, and can call it every where:
public static function hashPassword($password)
{
return CPasswordHelper::hashPassword($password);
}
Create a User model object for single user, then update by assigning new value for field:
...
$user = User::model()->find("`t`.`username` = :USER", array(':USER' => 'example.user'));
$user->firstname = 'New First Name';
$user->lastname = 'New Last Name';
$user->email = 'email#user.new';
# Now update User here
if($user->update()) {
echo 'Updated';
}
...
Hi all what i have done is here....
My controller ::
public function actionUpdate($id){
$model=$this->loadModel($id,'User');
$oldImage = $model->image;
// $old_password = $model->password;
$model->password = '';
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if(isset($_POST['User']))
{
$model->attributes=$_POST['User'];
//If image not uploaded then set old image
if(!$this->uploadImage($model)){
$model->image = $oldImage;
}
if($model->save()){
Yii::app()->user->setFlash('success', "Data Updated successfully"); // Flash Message
$this->redirect(array('admin','id'=>$model->user_id));
}
}
$this->render('update',array(
'model'=>$model,
));
}
My Model
public function rules()
{
// NOTE: you should only define rules for those attributes that
// will receive user inputs.
return array(
array('first_name, last_name, password, email,repeat_password', 'required',"on"=>'create'),
array('first_name, last_name, email', 'required',"on"=>'update'),
array('first_name, last_name', 'length', 'max'=>100),
array('password', 'length', 'max'=>30,'min'=>6),
array('repeat_password', 'compare', 'compareAttribute' => 'password', 'message'=>'Confirm Password must be same as password'),
array('email', 'length', 'max'=>50),
array('email', 'unique'),
//array('image', 'file', 'types'=>'jpg, gif, png'),
array('image', 'safe'),
// The following rule is used by search().
// #todo Please remove those attributes that should not be searched.
array('user_id, first_name, last_name, email', 'safe', 'on'=>'search'),
);
}
public function beforeSave(){
if(!empty($this->password))
$this->password = md5($this->password);
else
unset($this->password);
return parent::beforeSave();
}
My View ::
<?php
// If user update profile or update data then don't show password
if( ((#Yii::app()->request->getParam('act')!=="profile") && empty($_GET["id"])) || #$_GET["act"]=='changepwd' )
{
?>
<div class="row">
<?php echo $form->labelEx($model,'password'); ?>
<?php echo $form->passwordField($model,'password',array('maxlength'=>20,'minlength'=>6)); ?>
<?php echo $form->error($model,'password'); ?>
</div>
<div class="row"><!-- Confirm password -->
<?php echo $form->labelEx($model,'Confirm Password'); ?>
<?php echo $form->passwordField($model,'repeat_password',array('maxlength'=>20,'minlength'=>6)); ?>
<?php echo $form->error($model,'repeat_password'); ?>
</div>
<?php } ?>
public function actionUpdate($id) {
$model=$this->loadModel($id);
if(isset($_POST['User']))
{
$password = $model->password;
$model->attributes=$_POST['User'];
if($password === $model->password) {
$model->password = $password;
} else {
$model->password = md5(SALT . $model->password);
}
if($model->save())
$this->redirect(array('view','id'=>$model->id));
}
$this->render('update',array(
'model'=>$model,
));
}
When a user registers for my application the following validation rules are called before submission:
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('club, email, firstName, lastName, level, password, telephone', 'length', 'max'=>45),
array('passwordConfirm', 'compare', 'compareAttribute'=>'password', 'on'=>'register'),
array('email', 'isUniqueEmailAddress'),
);
}
The first three validation rules complete successfully, but the fourth (a custom validation method) does not. It should call the function 'isUniqueEmailAddress' and perform the following:
/*
* Returns true if there doesn't exist a user in the database with the submitted email
*/
public function isUniqueEmailAddress($attribute, $params)
{
//if (User::model()->find('email=:email', array(':email'=>$this->email)) !== null)
//{
$this->addError('email', 'Email account already exists');
//}
}
As you can see, I've even commented out all logic to simply ensure that a validation error is sent back to the registration form, but no errors are returned on validation(). I've read Yii's Documentation and scoured the forums but cannot understand why my custom validation method is not being called?
I ran into this problem when attempting to set a flash message in a controller after calling $model->save(). It was a code formatting issue which caused a logic error.
For example, in the model I had something like this:
public function validateNumItems($attribute, $params) {
$this->addError($attribute, 'Validate Items Failed');
}
In theory this should have caused the form submission to fail every time for debugging purposes. But it never did.
My controller's update action looked like this:
public function actionUpdate($id) {
$model = $this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['Collection']))
{
$model->attributes = $_POST['Collection'];
if ($model->save())
Yii::app()->user->setFlash('success', "Data saved!");
$this->redirect(array('index'));
}
$this->render('update', array('model' => $model, ));
}
The missing brackets around the $model->save() test created by Gii caused a logic error when I added new lines. Putting the brackets in place fixed things.
public function actionUpdate($id) {
$model = $this->loadModel($id);
// Uncomment the following line if AJAX validation is needed
// $this->performAjaxValidation($model);
if (isset($_POST['Collection'])) {
$model->attributes = $_POST['Collection'];
if ($model->save()) {
Yii::app()->user->setFlash('success', "Data saved!");
$this->redirect(array('index'));
}
}
$this->render('update', array('model' => $model, ));
}
array('email', 'exist')
like this.
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('club, email, firstName, lastName, level, password, telephone', 'length', 'max'=>45),
array('passwordConfirm', 'compare', 'compareAttribute'=>'password', 'on'=>'register'),
array('email', 'exist')
);
}
I commented with some possible reasons your code isn't working (it looks right), but in this case you can just use the Unique validator.
array('email', 'unique') will do it.
try this, it's working fine -
public function rules()
{
return array(
array('email, firstName, lastName, password, passwordConfirm, telephone', 'required'),
array('email', 'email','message'=>"The email isn't correct"),
array('email', 'uniqueEmail'),
);
}
your custom function, write into same model -
public function uniqueEmail($attribute, $params)
{
if($user = User::model()->exists('email=:email',array(':email'=>$this->email)))
$this->addError($attribute, 'Email already exists!');
}