Ya No Se Utilizar Update

Hola gente:

Llevo unas cuantas horas dando vueltas y alucinando, y ya no se que mas hacer, por lo que os pido ayuda. Podeis decirme en que me estoy equivocando para que no me funcione algo tan sencillo como un UPDATE para incrementar un campo?

Tengo una funcion:


public static function cargaBanner($tipoBanner=0){

		$criteria=new CDbCriteria();

		if ($tipoBanner>0){

			$criteria->addCondition('intTipoB='.$tipoBanner);

		}

		$criteria->addCondition('IFNULL(fFechaInicio,0)<CURDATE()');

		$criteria->addCondition('IFNULL(fFechaFin,CURDATE()+1)>CURDATE() ');

		$criteria->order='intEstaPres ASC';

		$criteria->limit=1;

		$banner= CbControlbanner::model()->find($criteria);

		$banner->intEstaPres=$banner->intEstaPres+1;

		fb('id-'.$banner->id_controlBanner.'conta-'.$banner->intEstaPres); //mensaje

		$banner->save();

		return $bann;

	}

Le doy un numero, me recupera un registro, incrementa el contador (intEstaPres), lo guarda y me devuelve datos…

Bueno, el problema es que me incrementa el valor en TODOS los registros que cumplian la condicion de ‘criteria’

Observad, que en criteria he especificado LIMIT 1, y que utilizo ->find(), por lo que solo deberia leer 1, por otra parte, esta funcion no se vuelve a llamar ya que lo estoy controlando en el log de firefox…COMO LO HACE!!!

Podrías revisar lo q se pasa en criteria en Firebug y postearlo?

O haz:





public static function cargaBanner($tipoBanner=0){

                $criteria=new CDbCriteria();

                if ($tipoBanner>0){

                        $criteria->addCondition('intTipoB='.$tipoBanner);

                }

.....

var_dump($tipoBanner);

exit;

.....



Y revisa lo que vale




$tipoBanner



Entiendo q lo que te está pasando es q




$tipoBanner



siempre vale cero.

Un saludo.

Gracias por responder @lagogz.He utilizado CvarDump por comodidad y aqui esta el resultado:


[07:04:37.902][trace][vardump] 2

in D:\Proyectos\sexoyred\web\commonend\helpers\shortcuts.php (6)

in D:\Proyectos\sexoyred\web\commonend\models\CbControlbanner.php (24)

in D:\Proyectos\sexoyred\web\frontend\views\layouts\grid_bs.php (16)

El valor 2, es correcto, pero de cualquier manera, el ‘find’ lo hago con limite 1, en CActiveRecord solo puede haber un registro, luego al hacer el ‘save()’ solo deberia modificar un registro… y me modifica todo los de tipo 2

Si quieres otra locura, intente esquivar el problema haciendo:


Yii::app()->db->createCommand($sql)->query();

con $sql=


[07:04:37.991][trace][vardump] 'UPDATE  cb_controlbanner SET intEstaPres=IFNULL(intEstaPres,0)+1 WHERE id_controlBanner=6'

y me sigue modificando todos los de tipo 2…

ya no se que mas hacer

Buenas de nuevo. Esto q cito tiene q actualizarte todos los registros que tengan id_controlBanner igual a 6, sí o sí. No hay otra!!!!!

El método find, en principio y según la ayuda de Yii:




Finds a single active record with the specified condition.



Aunque no pusieses Limit (lo pones para recuperar el registro q tú quieres,perfecto), siempre devolverá un valor. Por lo que en principio debería de actualizarte sólo un registro.

Podrías escribir la estructura de tu tabla indicando PKs y FKs?

Haz:




$banner= CbControlbanner::model()->find($criteria);


var_dump($banner->attributes);



Para ver que es lo que te recupera.

Prueba a cambiar find por findAll.

No, si el problema es que la recuperacion la hace perfecta


array

  'id_controlBanner' => string '13' (length=2)

  'sCodigoCli' => string '2013030101' (length=10)

  'sNombreCliente' => string 'wamcash' (length=7)

  'sDirImagen' => ''

  'sTipoImagen' => string 'iframe' (length=6)

  'sDirDestino' => null

  'intTipoB' => string '2' (length=1)

  'intMostrar' => string '1' (length=1)

  'intCondicion' => null

  'sCondicion' => null

  'fFechaInicio' => null

  'fFechaFin' => null

  'intEstaPres' => string '133' (length=3)

  'intEstaClick' => string '0' (length=1)

  'intControl' => null

El problema es la actualizacion; yo quiero sumar uno al contador de presentaciones (intEstaClick), pero la suma me la hace a varios registros!

Tengo la Primary en id_controlBanner, y tengo Foreig_keys en intTipoB, intMostrar y intCondicion.

Observa el segundo ejemplo que mando, (conuna instruccion UPDATE) que funciona bien cuando se ejecuta desde PHPMyAdmin, y provoca esa actualizacion erronea cuando me apoyo en Yii

Nota: id_controlBanner es primary y como consecuencia unique por lo que solo hay un registro que pueda cumplir la condicion

Podrías mostrar las rules de tu modelo y tu actionUpdate?

Es raro q si te carga el registro adecuado no te actualize correctamente.

Debería ser problema del modelo, entiendo yo.

Envía eso y lo reviso.

Un saludo.

No se en que influyen las rule, pero aqui estan:


public function rules() {

        return array(

            array('intTipoB, intMostrar, intCondicion', 'numerical', 'integerOnly'=>true),

            array('sCodigoCli', 'length', 'max'=>20),

            array('sNombreCliente', 'length', 'max'=>200),

            array('sTipoImagen, intControl', 'length', 'max'=><img src='http://www.yiiframework.com/forum/public/style_emoticons/default/cool.gif' class='bbc_emoticon' alt='8)' />,

            array('intEstaPres, intEstaClick', 'length', 'max'=>13),

            array('sDirImagen, sDirDestino, sCondicion, fFechaInicio, fFechaFin', 'safe'),

            array('sCodigoCli, sNombreCliente, sDirImagen, sTipoImagen, sDirDestino, intTipoB, intMostrar, intCondicion, sCondicion, fFechaInicio, fFechaFin, intEstaPres, intEstaClick, intControl', 'default', 'setOnEmpty' => true, 'value' => null),

            array('id_controlBanner, sCodigoCli, sNombreCliente, sDirImagen, sTipoImagen, sDirDestino, intTipoB, intMostrar, intCondicion, sCondicion, fFechaInicio, fFechaFin, intEstaPres, intEstaClick, intControl', 'safe', 'on'=>'search'),

        );

    }



Respecto al actionUpdate, no juega ya que estoy invocando una funcion, desde una vista.

Esta es la llamada en Frontend/views/layouts/grid_bs.php


<?php echo CbControlbanner::cargaBanner(2);?>

Este el el codigo en CbControlbanner


public static function cargaBanner($tipoBanner=0){

		$criteria=new CDbCriteria();

		if ($tipoBanner>0){

			$criteria->addCondition('intTipoB='.$tipoBanner);

		}

		fb($tipoBanner);

		$criteria->addCondition('IFNULL(fFechaInicio,0)<CURDATE()');

		$criteria->addCondition('IFNULL(fFechaFin,CURDATE()+1)>CURDATE() ');

		$criteria->order='intEstaPres ASC';

		$criteria->limit=1;

		$banner= CbControlbanner::model()->find($criteria);

//		var_dump($banner->attributes);

//		$banner->intEstaPres=$banner->intEstaPres+1;

//		fb('id-'.$banner->id_controlBanner.'conta-'.$banner->intEstaPres);

//		$banner->save();

//		exit;

		if ($banner!=null){

			CbControlbanner::cuentaPresentacion($banner->id_controlBanner);

			if ($banner->sTipoImagen==NULL)

				$bann=montaEnlace(montaImagen($banner->sDirImagen),enlaceBanner($banner->id_controlBanner,""));

			else {

				fb($banner->sTipoImagen);

				switch ($banner->sTipoImagen){

					case 'iframe':

						$bann=$banner->sDirImagen;

						break;

					default:

						$bann=montaEnlace(montaImagen($banner->sDirImagen),enlaceBanner($banner->id_controlBanner,""));

				}				

			} 

				fb($bann);

		}

			else 

				$bann="";

		return $bann;

	}

	

	public static function cuentaPresentacion($id){

		fb('cientaP-'.$id);

		incrementaRegistro('cb_controlbanner','intEstaPres','id_controlBanner='.$id);		

	}

	public static function cuentaClick($id){

		incrementaRegistro(CbControlbanner::tablename(),'intEstaClick','id_controlBanner='.$id);

	}

Y funciona todo, pero en la base de datos, me queda el campo intEstaPres con el mismo valor, para todos los registros que hubieran cumplido el criterio inicial.

Por ultimo, en funciones tengo:


function incrementaRegistro($tablename,$campo,$condicion){

	if ($tablename!="" && $campo!="" && $condicion!=""){

		if (is_numeric($condicion)){

			$condicion='id='.$condicion;

		}

		$sql='UPDATE  '.$tablename.' SET '.$campo.'=IFNULL('.$campo.',0)+1 WHERE '.$condicion;

		fb($sql);

		Yii::app()->db->createCommand($sql)->query();

		return;

	}

	else 

		fb('Error: falta algo. Tabla='.$tablename." campo=".$campo." id=".$id);

}

y la orden que se genera, es


'UPDATE  cb_controlbanner SET intEstaPres=IFNULL(intEstaPres,0)+1 WHERE id_controlBanner=6'

Yo ya no se que mas hacer

Nota: fb() es una funcion que me manda mensajes a la consola de firefox

Buenas otra vez y perdona por tardar tanto en responder, pero tengo mucho trabajo.

La verdad es q no veo nada raro.

Prueba a hacer esto en incrementaRegistro:




function incrementaRegistro($tablename,$campo,$condicion){

        if ($tablename!="" && $campo!="" && $condicion!=""){

                //if (is_numeric($condicion)){

                //        $condicion='id='.$condicion;

                //}

                //$sql='UPDATE  '.$tablename.' SET '.$campo.'=IFNULL('.$campo.',0)+1 WHERE '.$condicion;

                //fb($sql);

                //Yii::app()->db->createCommand($sql)->query();

                $model=CbControlbanner::model()->findByPk('clave primaria');  

                //O findByAttributes (aquí meterías en $condicion), o la 

                //función find q quieras.

                $model->intEstaPres='valor deseado';

                $model->save();


                return;

        }

        else 

                fb('Error: falta algo. Tabla='.$tablename." campo=".$campo." id=".$id);

}

A ver si de esta forma, recogiendo sólo los datos de la fila que quieres actualizar en un modelo te lo hace bien.

Un saludo.

Bien!!!!!!!!!!!!

Siguiendo tu idea:


public static function cuentaPresentacion($id){

		fb('cientaP-'.$id);

		$reg=CbControlbanner::model()->findByPk($id);

		if ($reg!=null){

			$reg->intEstaPres++;

			$reg->save();

		}	

	}

ha funcionado.

No se porque no funcionaba antes, ni porque no funcionaba cuando se hacia dentro de la misma recuperacion, pero…

Ya he empleado demasiado tiempo en esto, con lo que lo doy por resuelto.

Gracias por la ayuda @lagogz

Sabeis como puedo editar el titulo para marcarlo como solucionado?

Pues me alegro.

Un saludo.