Startseite
  • » Home
  • » Handbuch & FAQ
  • » Forum
  • » Übersetzungsserver
  • » Suche
Startseite › Forum › Drupalcenter.de › Module › Views ›

[gelöst] Node Reference/Back Reference über mehrere Content Typen

Eingetragen von Milchbar (39)
am 06.07.2010 - 18:19 Uhr in
  • Views
  • Drupal 6.x

Hey zusammen,

ich bin mir nicht sicher ob der Weg den ich zur Zeit einschlage nicht eh schon der falsche ist. Deswegen hier ein kurzer Überblick über das was ich erreichen möchte.

  • Ich habe 3 Inhaltstypen; Projekt, Kunde und Diensleistung
  • Beim erstellen eines neuen Projektes kann ich aus vorhandenen Kunden und Diensleistungen (via Node Reference) eine Auswahl treffen und möchte folgende Referenzen speichern:
    1. neues Projekt: speichert Referenz zu ausgewähltem Kunde und ausgewählten Dienstleistungen
    2. ausgewählte/r Kunde/n: speichert Referenz zum erstellten Projekt und den darin ausgewählten Dienstleistungen
    3. ausgewählte Diensleistung/-en: speichert Referenz zum erstellten Projekt und den darin ausgewählten Kunden
  • Nun dachte ich mir das man das Ganze über das Modul "Back Reference"[1] lösen kann. Das funktioniert auch bedingt, allerdings scheinbar immer nur zwischen maximal 2 Nodes. Hat jemand schonmal ein ähnliches Problem gehabt oder zufällig einen Lösungsansatz mit dem man das komfortabel lösen kann?

    Beste Grüße,
    Milchbar

    [1] http://drupal.org/project/backreference

‹ [gelöst] Views Pager: Seite merken mit Argument? Frage/Problem mit Locations: Felder werden nicht richtig angezeigt. ›
  • Anmelden oder Registrieren um Kommentare zu schreiben

Du möchtest also ein neues

Eingetragen von Exterior (2903)
am 06.07.2010 - 22:31 Uhr

Du möchtest also ein neues Projekt "Projekt A" speichern und wählst dort z.B. die Nodes "Kunde 1" und "Dienstleistung 1" als Nodereference. Damit referenziert also "Projekt A" auf "Kunde 1" und "Dienstleistung 1". Gleichzeitig soll aber automatisch "Kunde 1" auf "Projekt A" und "Dienstleistung 1" referenzieren und "Dienstleistung 1" soll auf "Projekt A" und "Kunde 1" referenzieren, habe ich das richtig verstanden?

Dürfte sich eigentlich alles mit Rules machen lassen.

Projekt referenziert Kunde und Dienstleistung --> geschieht ja eigentlich automatisch.

Dann wählt man zweimal die Aktion "referenzierten Node laden" und wählt jeweils die beiden Referenz-Felder und benennt die entstehenden Objekte entsprechend.
Dann kann man doch einfach wählen, dass man ein CCK-Feld füllen will, wählt den ersten referenzierten Node und das Nodereference-Feld und trägt dort die Node-IDs der referenzierten Nodes ein.

Ist nur ein einfall und nicht getestet.

Edit:
Habe mir die Regeln usw. gerade mal angeschaut und das dürfte problemlos klappen, eben mit etwas PHP-Auswertung.

  • Anmelden oder Registrieren um Kommentare zu schreiben

Hi Exterior, richtig, genau

Eingetragen von Milchbar (39)
am 07.07.2010 - 09:13 Uhr

Hi Exterior,

richtig, genau das möchte ich erreichen und genau das habe ich probiert. Allerdings habe ich hierbei das Problem das u.U. Mehrfach-Referenzen gesetzt werden. Beispiel:

Projekt A und Projekt B mit sich überschneidenden Dienstleistungen sind beide für Kunde A. Hier wird dann eine doppelte Referenz beim Kunden A gespeichert. Somit kann es passieren dass der Kunde x-mal die Dienstleistung A aufgeführt hat. Auch an PHP habe ich gedacht doch anscheinend den falschen Ansatz gehabt. Folgenden php-code habe ich zum füllen der Referenzen benutzt:

$a = $node_reference->field_services; // schauen ob Kunde bereits services eingetragen hat
$b = $node->field_services;  // neue services die hinzugefügt werden

