Yii Framework en Español - Foro

Versión completa: Como subir una imagen, y guardar el path en la base de datos
Actualmente estas viendo una versión simplificada de nuestro contenido. Ver la versión completa con el formato correcto.

Con esto podremos subir una imagen a una carpeta de nuestro sitio y guardar el path en la base datos, incluyendo la posibilidad de realizar una actualizacion.-


Para esto deberemos modificar la Vista, el Modelo y el Controlador.


Vista:
archivo _form.php


Código PHP:
..
//array de opciones del form...
'htmlOptions' => array(
        
'enctype' => 'multipart/form-data',
    ),
...
..
//Otros Elementos
..
..
<
div class="row">
        <?
php echo $form->labelEx($model,'imagen'); ?>
        <?php echo CHtml::activeFileField($model'imagen'); ?>  //con esto levantamos la imagen
        <?php echo $form->error($model,'imagen'); ?>
</div>
<?php if($model->isNewRecord!='1'){ ?>
<div class="row">
     <?php echo CHtml::image(Yii::app()->request->baseUrl.'/banner/'.$model->imagen,"imagen",array("width"=>200)); ?>  // La Imagen se muestra aquí si la página es la página de actualización
</div>
..
..
Otros elementos
..
.. 


Modelo:
solo es necesario agregar una linea en el metodo rules() en el Modelo, de la siguiente manera:


Código PHP:
array('imagen''file','types'=>'jpg, gif, png''allowEmpty'=>true'on'=>'update'), 
esto permitirá campo vacío cuando la página es la actualización


para todas las demás normas que le tiene que dar un escenario para insertar y actualizar, según la regla se aplicará tanto en la página (Insert y Update)


Código PHP:
array('titulo, imagen''length''max'=>255'on'=>'insert,update'), 


.. .. ahora viene la parte principal,


Controlador:
En el controlador Create subiremos la imagen con nombre aleatorio y guardamos la entrada en la base de datos.-


Código PHP:
public function actionCreate()
    {
        
$model=new Banner;  // este es el modelo relacionado a la tabla
        
if(isset($_POST['Banner']))
        {
            
$rnd rand(0,9999);  // Generamos un numero aleatorio entre 0-9999
            
$model->attributes=$_POST['Banner'];
 
            
$uploadedFile=CUploadedFile::getInstance($model,'imagen');
            
$fileName "{$rnd}-{$uploadedFile}";  // numero aleatorio  + nombre de archivo
            
$model->imagen $fileName;
 
            if(
$model->save())
            {
                
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);  // la imagen se subirá a la carpeta raiz /banner/
                
$this->redirect(array('admin'));
            }
        }
        
$this->render('create',array(
            
'model'=>$model,
        ));
    } 


Ahora viene la parte de la accion de actualizar


Código PHP:
public function actionUpdate($id)
    {
        
$model=$this->loadModel($id);
 
        if(isset(
$_POST['Banner']))
        {
            
$_POST['Banner']['imagen'] = $model->imagen;
            
$model->attributes=$_POST['Banner'];
 
            
$uploadedFile=CUploadedFile::getInstance($model,'imagen');
 
            if(
$model->save())
            {
                if(!empty(
$uploadedFile))  // checkeamos si el archivo subido esta seteado o no
                
{
                    
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$model->imagen);
                }
                
$this->redirect(array('admin'));
            }
 
            if(
$model->save())
                
$this->redirect(array('admin'));
        }
 
        
$this->render('update',array(
            
'model'=>$model,
        ));
    } 


En este ejemplo subimos una imagen a una carpeta especifica e introducimos la entrada en la base de datos. En la actualizacion sobreescribimos la imagen en la carpeta y actualizamos los datos.-


Archivo original desde aqui

hola una pregunta, como puedo adaptar el codigo del controller a un controller que esta ocupando cjuidialog?

(23-08-2012 08:31 AM)oscarvogel escribió: [ -> ]Con esto podremos subir una imagen a una carpeta de nuestro sitio y guardar el path en la base datos, incluyendo la posibilidad de realizar una actualizacion.-

Para esto deberemos modificar la Vista, el Modelo y el Controlador.

Vista:
archivo _form.php

Código PHP:
..
//array de opciones del form...
'htmlOptions' => array(
        
'enctype' => 'multipart/form-data',
    ),
...
..
//Otros Elementos
..
..
<
div class="row">
        <?
php echo $form->labelEx($model,'imagen'); ?>
        <?php echo CHtml::activeFileField($model'imagen'); ?>  //con esto levantamos la imagen
        <?php echo $form->error($model,'imagen'); ?>
