miércoles, 19 de junio de 2013

YII - Adjuntar (subir) fichero a través de un formulario

Algo que necesité al trabajar con YII, fue el tener que adjuntar un fichero en un formulario, ya que, era un sistema en el cual debía adjuntar una fotocopia (imagen) de su carnet de identidad (también conocido como DNI).

Para lograr esto, debemos abrir nuestro proyecto, y haber creado el CRUD, con esto, se nos genera “/protected/views/<nombre-elegido>/_form.php”. Dentro de este archivo veremos un segmento como el siguiente:


beginWidget('CActiveForm', array(
 'id'=>'empleados-form',
 'enableAjaxValidation'=>false,
)); ?>

Aquí simplemente debemos agregar una línea, quedan de la siguiente forma

beginWidget('CActiveForm', array(
 'id'=>'empleados-form',
 'enableAjaxValidation'=>false,
        'htmlOptions'=>array('enctype'=>'multipart/form-data'),
)); ?>

Luego, dentro del mismo fichero, debemos agregar la siguiente línea (la ubicación es a gusto).



Finalmente, nos toca la parte entretenida, y es que vamos a modificar el controlador. Aquí debemos trabajar con las funciones “actionCreate” y “actionUpdate”. En el ejemplo trabajaré con “actionCreate”, pero se debe agregar lo mismo en “actionUpdate”. Nuestro método viene por default de la siguiente forma.

public function actionCreate($id)
{
$model=$this->loadModel($id);

if(isset($_POST['Cliente']))
{
 $model->attributes=$_POST['Cliente'];
 
 if($model->save()){
     $this->redirect(array('view','id'=>$model->idcliente));
 }
}

$this->render('update',array(
 'model'=>$model,
));
}

He quitado una líneas que vienen comentadas. Debemos darnos cuenta que en este caso el nombre del modelo es “Cliente”, y su id  y primary key, es idcliente.

Lo que debemos hacer es agregar lo siguiente:

$model->fotocopiacarnet=CUploadedFile::getInstance($model,'image');
$model->fotocopiacarnet->saveAs('/path/' . CuploadedFile::getInstance($model,'image')->name);

En donde: 
  • fotocopiacarnet es el campo (columna) de la base de datos, donde guardará el path del carnet.
  • /path/ es la ruta donde dejamos las imagenes, por ejemplo, en mi caso es: /home/nicolas/public_html/proyectoYII/images/
En resumen, nos quedaría algo parecido a esto:

public function actionCreate()
{
 $model=new Cliente;

 if(isset($_POST['Cliente']))
 {
  $model->attributes=$_POST['Cliente'];
  $model->fotocopiacarnet=CUploadedFile::getInstance($model,'image');
   
  if($model->save()){
   $model->fotocopiacarnet->saveAs('/proyectoYII/images/' . CUploadedFile::getInstance($model,'image')->name);
  
   $this->redirect(array('view','id'=>$model->idcliente));
  }
 }

 $this->render('create',array(
  'model'=>$model,
 ));
}

Debemos tener en cuenta que “if($model->save())” por defecto no viene con { }, esto es debido a que por regla, cuando el if tiene sólo una línea de ejecución, no son necesario, pero como ahora tienen 2 líneas, es necesario hacerlo.

12 comentarios:

Gracias hermano! sabrás como crear la miniatura de la imagen y renombrar las imágenes?

Estimado,

En mi caso, cuando utilicé esta solución, mostraba la imagen a través del view.php. Para esto, en el CDetailView agregaba algo como lo siguiente:

array(
'label'=>'Carnet',
'type'=>'raw',
'value'=> CHtml::image(Yii::app()->baseUrl.'/images/fotocarnet/'.$model->carnet),
),


Saludos

hola disculpa soy nuevo en esto de yii me puedes ayudar con algun proyecto q tengas hecho de subir fotos de anta mano te agradesco gracias

puse en proyecto los pasos que tu indicas en el blog pongo este codigo en el campo de foto de mi tabla fileField($model,'foto'); ?> para q me salga el boton elegir imagen me elige la imagen me sale el nombre a lo q preciono el boton create me sale q no e seleccionado ningun archivo en q lugares debo modificar mi aplicacion para visializar la imagen al subir y visualizar la lista de imagenes subidas esto es lo q no se en que parte modificar es que soy nuevo en esto de php yii

en tu proyecto, el campo se llama foto?

Es importante agregar: 'htmlOptions' => array('enctype' => 'multipart/form-data'),
para que quede algo como lo siguiente


beginWidget('CActiveForm',array(
'id'=>'item-form',
'enableAjaxValidation'=>false,
'htmlOptions' => array('enctype' => 'multipart/form-data'),
)); ?>


me comentas

Si ya le puse gracias disculpa una pregunta en que parte de la aplicacion se pone el codigo para la vista de la imagen subida de la foto

si se llama foto el campo o disculpa q te moleste me podrias ayudar con un video tutorial paso a paso por fis si no es mucha molestia

Hola, disculpa pero no tengo tiempo para poder hacer un vídeo-tutorial, pero su te puedo orientar en todo lo necesario.

Respecto a tu pregunta, necesitas saber, el código para subir la foto? o para mostrarla?

Si es para subir, es el form con el siguiente código



pero como te comenté anteriormente, es necesario que en el widget esté lo siguiente:

'htmlOptions'=>array('enctype'=>'multipart/form-data'),


Saludos

Qué tal, me parece muy bueno el tutorial, pero tengo una duda:

Cuando quiero subir imágenes, pero en mi db no tengo ningún campo relacionado a la misma (como en tu ejemplo, $model->fotocopiacarnet) ¿cómo se puede hacer?

Hola, soy el dueño del blog, la verdad es que en Yii nunca subí sin guardar algo en la base (nombre, path, etc), por lo que, no te podría decir "esta es la solución", no obstante, te puedo recomendar los siguientes links:

http://php.net/manual/es/features.file-upload.post-method.php

http://www.w3schools.com/php/php_file_upload.asp

Saludos!

buenas hago todos los pasos como los publicas. Pero me sale este error al cargar la imagen.

move_uploaded_file(): The second argument to copy() function cannot be a directory

Publicar un comentario