Attribut eines Models ändern

Guten Abend liebe Community,

ich bin ein Neuling im Umgang mit Yii und habe nun, da ich langsam den Einstieg gefunden habe, noch ein paar Fragen. Zuerst schildere ich mein Vorhaben:

Ich habe eine zentrale Datenbanktabelle, die die Keys aller Datensätze erzeugt und speichert (Name: SURL). Wird also bspw. ein Forenpost erzeugt, soll die ID dieses Posts von SURL::newSurl() geholt werden, doch wie setze ich dies konkret um? Ich habe es schon hiermit erfolglos versucht:


class Posts extends CActiveRecord

{

// [...]

  public function setid(){

     $this->id = SURL::newSurl();

  }

}

Ich schätze mal, dass die setsonstwas-Funktionen nur für virtuelle Attribute gilt, aber hier habe ich ein "richtiges" Attribut. Auch das Überschreiben von $this->id in der beforeSave()

Nun zu meiner zweiten Frage:

Wie baue ich die Relations auf? Muss ich im SURL-Model die anderen Tabellen definieren oder andersherum?

Vielen Dank im Voraus.

MfG HerHde

Hallo HerHde, willkommen hier im Forum.

Ich frage mich gerade, warum du hier ein so kompliziertes Konstrukt aufbauen willst. Was genau ist der Gedanke hinter SURL? Wäre es nicht viel einfacher, die ID vom DBMS automatisch erzeugen zu lassen? Beispielsweise bei MySQL als ID einen integer wählen und dann auto increment verwenden.

Grüsse

dito_ch

Hallo dito,

die SURL ist das wichtigste Konzept im Script: Diese Tabelle soll alle Datensätze zusammenhalten. Dadurch, dass die IDs zentral verteilt werden, sind sie ohne Prefix tabellenübergreifend einzigartig. Mithilfe einer Zeichen-Map (0-9 und a-Z) kann man die IDs einfach umrechnen in einen Code, wie man ihn bspw. von Youtube kennt. Die Umrechnung läuft etwa wie von Binär zu Dezimal, nur, dass wir hier ein 62er-System haben. Diese Codes werden sehr kurz, wodurch man das ganze sehr bequem für Short-URLs nutzen kann (daher auch der Name SURL).

Die IDs werden übrigens in der SURL-Tabelle per AUTO-INCREMENT erzeugt.

wenn ich das richtig verstanden habe, hast du eine tabelle "post" mit feldern, nur die id ist kein auto_increment, sondern ein varchar. Du benutzt auch ein Post-ActiveRecord.

um einen Post zu erzeugen machst du folgendes:




$post = new Post();

$post->id = SURL::newUrl();

$post->title = 'irgendein Title';

$post->save();



und das funktioniert nicht?

Ich habe es so noch nicht getestet, da ich diesen Prozess in die Models auslagern möchte. Ansonsten wird es sehr viel redundante Arbeit, so einen Codeblock an jeder Stelle, an der ein Datensatz erzeugt wird, einzufügen. Ich möchte ja theoretisch nur diesen Teil automatisch vor jedem save verschiedenster Models ausführen lassen.


$post->id = SURL::newUrl();

Geht das nicht auf eine einfache Weise?

du kannst beforeSave überschreiben und auf $this->isNewRecord testen und dann die id setzen

Wenn ich das folgendermaßen mache, erscheint die neue SURL zwar im Formular, es wird aber kein Post mehr gespeichert.


public function beforeSave(){

	if ($this->isNewRecord){

		$this->id = SURL::newSurl();

	}

}

EDIT:

Ich habe es auch mit $this->setAttribute(‘id’, SURL::newSurl()); versucht, doch das Ergebnis ist das Gleiche. Auch, wenn ich das Ganze in der Funktion beforeValidate() ausführe.

beforeSave muss anscheinend true zurückgeben?

bzw return parent::beforeSave()

Ja, das klingt logisch und funktionieren tut es ganz nebenbei auch noch. Sehr gut, vielen Dank.

Nun nochmal zu meiner zweiten Frage:

welche relationen benötigst du denn?

Ich möchte, dass ich von einer SURL aus auf das verknüpfte Model zugreifen kann, also etwa $this->post->title. Wenn ich es richtig verstanden habe, müsste ich also in SURL folgendes angeben: ‘post’ => array(self::HAS_ONE, ‘Post’, ‘id’). Kann ich so eine Relation auch nur in Post angeben, um den oben genannten Effekt zu erreichen?

Ich habe mir nun nämlich eine Helferklasse erstellt, die die ActiveRecord-Klasse um mein spezielles beforeSave() ergänzt. Von dieser Klasse erben jetzt alle Datensätze, die eine SURL als ID haben, da wäre es doch sinnvoll, die Relation schon hier festzulegen, oder?

eine relation macht in diesem fall keinen sinn, weil du erstmal wissen musst, dass es ein post ist.

quasi musst du eh erst surl::model()->findByPk() machen und dann festellen, was für eine Tabelle du ansprechen musst und dann den Satz aus der entsprechenden tabelle holen -> umständlich.

Ich habe vergessen zu erwähnen, dass SURL ein Feld Table enthält, die die Tabelle angibt. Hierbei habe ich nun das Problem, wie ich den Namen des Models bekomme, wenn ich ihn der SURL übergeben möchte…

EDIT:

Ich habe letzteres gelöst, indem ich den Namen der Klasse über beforeSave() übergebe.


public function beforeSave(){

	return parent::beforeSave(__CLASS__);

}