$result = array_merge($a, $b); // array_merge überschreibt doppelte einträge
return $result;

Das funktioniert aber nicht wie gewünscht. Das Hauptproblem sind nach wie vor die Duplikate. Zur Not muss ich wohl das Array Wert für Wert mit dem neuen vergleichen. Werde mir dann das ganze nochmal genauer anschauen.

-- EDIT:
So, habe das ganze nochmal neu aufgebaut. Interessanterweise werden Duplikate nun anscheinend nicht mehr angezeigt, aber das muss ich noch ausführlicher testen. Allerdings folgendes Problem: die Regel scheint nicht alle verknüpften Referenzen anzusprechen. Beispiel:

Wenn ich bei einem Projekt mehrere Diensleistungen auswähle, diese ausgewählten Diensleistungen dann mit Rules ansprechen möchte, speichert er die Änderungen nur in der *ersten* gewählten Diensleistung. Die anderen bleiben unberührt.

Hier meine aktuelle Rule.

ON event After saving new content
IF Created content is Project

DO
Load a referenced node // Kunden
Populate client referenced content's field 'field_clientprojects'
Populate client referenced content's field 'field_clientservices'
Load a referenced node // Dienstleistungen
Populate service referenced content's field 'field_serviceprojects'
Populate service referenced content's field 'field_serviceclients'

Populate service referenced content's field 'field_serviceclients' besitzt folgende PHP Anweisungen zum füllen:

$a = $node->field_projectclients + $service_referenced_node->field_serviceclients;
return $a;

Hat jemand Vorschläge? ^^

  • Anmelden oder Registrieren um Kommentare zu schreiben

Mmmh, da fällt mir auf die

Eingetragen von Exterior (2903)
am 07.07.2010 - 23:33 Uhr

Mmmh, da fällt mir auf die Schnelle nur ein, als Rule-Aktion Custom-PHP-Code auszuführen. Habe jetzt bei Nodereference auch keine Funktion gefunden, die man einfach mal aufrufen könnte, um die Referencen einzutragen.

In dem PHP-Code könntest du folgendes machen:

--> den höchsten Delta-Wert aus der Tabelle des Referenz-Feldes für diesen Node suchen und speichern + inkrementieren

--> mit foreach() durch das Array $node->field_reference_feld wandern
Und im foreach-Abschnitt folgendes machen:
-->per SQL-Abfrage die IDs des aktuellen Nodes sowie des aktuellen Reference-Nodes und den Delta-Wert eintragen
--> Delta inkrementieren

Könnte dann so aussehen:

<?php
$reference
= $node->nid;

//mit foreach() durch array wandern
foreach ($node->field_reference_feld as $key => $value){
$node_id = $value['nid'];

//höchstes Delta des Nodes ermitteln
$sql = "SELECT MAX(delta) FROM {content_field_reference_feld} WHERE vid = %d;";
$delta = db_result(db_query($sql, $node_id));

//Delta inkrementieren
$delta++;

//Aktuellen Referenz-Node eintragen
$sql = "INSERT INTO content_field_reference_feld (vid, nid, delta, field_reference_feld_nid) VALUES (%d, %d, %d, %d);";
$result = db_query($sql, $reference, $reference, $delta, $node_id);
}
?>

Damit würden alle Einträge im Node-Reference-Feld in die entsprechende Tabelle eingetragen. Man könnte natürlich noch prüfen, ob in der Tabelle schon ein Eintrag mit dieser Reference-ID existiert und nur den Datensatz eintragen, wenn dies nicht zutrifft usw.

Das dürfte zwar im Grunde funktionieren, aber leider gibt's da ein Problem: Ich habe keine Ahnung, was passiert wenn das Script gleichzeitig von zwei Leuten ausgeführt wird. Denn dann könnte sich der Delta-Wert der beiden überschneiden, ich hoffe du weißt, was ich meine.

Hat vielleicht einer von den erfahreneren eine Lösung dafür?

Den PHP-Code müsste man natürlich noch anpassen etc, aber so könnte es schonmal klappen.

  • Anmelden oder Registrieren um Kommentare zu schreiben

VBO?

Eingetragen von Milchbar (39)
am 09.07.2010 - 06:43 Uhr

