ActiveRecord vs. FormModel

Hallo liebe Community,

ich bin gerade in der Entwicklungsphase eines Projekts. Dort stehe ich vor einer etwas komplizierten Frage, da ich noch blutiger Anfänger bin. Hierzu erstmal kurz das Szenario: Ich habe in einer Datenbank (innoDB) mehrere Tabellen, die alle irgendwie über Relationen verknüpft. Die Daten in der DB sollen über Tabellen dargestellt werden und über Formulare geändert, gelöscht und angelegt werden.

Was eignet sich nun besser: FormModel oder ActiveRecord?

Im ersten Moment dachte ich zwar an FormModel, da CRUD irgendwie hier am sinnigsten das Problem beschreibt. Dann habe ich aber in Guide aber etwas über Relationale ActiveRecords gelesen, was mir sinniger erschien. Immerhin möchte ich ja z.B. auch Zwischentabellen über "verschachtelte" Formulare erstellen. Ein Beispiel hierfür wäre "Autohaus" und "Kunde" mit der Zwischentabelle "Autokauf". Ich möchte dem User die Möglichkeit bieten, dass er in einem Formular x-beliebig viele Autokäufe auf einmal tätigen kann. Er drückt z.B. ein "Plus"-Zeichen über neue Felder für ein weiteren Autokauf einzublenden. Und dadurch kann er auf einmal 10 Käufe vornehmen und im Hintergrund werden 10 Einträge angelegt.

Ich hoffe, ich habe euch mein Problem einigermaßen beschreiben können.

Wäre sehr dankbar für euren Rat.

PS: Habe Bedenken, dass ich mich jetzt für FormModel entscheide und später im Projekt es doch noch zusätzlich als ActiveRecord brauche. :frowning:

ActiveRecords sind quasi Tabellenabbildungen als PHP-Objekte. Wenn du mit den Formularen in Tabellen eintragen, bearbeiten, löschen willst, sind ActiveRecords am sinnvollsten. Formulare die nicht in Tabellen eintragen sind dann FormModels, z.B. Login, Kontakformular, etc.

Bedeutet das also, dass CRUD auf ActiveRecords basiert?

Finde leide kein Beispiel zu Formularen mit ActiveRecords :frowning:

CRUD ist lediglich ein Akronym für die wichtigsten Datenbankoperationen: Create, Read, Update und Delete. Wie du das umsetzt ist im Prinzip deine Sache.

Standardmäßig ist das Prozedere folgendermaßen:

  1. Du erstellst eine Tabelle (manuell)

  2. Du legst ein Modell an (= ActiveRecord) für diese Tabelle an (manuell oder mit gii)

  3. Du erstellst CRUD-Operationen für dieses Modell (manuell oder mit gii)

Schritte 2 & 3 musst du nicht machen, wenn du ohne ActiveRecords auskommst und deine SQL-Anweisungen manuell schreibst. Dann hast du aber z.B. statt:




// eintragen

$auto = new Auto();

$auto->marke = "VW";

$auto->modell = "Käfer";

$auto->preis = 12090;

$auto->save();


// auslesen

$auto = Auto::model()->findByPk(1);



folgendes:




// eintragen

$sql = "INSERT INTO auto (marke, modell, preis) VALUES ('VW', 'Käfer', 12090)";

mysql_query($sql);


// auslesen

$sql = "SELECT * FROM auto WHERE autoid = 1 LIMIT 1";

$result = mysql_query($sql);

$auto = mysql_fetch_assoc($result);



Wobei das nantürlich nur die einfachsten Szenarien sind. Möchtest du z.B. Tabellen verknüpfen musst du die Joins immer manuell schreiben, während du bei ActiveRecords in der relations()-Methode ganz einfach auf andere Tabellen zugreifen kannst.

Vereinfacht gesagt: Wenn du auf AR verzichtest, verzichtest du auf eine ganze Menge an Bequemlichkeit. Unter Umständen bringt das aber Performancevorteile, sodass man bewusst darauf verzichtet.

Beispiele…Hm weiß ich jetzt auch nicht, am sinnvollsten wäre es wohl sich anzuschauen was gii produziert wenn du ein Model bzw. CRUD erstellst. Ansonsten würde ich’s mal mit dem Blog-Tutorial versuchen.

Danke für diese ausführliche Antwort.

Ich teste mal gii für CRUD aus. Und schaue, was ich erstellt bekomme.

Hallo,

bin gerade dabei ein Formular zum Erstellen von Datenbankeinträgen zu generieren.

Hierbei möchte ich einen Wizard zur Eingabe der Daten erstellen. Scheinbar gibt es schon eine Ext. namens Wizard Behavior. Leider funktioniert diese aber nur FormModel und nicht mit Active Records. Gibt es eine Wizard-Lösung für Active Records?

Alternativ müsste ich auf wform umsteigen, damit ich nicht mehrere Schritte (Wizard) habe, sondern ein großes kombiniertes Formular. Hierzu wäre meine Frage, ob ich solch ein Formular aus mehrere Active Records nur mit wform bauen kann oder ob das auch anders geht?

