Problema Con 'copia' Degli Attributi

Ho la variabile $a che è di tipo MioOggetto

Devo copiarlo dentro una variaible $b




$a->loadModel($a_id);

$b = new MioOggetto;

$b->attributes = $a->attributes;



C’è un problema




[warning] [application] Failed to set unsafe attribute "id" of "MioOggetto".



Va tutto a buon fine, ma mi sporco l’application.log e io lo pretendo pulito in produzione

Ho controllato le rules e IN NESSUNA di esse compare il campo id.

Qual cosa basilare di Yii mi sfugge dopo ben 8 mesi di uso full-time?

Permettimi di correggere quello che hai scritto

in

A me sembra che tu voglia clonare un oggetto, ed il modo di clonare oggetti in php è:




$obj = new MiaClasse();

$obj->password = "asdsadas";

$obj->username = "sensorario"


$obj2 = clone $obj;



Hai provato a mettere una rule dentro rules() del tipo


array('id', 'safe')

Probabilmente quel messaggio di warning ti viene dato perchè ID è settato come primary key della tabella.errore

@Leonardo Rossi: benvenuto tra noi !

  1. Si, id è la chiave primaria, ma

  2. dato che dopo la copia devo salvare il record, NON posso ovviamente portarmi a dietro come safe l’attributo id.

La domanda rimane: come mai cerca di settare anche l’id durante l’attribuzione massiva dei valori ?

Questo è il codice della setAttributes, che viene eseguito automaticamente usandola come

$model->attributes = $altro_model->attributes;

Guida ufficiale




public function setAttributes($values,$safeOnly=true)

{

    if(!is_array($values))

        return;

    $attributes=array_flip($safeOnly ? $this->getSafeAttributeNames() : $this->attributeNames());

    foreach($values as $name=>$value)

    {

        if(isset($attributes[$name]))

            $this->$name=$value;

        elseif($safeOnly)

            $this->onUnsafeAttribute($name,$value);

    }

}



quello che segue invece è il codice della getSafeAttributeNames




public function getSafeAttributeNames()

{

    $attributes=array();

    $unsafe=array();

    foreach($this->getValidators() as $validator)

    {

        if(!$validator->safe)

        {

            foreach($validator->attributes as $name)

                $unsafe[]=$name;

        }

        else

        {

            foreach($validator->attributes as $name)

                $attributes[$name]=true;

        }

    }


    foreach($unsafe as $name)

        unset($attributes[$name]);

    return array_keys($attributes);

}



Da questo capisco il problema è semplicemente che nell’espressione




$model_a->attributes = $model_b->attributes



nella parte DESTRA dell’espressione,tra gli attributes, c’è già anche ‘id’, cosa che non mi aspettavo.

Quindi facendo il ciclo tra tutti gli attributes di B da settare in A, trova id, vede che non è safe, quindi segnala il warning (e non lo setta, come corretto e come voluto).

… beh, alla fine ho capito …

Quindi la soluzione Yii-compliant per clonare un record è:




        $model = $this->loadModel($model_id_to_clone);

        $model->isNewRecord = true;

        $model->unsetAttributes(array("id"));

        $model->save();



Ovviamente sarebbe appropriato verificare se validate va a buon fine, ma il concetto è questo.