Ich nochmal. Nachdem ich mir gestern das Beispiel von Exterior angeschaut hab und noch das ein oder andere Forum durchwühlt habe bin ich auf "Views Bulk Operations (VBO)" [1] gestoßen. Hat hier schonmal einer mit gearbeitet? Ich versuche über den vormittag mal das Problem damit [2] zu lösen, hab aber mit VBO noch nie gearbeitet. Daher bin ich für weitere Anregungen dankbar :) - nicht das ich hier den heiligen Gral vermute, der sich als Pappbecher entpuppt.

[1] http://drupal.org/project/views_bulk_operations
[2] http://thereisamoduleforthat.com/content/event-driven-bulk-updates-using...

  • Anmelden oder Registrieren um Kommentare zu schreiben

VBO funktioniert im Grunde

Eingetragen von Exterior (2903)
am 09.07.2010 - 12:47 Uhr

VBO funktioniert im Grunde ganz gut, soweit ich das beurteilen kann.

Aber ich habe keine Ahnung, ob du damit dieses Problem lösen kannst, musst du mal probieren.

  • Anmelden oder Registrieren um Kommentare zu schreiben

Ich glaube, ich könnte eine

Eingetragen von Exterior (2903)
am 09.07.2010 - 19:34 Uhr

Ich glaube, ich könnte eine Möglichkeit gefunden haben:

Zuerst erstellst du dir ein neues RegelSet, nennen wir es mal "Regelset Backreference". Als "maschinenlesbaren Namen" geben wir auch einfach "backreference" ein (daraus ergibt sich, dass das Regelset den Namen rule_backreference erhält).

Außerdem geben wir dem Regelset zwei Argumente mit auf den Weg, beide vom Typ "Inhalt". Das eine bekommt die Bezeichnung "Referenzierter Node" und den Namen "referenced_node". Das andere Argument bezeichnen wir mit "Erstellter Inhalt" und benennen es mit "node_added".

Darin erstellen wir zwei Regeln.

Regel 1:
Bekommt als Bedingung, dass der Inhalt "Referenzierter Node" vom Typ Kunde ist.

Die Regel bekommt 2 Aktionen:
"Ein CCK-Feld füllen" --> als Inhalt wird der Referenzierte Node genommen, als Feld das Node-Reference-Feld für Projekte, das heißt bei mir gerade field_projekt_referenz.
Den Wert legen wir mit PHP fest und tragen folgendes ein:

<?php
return array(
 
0 => array('nid' => $node_added->nid),
);
?>

Als 2. Aktion nehmen wir nochmal "Ein CCK-Feld" füllen, wieder vom Referenzierten Node (welcher in dieser Regel vom Typ Kunde ist) und nehmen das Node-Reference-Feld für die Dienstleistung (field_dienstleistung_referenz).
Auch dort legen wir den Wert mit PHP fest und tragen da folgendes ein:

<?php
$werte
= array(); $i = 0;

foreach (
$node_added->field_dienstleistung_referenz as $row) {
$id = $row['nid'];
$werte[$i] = array('nid' => $id);
$i++;
}

return
$werte;
?>

Das war die erste Regel.
Die zweite sieht fast genauso aus. Man prüft als Bedingung ob der Referenzierte Node vom Typ Dienstleistung ist.
Die erste Aktion trägt wieder die Projekt-Referenz ein.

Als zweite Aktion in dieser Regel füllen wir wieder ein CCK-Feld des Referenzierten Nodes, allerdings diesmal field_kunde_referenz und tragen folgendes ein:

<?php
$werte
= array(); $i = 0;

foreach (
$node_added->field_kunde_referenz as $row) {
$id = $row['nid'];
$werte[$i] = array('nid' => $id);
$i++;
}

return
$werte;
?>

Damit ist das Regelset fertig. Jetzt legen wir noch eine Reaktive Regel an, als Ereignis nehmen wir "Nach dem Speichern von neuem Inhalt". Als Bedingung prüfen wir, dass der neue Inhalt vom Typ "Projekt" ist.

Als Aktion führen wir Custom PHP aus und tragen folgenden PHP-Code ein:

<?php
//Backreference für alle referenzierten Dienstleistungen ausführen
foreach ($node->field_dienstleistung_referenz as $r) {
$id = $r['nid']; $n = node_load($id);

//Führt das Regelset aus und übergibt hinten die beiden Node-Objekte als Argumente
rules_invoke_rule_set('rules_backreference', array('referenced_node' => $n, 'node_added' => $node));
}

