4 Stimmen

Cakephp's beforeSave behält keine neuen Daten, wenn saveAll verwendet wird?

Ich habe ein relativ einfaches Eingabemodell mit nur fünf Feldern:

  1. id
  2. type (welcher Datentyp dieser Eintrag ist)
  3. Menge (wie viele von welcher Art auch immer es ist)
  4. Einheit (die Einheit des Typs)
  5. Datum (die Uhrzeit, zu der der Eintrag vorgenommen wurde)
  6. user_id (die Kennung des Benutzers, der die

Also, nichts Ausgefallenes. Jetzt kann ein einzelnes Formular mehrere Einträge haben (sowohl bereits vorhandene als auch neu erstellte), das Formular wird über Ajax-Aufrufe erweitert.

Wenn ich das Formular abschicke $this->data sieht so aus:

Array
(
    [Entry] => Array
        (
            [date] => 2011-01-07
            [0] => Array
                (
                    [id] => 1
                    [type] => Eat
                    [amount] => 1 Steak, one baked potatoe
                    [unit] => lunch
                    [time] => Array
                        (
                            [hour] => 13
                            [min] => 31
                        )

                )

            [1] => Array
                (
                    [type] => weight
                    [amount] => 78.5
                    [unit] => KG
                    [time] => Array
                        (
                            [hour] => 22
                            [min] => 22
                        )

                )

        )

)

Der erste Eintrag in $this->data['Entry']['date'] ist das Datum, das für ALLE Einträge verwendet werden soll. Und da auch die user_id fehlt, habe ich eine "beforeSave" Funktion im Eintragsmodell erstellt. Diese sieht wie folgt aus:

function beforeSave() {
    App::import('Component','Session');
    $this->Session = new SessionComponent();

    if (isset($this->data) && isset($this->data['Entry'])) {
        $date = $this->data['Entry']['date'];
        unset($this->data['Entry']['date']);

        foreach ($this->data['Entry'] as $n => $entry) {
            if (is_array($entry)) {
             $this->data['Entry'][$n]['date'] = $date . ' ' . $entry['time']['hour'] . ':' . $entry['time']['min'] . ':00';
                $this->data['Entry'][$n]['user_id'] = $this->Session->read('Auth.User.id');
            }
        }
        debug($this->data);

    }
    return true;
}

Ich entferne das Datum, füge es zusammen mit dem Zeiteintrag des Benutzers ein, wodurch ein mysql datetime-Eintrag entsteht, und füge die user_id des angemeldeten Benutzers hinzu. Eigentlich ganz einfach. Das resultierende Array (wie es von der letzten debug() ) sieht folgendermaßen aus:

Array
(
    [Entry] => Array
    (
        [0] => Array
            (
                [id] => 1
                [type] => Eat
                [amount] => 1 Steak, 1 baked potatoe
                [unit] => lunch
                [time] => Array
                    (
                        [hour] => 09
                        [min] => 31
                    )

                [date] => 2011-01-07 09:31:00
                [user_id] => 2
            )

        [1] => Array
            (
                [type] => Weight
                [amount] => 78.5
                [unit] => KG
                [time] => Array
                    (
                        [hour] => 22
                        [min] => 22
                    )

                [date] => 2011-01-07 22:22:00
                [user_id] => 2
            )

    )

)

So sieht es genau so aus, wie ich es haben möchte, und es sollte leicht zu speichern sein. Aber wenn ich $this->Entry->saveAll($this->data['Entry'] ), um alle Einträge zu speichern, funktioniert es nicht nur nicht, sondern wenn ich Debug $this->data direkt nach der saveAll-Funktion sieht es genauso aus wie vor der saveAll-Funktion - das Datum ist wieder im Array, die Einträge haben keinen date- oder user_id-Eintrag.

Ich kann sehen, dass beforeSave aufgerufen wird, ich kann sehen, dass es Änderungen $this->data aber irgendwo zwischen dem Ende von beforeSave und der Verwendung von "saveAll" gehen alle meine Änderungen verloren und $this->data wird in seinen ursprünglichen Zustand zurückversetzt. Es findet also keine Speicherung statt.

6voto

snowball Punkte 76

Ich hatte ähnliches Problem versuchen, einige Bereinigung mit hasMany durch zu implementieren. Wie sich herausstellte, liegt das Problem darin, wie saveAll() funktioniert. Die $this->data im Controller sind nicht die gleichen wie die $this->data im Model::beforeSave() Callback und die beiden sind nicht synchronisiert. Wenn Sie Model::saveAll() aufrufen und dabei $this->data aus dem Controller übergeben, geben Sie dem Model explizit "die alte Version" des Datenarrays. Und wenn man sich die saveAll-Definition in cake/libs/model/model.php anschaut, tut es das auch:

if (empty($data)) {
   $data = $this->data
}

und nichts weiter, um das geänderte $data-Array im Modell zu synchronisieren und durch den Parameter $data vom Controller zu übergeben. Die Lösung besteht darin, die Daten nicht an saveAll() zu übergeben, sondern die Daten zuerst mit Model::set() im Model zu setzen und dann Model::saveAll() (ohne den Parameter $data) aufzurufen.

2voto

himanshu vora Punkte 21

Wenn wir SaveAll aufrufen, werden die aktualisierten/übermittelten Daten nicht an beforeSave des Modells übergeben. Um aus diesem Problem herauszukommen,

tmp_data-Array im Modell erstellen

es decir

var $tmp_data = array();

setzen Sie diese Variable vor dem Aufruf von saveall, d.h.

$this->model->tmp_data = $this->data;
$this->model->saveAll();

Dann ändern Sie den Code für model->beforeSaveBefore Anstelle von $this->data use $this->tmp_data

1voto

Leo Punkte 1501

Sie stolpern doch nicht über die Validierung, oder?

Versuchen Sie

$this->Entry->saveAll($data,array('validate'=>false));

Wenn es funktioniert, liegt das Problem in der Validierung

Vergessen Sie jedoch nicht, dass Sie create() vor dem Speichern für einzelne Modelle verwenden müssen, wenn kein Primärschlüssel angegeben ist. Vielleicht ist die Vermischung von neuen und bestehenden Daten in saveAll() das Problem.

0voto

mark Punkte 21538

Soweit ich weiß, lösen saveAll() updateAll() und deleteAll() standardmäßig keine Rückrufe aus.

Sie müssen sie manuell aktivieren (letzter Parameter der Methode)

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X