[gelöst] Blöcke nur in bestimmten Kategorien anzeigen lassen?
Eingetragen von holger@drupal.org (544)
am 24.11.2008 - 10:33 Uhr in
am 24.11.2008 - 10:33 Uhr in
Hallo allerseits,
wie kann man realisieren, dass einige Blöcke nur in bestimmten Kategorien angezeigt werden?
Ein Beispiel zur Verdeutlichung:
Ich erstelle 2 Kategorien, z.B. "Sommer" und "Winter" und 2 Blöcke für die Sidebar-Rechts, z.B. "Sommer-Block" und "Winter-Block".
Wenn nun ein User die Kategorie "Sommer" oder einen dieser Kategorie zugewiesenen Artikel ansieht, dann soll der Block "Sommer-Block" angezeigt werden, bei "Winter" der "Winter-Block" u.s.w.
- Anmelden oder Registrieren um Kommentare zu schreiben
Block bearbeiten und unten
am 24.11.2008 - 11:34 Uhr
Block bearbeiten und unten bei Sichtbarkeit, die entsprechende Option sowie die URL der Taxonomyseite eintragen.
----------------------------------------
Alle Angaben ohne Gewähr!!:D
http://www.tobiasbaehr.de/
Für die Kategorien alleine
am 24.11.2008 - 12:38 Uhr
Für die Kategorien alleine oder z.B. nur die Startseite klappt das bei mir auch, allerdings bislang leider nicht bei Aufruf eines der Kategorie zugewiesenen Artikels.
Das müsste etwa so aussehen:
Wenn der User Kategorie "Sommer" aufruft wird der Block "Sommer-Block" angezeigt.
Ruft der User den Artikel node/1 auf, welcher der Kategorie "Sommer" zugewiesen ist, dann soll ebenfalls der "Sommer-Block" angezeigt werden.
Natürlich könnte man das manuell jeweils einbringen, aber bei größeren Seiten mit einigen Tausend Beiträgen wäre ein Automatismus wohl besser.
Vielleicht hat ja noch jemand einen Tipp für solche Umsetzung.
Gruß Holger
IT-News auf http://w3projekt.com
taxonomy_node_get_terms
am 24.11.2008 - 13:05 Uhr
Moin!
Du musst über ein kleines PHP-Skript abfragen, ob sich der/die/das node im gewünschten Term befindet. Dazu kannst Du taxonomy_node_get_terms() verwenden. Die node-Id, die Du benötigst, bekommst Du mittels arg().
<?php
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$terms = taxonomy_node_get_terms($node);
// terms durchlaufen und falls die gewünschte Kategorie gefunden wird:
if (...) {
return TRUE;
}
}
return FALSE;
?>
Das Ganze packst Du Dir dann in eine Datei (Vorschlag: [misc/scripts/block_taxonomy.inc]) und inkludierst diese Datei dann mittels
<?php
include_once(dirname(__FILE__) . '/misc/scripts/block_taxonomy.inc');
?>
hth,
Stefan
PS: Bei dem include-Pfad bin ich mir nicht völlig sicher. Es kann sein, dass da noch ein '../' fehlt.
Guten Abend, das sieht ja
am 24.11.2008 - 20:21 Uhr
Guten Abend,
das sieht ja fast schon wissenschaftlich aus ....
Was genau müsste denn bei
if (...)
noch hinzugefügt werden um das Ganze lauffähig zu machen?
Leider bin ich kein Programmierer deshalb muss ich nachfragen.
Gruß Holger
IT-News auf http://w3projekt.com
taxonomy
am 24.11.2008 - 21:13 Uhr
Was genau müsste denn [...] noch hinzugefügt werden um das Ganze lauffähig zu machen?
Au weia, da hab ich mir ja wieder was eingebrockt :-).
<?php
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$terms = taxonomy_node_get_terms($node);
$needle = array('Sommer', 'Winter');
/**
* terms nach gewünschten Kategorien durchsuchen und
* je nach Ergebnis Block (nicht) anzeigen
*/
return terms_contains($terms[$node->vid]['tid'], $needle);
}
/**
* Durchsucht ein Array von terms nach einem bestimmten Namen.
*
* @param $terms Array Array mit den zu durchsuchenden terms.
* @param $needle mixed Array oder String mit den zu findenden Namen.
* @return boolen TRUE wenn der/die Namen gefunden wurden, sonst FALSE.
*/
function terms_contains($terms, $needle) {
if (!is_array($needle)) {
$needle = array($needle);
}
foreach ($terms as $key => $term) {
if (in_array($term->name, $needle)) {
return TRUE;
}
}
return FALSE;
}
?>
Nur noch ein kleiner Hinweis in eigener Sache: das ist komplett ungetestet, muss also nicht funktionieren :-). Kann aber.
Stefan
Werd ich mal testen, danke
am 24.11.2008 - 21:40 Uhr
Werd ich mal testen, danke für deine Mühe!
Ich hab das Ganze bislang unter Wordpress laufen und da ist es eine ansich simple if - elseif Funktion
<?php
if ( is_category('computertechnik') || in_category('12') ) {
wpads('300-computertechnik');
} elseif( is_category('informationstechnik') || in_category('7') ) {
wpads('300-informationstechnik');
} elseif( is_category('58') || in_category('58') ) {
wpads('300-macnews');
} elseif( is_category('technologie') || in_category('90') ) {
wpads('300-technologie');
} elseif( is_category('netzwelt') || in_category('46') ) {
wpads('300-netzwelt');
} else {
wpads('300-default');
}
?>
Gehts sowas nicht auch unter Drupal, weil man da ja nicht extra ein Modul bräuchte?
Beste Grüße, Holger
IT-News auf http://w3projekt.com
terms
am 25.11.2008 - 15:09 Uhr
Die von mir vorgeschlagene Lösung ist kein eigenständiges Modul, sondern nur ein Codeschnipsel, dass Du in die Blockkonfiguration einträgst (besser in eine eigene Datei, die Du dann inkludierst).
Und wenn Du das in mehreren Blöcken verwenden willst, kannst Du die Funktion
terms_contains()
auch einfach in die Datei template.php Deines Themes packen. Dann ist sie allerdings nur in diesem Theme verwendbar.Ist also prinzipiell nicht komplizierter oder umfangreicher als der wp-Code.
Stefan
Fehler warning: Invalid argument
am 30.11.2008 - 23:06 Uhr
Bei Verwendung des Codes bekomm ich folgenden Fehler über jedem! Artikel angezeigt:
warning: Invalid argument supplied for foreach() in /web/1/000/014/453/10569/htdocs/drupal/includes/common.inc(1547) : eval()'d code on line 26.
Kurze Erklärung was ich gemacht hab:
1. neuen Block mit EingabeFormat PHP für den Bereich Inhalt
2. Sichtbarkeit auf PHP-Modus
3. folgenden Code rein
<?php
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$terms = taxonomy_node_get_terms($node);
$needle = array('microsoft');
/**
* terms nach gewünschten Kategorien durchsuchen und
* je nach Ergebnis Block (nicht) anzeigen
*/
return terms_contains($terms[$node->vid]['tid'], $needle);
}
/**
* Durchsucht ein Array von terms nach einem bestimmten Namen.
*
* @param $terms Array Array mit den zu durchsuchenden terms.
* @param $needle mixed Array oder String mit den zu findenden Namen.
* @return boolen TRUE wenn der/die Namen gefunden wurden, sonst FALSE.
*/
function terms_contains($terms, $needle) {
if (!is_array($needle)) {
$needle = array($needle);
}
foreach ($terms as $key => $term) {
if (in_array($term->name, $needle)) {
return TRUE;
}
}
return FALSE;
}
?>
Meine Seitenstruktur ist in etwa folgende: 5 Hauptkategorien und dann zu jedem Artikel in diesen Kategorien verschiedene Tags, die ja auch über Taxonomy laufen. Im Versuch hab ich nun den Tag "Microsoft" im Code eingegeben, damit der Inhalsblock eben nur erscheint, wenn einem Artikel der Tag "Microsoft" zugewiesen ist.
Was ich auch versucht habe war, einfach im Block "Nur auf den aufgelisteten Seiten anzeigen." auszuwählen und dort "tag/microsoft" reingeschrieben, Dann kommt zwar kein Fehler, aber es erscheint auch nicht der Block.
Hat da noch jemand eine Idee? Link zur Demo ist http://cms.w3projekt.com/ (ist nur eine Testseite)
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
... ist nicht der von Drupal emfohlene Weg
am 01.12.2008 - 01:44 Uhr
Das Ganze packst Du Dir dann in eine Datei (Vorschlag: [misc/scripts/block_taxonomy.inc]) und inkludierst diese Datei dann mittels
Diesen Vorschlag halte ich für ungünstig.
1.
Um PHP-Code zu platzieren kennt Drupal andere Techniken als diesen in Dateien zu schreiben und diese Dateien per include() einzubinden.
Ich lasse mich gern belehren, aber das Includen von Dateien um PHP-Code aufzunehmen ist nicht der von Drupal emfohlene und propagierte Weg.
Man kann es auch anders formulieren:
Wer diesen Weg beschreitet ist zu faul ein kleines Modul zu schreiben. Wobei ein Modul nicht mal zwingend erforderlich ist. Denn in einer Funktion kann man PHP-Code auch in die "template.php" einfügen und dann diese Funktion an den Stellen aufrufen wo man sie benötigt.
2.
Selbst wenn man Pkt. 1 realisiert ist beim nächsten Core-Upgrade mit hoher Warscheinlichkeit die Datei weg.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
strategische Ueberlegung fuer die Blocksteuerung
am 01.12.2008 - 02:02 Uhr
Stelle doch mal eine strategische Ueberlegung fuer die Blocksteuerung an. Stelle Dir dafuer die Frage: Bei welchen URL's tritt die Situation ein bzw. welche URL's kann es geben damit die Situation eintritt.
Die Situation nach der Du suchst ist den Block anzuzeigen.
Bei dieser Untersuchung wirst Du erkennen das es verschiedene Formen von URL's gibt in denn der Block angezeigt werden soll. Nicht alle Situationen lassen es zu per URL ueber arg() das Nodeobject zu laden um damit weiterfuehrend die Terms zu ermitteln.
Daraus ergibt sich das Du im PHP Code der Blocksichtbarkeits-Steuerung mehrgleisig fahren musst. Das Nodeobject ist lediglich ein Gleis.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
So kann man die Websiteperformance verschlechtern
am 01.12.2008 - 02:19 Uhr
Das ist Quatsch und realisiert eine unnütze Datenbankabfrage:
<?php
if ((arg(0) == 'node') && is_numeric(arg(1))) {
$node = node_load(arg(1));
$terms = taxonomy_node_get_terms($node);
?>
Der Quatsch besteht darin das man
<?php
$terms = taxonomy_node_get_terms($node);
?>
NICHT ausführen muss um an die Terms der Node heranzukommen. Da die Funktion taxonomy_node_get_terms() eine Datenbankabfrage ausführt wird somit eine überflüssige Datenbankabfrage produziert.
Wieso?
Kann jeder testen. Beide nachfolgenden Arrays sind identisch.
Array $terms mit taxonomy_node_get_terms()
<?php
$terms = taxonomy_node_get_terms($node);
?>
Array $node_terms aus dem Nodeobject:
<?php
$node_terms = $node->taxonomy;
?>
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Nodeobject für die Blocksichtbarkeits-Steuerung auswerten
am 01.12.2008 - 02:38 Uhr
Um die Terms aus dem Nodeobject für die Blocksichtbarkeits-Steuerung auszuwerten könnte man derart vorgehen:
<?php
return FALSE;
// Prüf-Array mit den Term ID's auf die zu prüfen ist
$check_terms = array(34, 78);
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
$node = node_load(arg(1));
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $tid => $term) {
if (array_key_exists($tid, $check_terms)) {
return TRUE;
}
}
}
}
?>
Es empfiehlt sich das Prüf-Array mit den Terms nicht mit deren Namen sondern mit deren ID's aufzubauen. Dadurch wird der Code von Namens-Änderungen der Terms nicht beeinflusst.
PS
Das ist der gesamte Code den man in den betreffenden Blöcken in der Blocksichtbarkeits-Steuerung (auf PHP Code umschalten nicht vergessen) verwendet um in Abhängigkeit bestimmter Terms einen Block anzuzeigen.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Danke quiptime für die
am 01.12.2008 - 13:05 Uhr
Danke quiptime für die ausführlichen Erläuterungen.
Allerdings funktioniert die Abfrage auch mit deinem Code noch nicht.
im Block habe ich jetzt eingefügt:
<?php
return FALSE;
// Prüf-Array mit den Term ID's auf die zu prüfen ist
$check_terms = array(34);
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $tid => $term) {
if (array_key_exists($tid, $check_terms)) {
return TRUE;
}
}
}
}
?>
Die 34 entspricht dem Tag "Microsoft".
Die grundlegende Struktur der Vokabulare und Begriffe ist folgende:
Vokabular: (Hauptkategorien) ID=1
darin als Begriff: (Informationstechnik) Term ID=2
Vokabular: (Unterkategorien als tags) ID=2
darin die eigentlichen Tags als Begriffe: (z.B. Microsoft) Term ID=34
Um auszuschließen das es am Template liegt habe ich mal bei "Nur auf den aufgelisteten Seiten anzeigen." den "tag/microsoft" eingegeben und dann wird der Block korrekt bei Aufruf der Kategorie angezeigt, allerdings noch nicht im Artikel, der den Tag "Microsoft" enthält.
Dann habe ich bei statt array(34) die Term-ID der Hauptkategorie noch zugefügt, weil ich dachte es besteht eine Abhängigkeit, also array(2, 34) aber auch dann wird der Inhaltsblock nicht dargestellt.
Nur warum es noch nicht geht ist mir ein Rätsel.
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
return
am 01.12.2008 - 14:30 Uhr
Moin!
Allerdings funktioniert die Abfrage auch mit deinem Code noch nicht.
...
<?php
return FALSE;
// ...
?>
Nur warum es noch nicht geht ist mir ein Rätsel.
Weil Du immer
FALSE
an den Block gibst. Somit "denkt" er immer, er müsse nicht angezeigt werden. Pack dasreturn FALSE;
mal hinter die letzte schließende Klammer.hth,
Stefan
PS @quiptime: mir ist sehr wohl bewusst, dass ein Minimodul hier der sauberste Weg wäre, es ging jedoch um eine schnelle und einfach Lösung. Und die includes kann man ja auch in einen anderen Ordner ([sites/all/includes] oder so) legen. :)
Hab ich, aber leider auch
am 01.12.2008 - 14:43 Uhr
Hab ich, aber leider auch ohne Erfolg,
<?php
// Prüf-Array mit den Term ID's auf die zu prüfen ist
$check_terms = array(34);
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $tid => $term) {
if (array_key_exists($tid, $check_terms)) {
return TRUE;
}
}
}
} return FALSE;
?>
Wenn ich den Artikel aufrufe, dem der Tag (in dem Fall 34) zugewiesen ist, erscheint der Block nicht.
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
Warum denn nicht über den Pfadnamen und AUTOPATH?
am 01.12.2008 - 14:56 Uhr
Weshalb weist Du denn Deinen Nodes nicht einfach einen Pfadnamen zu? Mit URL-Aliasen ( Modul Autopath ) und Deiner vorhandenen Taxonomie ist es dann doch kein Problem, die Blöcke der Rubrik "Sommer" zuzuweisen ...
Du gibts einfach unter "Pfadeinstellungen für Beiträge" als Pfad für die Beiträge im "Sommer" z.B. sommer/[title-raw] an.
Dann noch in den Blockkonfigurationen eingestellt, daß der entsprechende Block nur bei URLS mit sommer* angezeigt wird ...
Schon sollte es klappen! Hoffe, Dir vielleicht etwas einfacher geholfen zu haben.
-------------------------------------
Öfter mal was neues ... warum nicht mal DRUPAL :-) Meinen "Drupal Kampf" als Anfänger schildere ich mal unter http://www.thoor.de
Thoor die Pfadnamen sollen
am 01.12.2008 - 15:10 Uhr
Thoor die Pfadnamen sollen auf jeden Fall erhalten bleiben.
Ich hoffe das sich trotzdem eine Lösung findet.
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
return FALSE als 1. ist ein Logikfehler von mir
am 01.12.2008 - 15:37 Uhr
Sorry,
return FALSE als 1. ist ein Logikfehler von mir. Den damit wird der nachfolgende Code nicht mehr ausgefuehrt.
<?php
$check_terms = array(34);
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
$node = node_load(arg(1));
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $tid => $term) {
if (array_key_exists($tid, $check_terms)) {
return TRUE;
}
}
}
}
return FALSE;
?>
PS
Betreffs der sauberen Loesung mit dem Minimodul und so weiter.
Es gibt Leute die lesen hier nach und denen ist vermutlich nicht bewusst das Du eine schnelle Loesung meinst.
Die Change das sich die einfache und schnelle Loesung spaeter als unguenstige Loesung erweist ist sehr hoch. Daran aendert auch ein anderer Ordner fuer ein include nichts.
Ein Theme-Entwickler sollte nicht includen. Ein Modul-Entwickler kann/sollte dies durchaus praktizieren. Der Thraed hier laeuft aber unter dem Thema des Theming - und das insbesondere so lange es nicht um das Einbringen des PHP Code mittels eines Modules geht.
Es gibt noch einen Aspekt zu Gunsten des Platzieren des Code in einem Modul:
Ein Modul kann man deaktivieren - im GUI.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
ich habe jetzt mal quiptimes
am 01.12.2008 - 16:08 Uhr
ich habe jetzt mal quiptimes letzten Code für die Anzeige des Blocks versucht , aber klappt leider noch immer nicht.
<?php
// Prüf-Array mit den Term ID's auf die zu prüfen ist
$check_terms = array(34);
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
if (count($node->taxonomy) > 0) {
foreach ($node->taxonomy as $tid => $term) {
if (array_key_exists($tid, $check_terms)) {
return TRUE;
}
}
}
}
else {
return FALSE;
}
?>
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
Seltsames bei PHP Blocksteuerung mit D6 - Loesung
am 01.12.2008 - 16:28 Uhr
Eben gestestet und eine Seltsamkeit der Blocksteuerung mit PHP unter Drupal 6 festgestellt.
Dieser Code sollte funktionieren, ein Block wird aber nicht angezeigt:
<?php
$check_terms = array(1);
$output = FALSE;
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
$mynode = node_load(array('nid' => arg(1)));
if (count($mynode->taxonomy) > 0) {
foreach ($mynode->taxonomy as $tid => $term) {
if (array_key_exists($term->tid, $check_terms)) {
$output = TRUE;
}
}
}
}
return $output;
?>
Dieser Code funktioniert und zeigt den Block:
<?php
$check_terms = array(1);
$output = FALSE;
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
$mynode = node_load(array('nid' => arg(1)));
if (count($mynode->taxonomy) > 0) {
print ' '; // <<< --- ein Leerzeichen
foreach ($mynode->taxonomy as $tid => $term) {
if (array_key_exists($term->tid, $check_terms)) {
$output = TRUE;
}
}
}
}
return $output;
?>
Link zum Testen: http://quiptime.bplaced.net/node/3
Der Block erscheint ganz unten als "Huhu, bin sichtbar".
@holger@drupal.org,
vergiss die Zeile mit
<?php
$mynode = node_load(array('nid' => arg(1)));
?>
nicht.
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
Problem der Seltsamkeit geklaert.
am 01.12.2008 - 16:49 Uhr
Das seltsame Verhalten liegt in der Verwendung der PHP Funktion array_key_exists() begruendet. (Wow, haette ich nicht gedacht.)
Verwendet man statt dessen die PHP Funktion in_array() klappt es so wie es soll.
Damit funktioniert dieser Code und erledigt die ihm zugedachte Aufgabe:
<?php
$check_terms = array(1);
$output = FALSE;
if (arg(0) == 'node' && is_numeric(arg(1)) && !arg(2)) {
$mynode = node_load(array('nid' => arg(1)));
if (count($mynode->taxonomy) > 0) {
foreach ($mynode->taxonomy as $tid => $term) {
if (in_array($term->tid, $check_terms)) {
$output = TRUE;
}
}
}
}
return $output;
?>
-------------
quiptime
Nur tote Fische schwimmen mit dem Strom.
PHP Funktion in_array()
am 01.12.2008 - 17:37 Uhr
Das war die Lösung !!!
Vielen Dank an quiptime und alle Beteiligten.
Kurze Zusammenfassung für die Nachwelt:
Mit diesem Code kann man steuern, das Blöcke nur dann angezeigt werden, wenn man einen Artikel (node) aufruft, der vorher einem oder mehreren Tags oder einer Kategorie zugewiesen wurde - sozusagen inhaltsbasiert.
Interessant ist das vor allem bei Nutzung von Drupal als Weblog sowie zur inhaltsbasierten Steuerung von Werbung oder auch beliebigem anderen Content in Blöcken.
Beste Grüße, Holger
---
IT-News und IT-Jobs auf w3Projekt.com
Lösung
am 01.12.2008 - 22:51 Uhr
Argh, sonst bin ich doch einer der Ersten, die Freund google bemühen.
Hier nochmal gleiche Lösungen auf drupal.org :-).
http://drupal.org/node/64133#comment-125341
http://drupal.org/node/69076
Und natürlich gibt es auch ein Modul dafür! blockterm
Leider scheint die Portierung auf d6 eingeschlafen zu sein (allerdings gibt es einen wohl funktionierenden Patch zum Selberbauen).
Stefan