//Backreference für alle referenzierten Kunden ausführen
foreach ($node->field_kunde_referenz as $r) {
$id = $r['nid']; $n = node_load($id);

//Führt das Regelset aus und übergibt hinten die beiden Node-Objekte als Argumente
rules_invoke_rule_set('rules_backreference', array('referenced_node' => $n, 'node_added' => $node));
}
?>

Das war's, wenn man jetzt einen Node A vom Typ "Projekt" erstellt, dann bekommen alle referenzierten Dienstleistungen das Projekt A sowie die darin referenzierten Kunden als Referenz und genauso verhält es sich mit allen referenzierten Kunden. In dem PHP-Code des Regelsets kann man dann noch Anpassungen vornehmen, um bestehende Inhalte beizubehalten und Doppel-Einträge zu vermeiden, sollte keine große Sache sein.

Hab's gerade getestet und es scheint ordentlich zu funktionieren.

  • Anmelden oder Registrieren um Kommentare zu schreiben

Respekt! ;)

Eingetragen von Milchbar (39)
am 09.07.2010 - 20:07 Uhr

Hab Deinen Beitrag nur kurz überflogen und werde es später am Abend noch testen. Melde mich dann hier nochmal, aber das sieht wirklich danach aus, als ob das die Lösung ist. Vielen Dank für die Mühe das selbst zu testen und hier noch so einen langen Artikel zu schreiben!

--edit: Konnte doch nicht mehr abwarten und hab es direkt probiert ;) Es funktioniert einwandfrei! Nochmals besten Dank!

  • Anmelden oder Registrieren um Kommentare zu schreiben

Schön dass es klappt :) Dann

Eingetragen von Exterior (2903)
am 09.07.2010 - 20:34 Uhr

Schön dass es klappt :)

Dann noch oben [gelöst] hin und alles ist wunderbar ^^

  • Anmelden oder Registrieren um Kommentare zu schreiben

Zu früh gefreut...

Eingetragen von Milchbar (39)
am 11.07.2010 - 09:42 Uhr

leider ist das Problem nicht wirklich gelöst. Wenn man nur ein Projekt erstellt dann funktioniert es superb. Sobald ich aber ein zweites Projekt mit exakt denselben Eigenschaften(Diensleistung und Kunde) erstelle werden die Verknüpfungen (sprich: Node-Referenzen) überschrieben. Zum Anhängen von neuen Nodes habe ich die erste Aktion von

<?php
return array(
 
0 => array('nid' => $node_added->nid),
);
?>

zu

<?php
$old
= $referenced_node->field_clientprojects
$new
= array(0 => array('nid' => $node_added->nid));
$merged = $old + $new;
return
$merged;
?>

Das funktioniert weil hier eben immer nur 1 Projekt (das gerade erstellte) hinzugefügt wird. Für die 2. Aktion (s.o. Beitrag von Exterior) schaut das aber anders aus. Erstelle ich beispielsweise 2 verschieden Projekte mit denselben Kunden und denselben Diensleistungen, dann taucht in den entsprechenden Dienstleistungen und Kunden nur das zuletzt erstellte Projekt auf.

Ich habe probiert erst das ursprüngliche Node-Reference-Array auszulesen und dann das neue anzufügen. Problerm hierbei: es tauchen Duplikate auf und das ganze wirkt irgendwie nicht sonderlich "stabil".

  • Anmelden oder Registrieren um Kommentare zu schreiben

Gelöst

Eingetragen von Milchbar (39)
am 11.07.2010 - 12:16 Uhr

Habs jetzt einfach mit ner 2. foreach gelöst und eine funktion zum entfernen von duplikaten in multidimensionalen arrays hinzugefügt.

Die Funktion kommt als "Custom PHP Code" in die erstellte "Triggered Rule". Somit sieht der Code folgendermaßen aus:

<?php
// super_unique: findet und entfernt Duplikate in einem mehrdimenionsalen Array
// via: http://www.php.net/manual/de/function.array-unique.php#97285
function super_unique($array){
 
$result = array_map("unserialize", array_unique(array_map("serialize", $array)));
  foreach (
$result as $key => $value) {
    if(
is_array($value)){
     
$result[$key] = super_unique($value);
    }
  }
  return
$result;
}