Wenn du meinst ob du beispielsweise model A inklusive model B in einem formular unterbringen kannst, dann ist die Antwort "ja". Im Endeffekt liegts an deinem Controller ob er nur model A erzeugt oder auch ein model B. Nehmen wir an der "create" view rendered ein formular in dem du felder für beide models ausgibst




$modelA=new ModelA;

$modelB=new ModelB;


$this->render('create',array('modelA'=>$modelA,'modelB'=>$modelB));



Habe mich gerade mal mit der wform-Extension befasst. Bisher weiß ich leider noch nicht so ganz, was ihr vorteil ist. :slight_smile:

Aber hier habe ich gerade extreme Probleme mit dem PK, der 2 Colums hat. Denn aus irgendeinem Grund erwartet wform immer nur Tabellen mit einem einfachen PK. :frowning:

Das sieht man hieran (.../protected/extensions/wform/WFormRelation.php):


public function removeFromLazyDelete($model) {

     if (array_key_exists($model->primaryKey, $this->_lazyDeleteRecords))

             unset($this->_lazyDeleteRecords[$model->primaryKey]);

}

Als erstes Argument bei array_key_exists wird ein String oder Integer erwartet. Bei einem zusammengesetzten PK ist dies aber ein Array. Oder habe ich jetzt einen Denkfehler? :wink:

Das Problem bei extension ist, dass diese halt meistens für einen bestimmten use-case entworfen wurden und nicht immer alle Situationen abdecken. Das scheint hier der Fall zu sein. Ich würd einfach mal versuchen alles mit vorhandenen "Bordmitteln" zusammenzubasteln und wenns dann wo hakt kann man immer noch zu einer extension greifen. Hier gibts einen Wikieintrag zum Thema mehrere models + AJAX (das JUI widget kannst du ja weglassen, das prinzip ist aber das selbe): http://www.yiiframework.com/wiki/72/cjuidialog-and-ajaxsubmitbutton

Danke Haensel, dass du dich so bemühst.

Aber mal eine Frage hierzu. Wie ist das denn nun, wenn ich jetzt einen neuen Eintrag in Tabelle X anlege und die dort generierte ID (in dem Fall der PK) dann woanders eintragen muss Wird diese ID beim Erzeugen angelegt?

Danke schon mal. Bist meine Rettung gewesen.

Ja, wenn du ActiveRecord nutzt ist das relativ trivial. Beispiel:




$zebra1= new Zebra; //hier gibts noch keine ID klarerweise, wurde ja noch nicht gespeichert

$zebra1->name="Zebra";

$zebra1->save();


echo $model->id //1, wenn das das erste Zebra war und die id als auto_increment definiert wurde


$zebra2=new Zebra;

$zebra2->name="Zebra2";

$zebra2->papa_id=$zebra1->id; //Annahme das jedes Zebra ein anderes Zebra als Papa hat, welcher über den FK papa_id definiert wird

$zebra2->save();




Liebe Grüße,

Hannes

Muss es nicht


echo $zebra1->id 

heißen?

Achso, ja, Tippfehler :)

Kein Problem. Lieber frag ich jetzt nach, als später, wenn es dann nicht funktioniert. :slight_smile:

Aber zusammengesetzten Primärschlüssel muss ich nicht in der relations-Methode angeben oder?

Grüße und schöne restliche Osterstunden :stuck_out_tongue:

Hat jemand auch noch eine Anleitung zum Thema Multi-Model?

Angenommen, ich habe 10 Felder in einem Form. 3 Davon sollen zum Erstellen eines Eintrags in der Tabelle X genutzt werden. 7 + die erzeugte ID (Auto_Increment) aus dem eben erzeugten Eintrag sollen für den Eintrag in einer anderen Tabelle genutzt werden.

hier kann ich ja sicher nicht einfach save des ersten Models aufrufen und dann nochmal save des anderen Models (wie oben beschrieben). Die Einträge sollen nur erzeugt werden, wenn das gesamte Formular abgesendet wird. :slight_smile:

Für Multimodel forms kann ich dir das hier empfehlen:

http://www.yiiframework.com/wiki/19

Edit: wenn du fragen dazu hast gib bescheid, ich hab das schon mit bis zu 5 models verwendet ;) Das löschen habe ich jedoch noch nicht abgeändert, das würde ich im Model machen, glaub im beforeDelete callback wäre es am sinnvollsten.

Grüße

-Seb

das ist es:

http://www.yiiframework.com/wiki/291/update-two-model-with-one-view/

bzw. wenn du eine extension verwenden möchtest, ich werde die hier nachher mal ausprobieren:

http://www.yiiframework.com/extension/wform/

Sebako, davon nehme ich Abstand. Wie gesagt unterstützt die Extension keinen zusammengesetzten Primärschlüssel.

Habe nun mein Formular sauber zusammengebaut und es läuft auch. Leider gibt es ein kleines Problem.

Im oberen Bereich habe ich Felder für Model1 und im unteren Bereich Felder für Model2. Für das Formular habe ich enableAjaxValidation auf true gesetzt. Wenn nun validiert wird und eine Fehler im unteren Bereich entsteht, so wird der Fehler angezeigt. Kommt es aber zu einem Fehler im oberen Bereich, werden die unteren Felder alle gelöscht. Ist das normal? Hängt das mit den zwei verschiedenen Models zusammen?