</div>
<?php if($model->isNewRecord!='1'){ ?>
<div class="row">
     <?php echo CHtml::image(Yii::app()->request->baseUrl.'/banner/'.$model->imagen,"imagen",array("width"=>200)); ?>  // La Imagen se muestra aquí si la página es la página de actualización
</div>
..
..
Otros elementos
..
.. 

Modelo:
solo es necesario agregar una linea en el metodo rules() en el Modelo, de la siguiente manera:

Código PHP:
array('imagen''file','types'=>'jpg, gif, png''allowEmpty'=>true'on'=>'update'), 
esto permitirá campo vacío cuando la página es la actualización

para todas las demás normas que le tiene que dar un escenario para insertar y actualizar, según la regla se aplicará tanto en la página (Insert y Update)

Código PHP:
array('titulo, imagen''length''max'=>255'on'=>'insert,update'), 

.. .. ahora viene la parte principal,

Controlador:
En el controlador Create subiremos la imagen con nombre aleatorio y guardamos la entrada en la base de datos.-

Código PHP:
public function actionCreate()
    {
        
$model=new Banner;  // este es el modelo relacionado a la tabla
        
if(isset($_POST['Banner']))
        {
            
$rnd rand(0,9999);  // Generamos un numero aleatorio entre 0-9999
            
$model->attributes=$_POST['Banner'];
 
            
$uploadedFile=CUploadedFile::getInstance($model,'imagen');
            
$fileName "{$rnd}-{$uploadedFile}";  // numero aleatorio  + nombre de archivo
            
$model->imagen $fileName;
 
            if(
$model->save())
            {
                
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$fileName);  // la imagen se subirá a la carpeta raiz /banner/
                
$this->redirect(array('admin'));
            }
        }
        
$this->render('create',array(
            
'model'=>$model,
        ));
    } 

Ahora viene la parte de la accion de actualizar

Código PHP:
public function actionUpdate($id)
    {
        
$model=$this->loadModel($id);
 
        if(isset(
$_POST['Banner']))
        {
            
$_POST['Banner']['imagen'] = $model->imagen;
            
$model->attributes=$_POST['Banner'];
 
            
$uploadedFile=CUploadedFile::getInstance($model,'imagen');
 
            if(
$model->save())
            {
                if(!empty(
$uploadedFile))  // checkeamos si el archivo subido esta seteado o no
                
{
                    
$uploadedFile->saveAs(Yii::app()->basePath.'/../banner/'.$model->imagen);
                }
                
$this->redirect(array('admin'));
            }
 
            if(
$model->save())
                
$this->redirect(array('admin'));
        }
 
        
$this->render('update',array(
            
'model'=>$model,
        ));
    } 

En este ejemplo subimos una imagen a una carpeta especifica e introducimos la entrada en la base de datos. En la actualizacion sobreescribimos la imagen en la carpeta y actualizamos los datos.-

Archivo original desde aqui

Tengo una pregunta y como se borran los archivos del servidor? de la base de datos va de lujo pero fisicamente las imagenes aun siguen en el server XD
gracias de antemano!!

Muchas gracias por la información, me queda una duda si, lo he intentado modificar según como estoy trabajando yo, y está funcionando okey, el problema que tengo es que si subo por primera vez una imagen .png, después puedo actualizar sólo a .png, ya que si por ejemplo, subo un .jpg, el archivo se sube al servidor y ruta del servidor, pero en la base de datos no se actualiza el valor a .jpg


La función crear y actualizar que tengo son las siguientes:


Crear:


Código PHP:
public function actionCreate()
    {
            
$model=new Cliente;  // este es el modelo relacionado a la tabla
            
            
if(isset($_POST['Cliente']))
            {
                
$model->attributes=$_POST['Cliente'];
                
$uploadedFile=CUploadedFile::getInstance($model,'carnet'); //Captura el fichero subido
                
$extensionFile=$uploadedFile->getExtensionName(); //Obtener la extensión del fichero subido
                
$fileName $model->rut//Nombre con el que se guardará el fichero
                
$model->carnet $fileName.".".$extensionFile//Indicar como se guarda en la base de datos
 
                
if($model->save())
                {
                    
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/images/carnet/'.$fileName.".".$extensionFile0777); //Guardando físicamente el fichero en el servidor
                    
$this->redirect(array('admin'));
                    
//$this->redirect(array('view','id'=>$model->idcliente));
                
}
            }
            
            
$this->render('create',array(
                
'model'=>$model,
            ));
    } 


Actualizar:


Código PHP:
public function actionUpdate($id)
    {
            
$model=$this->loadModel($id);
 
            if(isset(
$_POST['Cliente']))
            {
                
$_POST['Cliente']['carnet'] = $model->carnet;
                
$model->attributes=$_POST['Cliente'];
 
                
$uploadedFile=CUploadedFile::getInstance($model,'carnet');
 
                if(
$model->save())
                {
                    if(!empty(
$uploadedFile))  // checkeamos si el archivo subido esta seteado o no
                    
{
                        
/*
                         * extensionFile y fileName van dentro de la validación,
                         * debido a que son necesarios sólo si $uploadedFile no es vacío
                         */
                        
$fileName $model->rut//Nombre con el que se guardará el fichero
                        
$extensionFile=$uploadedFile->getExtensionName(); //Obtener la extensión del fichero subido
                        
$model->carnet $fileName.".".$extensionFile;
                        
                        
$uploadedFile->saveAs(Yii::getPathOfAlias('webroot').'/images/carnet/'.$fileName.".".$extensionFile0777);
                    }
                    
                    
$this->redirect(array('admin'));
                }
 
                if(
$model->save())
                    
$this->redirect(array('admin'));
            }
 
            
$this->render('update',array(
                
'model'=>$model,
            ));
    } 


Si me pudieras orientar te lo gradecería


Saludos

Hola nkdos, hace algún tiempo tuve el mismo problema de que al actualizar algún archivo (pdf, doc, xls, jpg, png, etc) por alguno con otra extensión se modificaba en el servidor, pero no en la BDD, use el mismo código del ejemplo, modificando algunas cosas del método Update y hasta ahora me funciona muy bien.
Por lo que veo tu obtienes la extensión del archivo, la verdad en mi caso no me resulto necesario ya que lo reconocía automáticamente. De todas maneras esto es lo que ha funcionado para mi:


Código PHP:
    public function actionCreate()
    {
        
$model=new Noticias;

        
// Uncomment the following line if AJAX validation is needed
        // $this->performAjaxValidation($model);

        
if(isset($_POST['Noticias']))
        {
            
$rnd rand(0,9999);  // Generamos un numero aleatorio entre 0-9999
            
$model->attributes=$_POST['Noticias'];

            
$subiendoImagen=CUploadedFile::getInstance($model,'imagen');
            
$imgNombre "{$rnd}-{$subiendoImagen}";  // numero aleatorio  + nombre de archivo
            
$model->imagen $imgNombre;


            if(
$model->save()){
                
$subiendoImagen->saveAs(Yii::app()->basePath.'/../images/noticias/'.$imgNombre);
                
$this->redirect(array('view','id'=>$model->id_noticia));
            }
        }
        
$this->render('create',array(
            
'model'=>$model,
        ));
    } 


Código PHP:
    public function actionUpdate($id)
    {
        
$model=$this->loadModel($id);

        if(isset(
$_POST['Noticias']))
        {
            
$rnd rand(0,9999);  // Generamos un numero aleatorio entre 0-9999
            
$_POST['Noticias']['imagen'] = $model->imagen;
            
$model->attributes=$_POST['Noticias'];

            
$subiendoImagen=CUploadedFile::getInstance($model,'imagen');
            
$imgNombre "{$rnd}-{$subiendoImagen}";  // numero aleatorio  + nombre de archivo
            
$model->imagen $imgNombre;

            if(
$model->save()){
                if(!empty(
$subiendoImagen)){
                    
$subiendoImagen->saveAs(Yii::app()->basePath.'/../images/noticias/'.$imgNombre);
                } 
                
$this->redirect(array('view','id'=>$model->id_noticia));
            }
        }
        
$this->render('update',array(
            
'model'=>$model,
        ));
    } 


De paso, para borrar los archivos del servidor lo conseguí haciendo lo siguiente, (seguro no es la mejor forma pero funciona)


Código PHP:
    public function actionDelete($id)
    {
        
$model $this->loadModel($id);
        
unlink(Yii::app()->basePath.'/../images/noticias/'.$model->imagen);
        
$this->loadModel($id)->delete();

        
// if AJAX request (triggered by deletion via admin grid view), we should not redirect the browser
        
if(!isset($_GET['ajax']))
            
$this->redirect(isset($_POST['returnUrl']) ? $_POST['returnUrl'] : array('index'));
    } 

hola cleimak, tengo una duda, al momento de realizar la actualizacion de los datos del formulario, como le puedo hacer para que, si no quiero actualizar la imagen que subi al momento de crear el registro, dicha imagen no me la borre pero si m actualice la informacion de ese formulario??

URLs de referencia