//Backreference für alle referenzierten Dienstleistungen ausführen
foreach ($node->field_projectservices as $r) {
$id = $r['nid']; $n = node_load($id);

//[...]
?>

Die Aktion im RegelSet wird folgendermaßen angepasst:

<?php
$new
= array(); $i = 0;

// Bereits eingetragene nid des referenzierten Nodes auslesen...
foreach ($referenced_node->field_serviceclients as $row){
 
$id = $row['nid'];
 
$new[$i] = array('nid' => $id);
 
$i++;
}

//... und die neue(/n) nid hinzufügen
foreach ($node_added->field_projectclients as $row) {
 
$id = $row['nid'];
 
$new[$i] = array('nid' => $id);
 
$i++;
}

// Zum Schluss via super_unique alle Duplikate entfernen
return super_unique($new);
?>

Bis jetzt scheint es problemlos zu funktionieren. Ich werde noch ein paar Tests laufen lassen und ggfs. den Thread wieder öffnen, sollte es doch noch zu Problemen kommen.

  • Anmelden oder Registrieren um Kommentare zu schreiben

Benutzeranmeldung

  • Registrieren
  • Neues Passwort anfordern

Aktive Forenthemen

  • für drupal11 ein Slider Modul
  • [gelöst] W3CSS Paragraphs Views
  • Drupal 11 neu aufsetzen und Bereiche aus 10 importieren
  • Wie erlaubt man neuen Benutzern auf die Resetseite zugreifen zu dürfen.
  • [gelöst] Anzeigeformat Text mit Bild in einem Artikel, Drupal 11
  • Social Media Buttons um Insteragram erweitern
  • Nach Installation der neuesten D10-Version kein Zugriff auf Website
  • Composer nach Umzug
  • [gelöst] Taxonomie Begriffe zeigt nicht alle Nodes an
  • Drupal 11 + Experience Builder (Canvas) + Layout Builder
  • Welche KI verwendet ihr?
  • Update Manger läst sich nicht Installieren
Weiter

Neue Kommentare

  • melde mich mal wieder, da ich
    vor 2 Tagen 18 Stunden
  • Hey danke
    vor 3 Tagen 13 Stunden
  • Update: jetzt gibt's ein
    vor 4 Tagen 7 Stunden
  • Hallo, im Prinzip habe ich
    vor 1 Woche 1 Tag
  • Da scheint die Terminologie
    vor 1 Woche 1 Tag
  • Kannst doch auch alles direkt
    vor 1 Woche 6 Tagen
  • In der entsprechenden View
    vor 1 Woche 6 Tagen
  • Dazu müsstest Du vermutlich
    vor 1 Woche 6 Tagen
  • gelöst
    vor 4 Wochen 2 Tagen
  • Ja natürlich. Dass ist etwas,
    vor 4 Wochen 3 Tagen

Statistik

Beiträge im Forum: 250233
Registrierte User: 20449

Neue User:

  • Mroppoofpaync
  • 4aficiona2
  • AppBuilder

» Alle User anzeigen

User nach Punkten sortiert:
wla9461
stBorchert6003
quiptime4972
Tobias Bähr4019
bv3924
ronald3857
md3717
Thoor3678
Alexander Langer3416
Exterior2903
» User nach Punkten
Zur Zeit sind 0 User und 15 Gäste online.

Hauptmenü

  • » Home
  • » Handbuch & FAQ
  • » Forum
  • » Übersetzungsserver
  • » Suche

Quicklinks I

  • Infos
  • Drupal Showcase
  • Installation
  • Update
  • Forum
  • Team
  • Verhaltensregeln

Quicklinks II

  • Drupal Jobs
  • FAQ
  • Drupal-Kochbuch
  • Best Practice - Drupal Sites - Guidelines
  • Drupal How To's

Quicklinks III

  • Tipps & Tricks
  • Drupal Theme System
  • Theme Handbuch
  • Leitfaden zur Entwicklung von Modulen

RSS & Twitter

  • Drupal Planet deutsch
  • RSS Feed News
  • RSS Feed Planet
  • Twitter Drupalcenter
Drupalcenter Team | Impressum & Datenschutz | Kontakt
Angetrieben von Drupal | Drupal is a registered trademark of Dries Buytaert.
Drupal Initiative - Drupal Association