Seite 1 von 2
vpSitemap und aktive Kategorie
Verfasst: So 23. Dez 2007, 17:05
von kloevekorn
Hallo.
Die vpSitemap ist so wunderbar, dass ich sie gerne als Navigation mit immer aufgeklappten Unterkategorien einsetzen möchte.
Leider fehlt dafür die Kennzeichnung der aktuellen Kategorie.
Wie ich meine zu erkennen, findet im Code keine Abfrage nach der aktuellen Kategorie statt. Ich habe versucht, eine solche Abfrage einzubasteln, aber bislang ohne Erfolg. Und selbst, wenn es mir irgendwann gelingt ...
- es soll nicht übermäßig Systemlast erzeugen
- und es muss mehrsprachenfähig sein.
Ich vermute, dass das prinzipiell einfach sein müsste. Kann jemand Fähiges eine solche Codezeile bauen?
Ich bedanke mich für euern Gehirnschmalz.
Code: Alles auswählen
/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname : vpSitemap 0.4
* Author : Ingo van Peeren
* Copyright : Ingo van Peeren (ingo@van-peeren.de)
* Created : 2005-01-14
* Modified : 2006-09-07
* Credits : Nik Wyss & juergen@sotonic.de
************************************************/
// Includes
cInclude("frontend", "includes/functions.navigation.php");
// CMS_VALUES initialisieren
$anzahlEbenen = "CMS_VALUE[1]";
$startkategorie = "CMS_VALUE[0]";
$ebeneNullAnzeigen = "CMS_VALUE[2]";
function vpSitemap($kategorie=0, $level)
{
global $lang, $client, $cfg, $startkategorie, $anzahlEbenen, $ebeneNullAnzeigen;
$db = new DB_Contenido;
$sql = "SELECT
*
FROM
".$cfg["tab"]["cat_tree"]." AS A,
".$cfg["tab"]["cat"]." AS B,
".$cfg["tab"]["cat_lang"]." AS C
WHERE
A.idcat=B.idcat
AND B.idcat=C.idcat
AND C.idlang='$lang'
AND B.idclient='$client'
AND B.parentid=$kategorie
AND level <= $anzahlEbenen
AND C.visible=1
ORDER by A.idtree";
$db->query($sql);
$treffer = $db->num_rows();
if ($treffer) {
if ($kategorie == $startkategorie) $result .= "\n" . str_repeat (" ", ($level * 4)) . "<ul id=\"sitemap\">\n";
else $result .= "\n" . str_repeat (" ", ($level * 4) + 4) . "<ul>\n";
}
while ($db->next_record())
{
$visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
if ($visible) {
$lvl = $db->f("level");
$result .= str_repeat (" ", ($lvl * 4) + 2);
if (($lvl > 0) || ($ebeneNullAnzeigen)) {
$result .= '<li><a href="front_content.php?idcat='.$db->f("idcat").'&lang='.$lang.'&client='.$client.'" title="' . mi18n("Ebene") . ' '.$lvl.': ' . $db->f("name") . '">' . $db->f("name") . '</a>' . vpSitemap($db->f("idcat"), $lvl) . "</li>\n";
}
else {
$result .= "<li> ".vpSitemap($db->f("idcat"), $lvl) . "</li>\n";
}
}
}
if ($treffer) {
if ($kategorie == $startkategorie) $result .= str_repeat (" ", ($level * 4));
else $result .= str_repeat (" ", ($level * 4) + 4);
$result .= "</ul>\n";
$result .= str_repeat (" ", ($level * 4) + 2);
}
return($result);
}
$sql = "SELECT
level
FROM
".$cfg["tab"]["cat_tree"]."
WHERE
idcat=$startkategorie";
$db->query($sql);
$db->next_record();
$startEbene = $db->f("level") + 1;
$anzahlEbenen += $startEbene;
if ($startkategorie==0) {
if ($ebeneNullAnzeigen) $anzahlEbenen--;
$startEbene--;
}
echo vpSitemap($startkategorie, $startEbene);
?>
Verfasst: So 23. Dez 2007, 17:56
von tono
Der Code ist so gut wie unlesbar. Ist irgendwie einmal zuviel durch htmlspecialchars gelaufen.
Irgendwo glabe ich zu lesen "result.=" in dieser Zeile steht auch $db->f("idcat").
Dort wird dein Link zusammengeschustert. Dort in der Gegend kannst Du mit if($db->f('idcat')==$idcat) etwas anhängen, umbauen (z.B. css-Klasse) für die aktuelle Kategorie.
Verfasst: So 23. Dez 2007, 22:22
von kloevekorn
tono hat geschrieben:Der Code ist so gut wie unlesbar. Ist irgendwie einmal zuviel durch htmlspecialchars gelaufen.
Irgendwo glabe ich zu lesen "result.=" in dieser Zeile steht auch $db->f("idcat").
Dort wird dein Link zusammengeschustert. Dort in der Gegend kannst Du mit if($db->f('idcat')==$idcat) etwas anhängen, umbauen (z.B. css-Klasse) für die aktuelle Kategorie.
Beim Code muss ich dir recht geben, phptidy.php hat es leider auch nicht schöner gemacht.
Aber zu deinem Vorschlag: das habe ich auch versucht:
An dieser Stelle
Code: Alles auswählen
$visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
if ($visible) {
/* echo "kategorie dbidcat: ".$db->f("idcat")."\n"; */
$lvl = $db->f("level");
Code: Alles auswählen
if ($db->f('idcat')!=$idcat){echo "yes";} else {echo "no";}
Code: Alles auswählen
if ($db->f('idcatlang')!=$idcat){echo "yes";} else {echo "no";}
"==" gibt "yes" für jeden Eintrag aus. != gibt "no" aus.. Im Modul wird m.E. die aktuelle Kategorie nicht abgefragt. Gibt es da vielleicht eine globale Variable oder sowas?
In den Funktionen in der functions.navigation.php kann ich so eine Funktion auch nicht entdecken. Die Abfragen aus der Hauptnavigation kann ich nicht übertragen, außerdem soll die Funktion schlank sein und das Modul mehrsprachefähig.
Ich brauch wohl noch ne DB-Abfrage.
Wenn nach den Tagen jemand noch einen Vorschlag hat, wäre ich sehr dankbar. Sollte ich nach den Tagen eine Lösung finden, werde ich sie posten. Bis dann ist das Problem offen.
Frohe Weihnachten!
Verfasst: Di 25. Dez 2007, 21:58
von tono
Oh, sorry hab nicht richtig hingeguckt. Das ganze passiet ja in einer Function. Du muss natürlich noch die Zeile
Code: Alles auswählen
global $lang, $client, $cfg, $startkategorie, $anzahlEbenen, $ebeneNullAnzeigen;
um $idcat ergänzen.
Wenn das auch nicht klappt, sag mal was var_dump($idcat) ausspuckt.
Verfasst: Mi 26. Dez 2007, 10:58
von kloevekorn
Vielen, vielen Dank! So funktioniert es. Klasse!
Wird es auch mehrsprachig funktionieren?
Der vollständige Output der vpSitemap mit Darstellung der aktiven Kategorie (funzt mit dem original-Input der vpSitemap):
Code: Alles auswählen
<?php
/***********************************************
* CONTENIDO MODUL - OUTPUT
*
* Modulname : vpSitemap 0.4
* Author : Ingo van Peeren
* Copyright : Ingo van Peeren (ingo@van-peeren.de)
* Created : 2005-01-14
* Modified : 2006-09-07, 2007-12-26 Kloevekorn (credits: Tono)
* Credits : Nik Wyss & juergen@sotonic.de
************************************************/
// Includes
cInclude("frontend", "includes/functions.navigation.php");
// CMS_VALUES initialisieren
$anzahlEbenen = "CMS_VALUE[1]";
$startkategorie = "CMS_VALUE[0]";
$ebeneNullAnzeigen = "CMS_VALUE[2]";
function vpSitemap($kategorie=0, $level)
{
global $lang, $client, $cfg, $startkategorie, $anzahlEbenen, $idcat, $ebeneNullAnzeigen;
$db = new DB_Contenido;
$sql = "SELECT
*
FROM
".$cfg["tab"]["cat_tree"]." AS A,
".$cfg["tab"]["cat"]." AS B,
".$cfg["tab"]["cat_lang"]." AS C
WHERE
A.idcat=B.idcat
AND B.idcat=C.idcat
AND C.idlang='$lang'
AND B.idclient='$client'
AND B.parentid=$kategorie
AND level <= $anzahlEbenen
AND C.visible=1
ORDER by A.idtree";
$db->query($sql);
$treffer = $db->num_rows();
if ($treffer) {
if ($kategorie == $startkategorie) $result .= "\n" . str_repeat (" ", ($level * 4)) . "<ul id=\"sitemap\">\n";
else $result .= "\n" . str_repeat (" ", ($level * 4) + 4) . "<ul>\n";
}
while ($db->next_record())
{
$visible = checkCatPermission($db->f("idcatlang"),$db->f("public"));
if ($visible) {
/* echo "kategorie dbidcat: ".$db->f("idcat")."\n"; */
/*sollte es mit Sprachen Probleme geben, dann ggfls. idcat mit idcatlang vertauschen*/
if ($db->f("idcat")==$idcat){$class=' class="active"';} else {$class="";} /**/
$lvl = $db->f("level");
$result .= str_repeat (" ", ($lvl * 4) + 2);
if (($lvl > 0) || ($ebeneNullAnzeigen)) {
$result .= '<li'.$class.'><a href="front_content.php?idcat='.$db->f("idcat").'&lang='.$lang.'&client='.$client.'" title="' . mi18n("Ebene") . ' '.$lvl.': ' . $db->f("name") . '">' . $db->f("name") . '</a>' . vpSitemap($db->f("idcat"), $lvl) . "</li>\n";
}
else {
$result .= "<li> ".vpSitemap($db->f("idcat"), $lvl) . "</li>\n";
}
}
}
if ($treffer) {
if ($kategorie == $startkategorie) $result .= str_repeat (" ", ($level * 4));
else $result .= str_repeat (" ", ($level * 4) + 4);
$result .= "</ul>\n";
$result .= str_repeat (" ", ($level * 4) + 2);
}
return($result);
}
$sql = "SELECT
level
FROM
".$cfg["tab"]["cat_tree"]."
WHERE
idcat=$startkategorie";
$db->query($sql);
$db->next_record();
$startEbene = $db->f("level") + 1;
$anzahlEbenen += $startEbene;
if ($startkategorie==0) {
if ($ebeneNullAnzeigen) $anzahlEbenen--;
$startEbene--;
}
echo vpSitemap($startkategorie, $startEbene);
?>
Verfasst: Mi 26. Dez 2007, 22:42
von tono
kloevekorn hat geschrieben:Wird es auch mehrsprachig funktionieren?
Wenn das Original mehrsprachenfähig ist, schon. Die Ergänzug ändert da eigentlich nix.
Verfasst: Di 22. Jan 2008, 14:06
von kloevekorn
Hallo,
ich möchte eine weitere Funktionalität integrieren. Und zwar soll neben der allgemeinen Aufgeklapptheit des Kategorienbaums, auf beispielsweise zwei Ebenen, die aktuelle kategorie noch eine Ebene weiter aufgeklappt werden.
Beispiel: Ich zeige standardmäßig zwei Kategorienlevel an, nur die jeweils aktive Kategorie wird auf Level 3 aufgeklappt.
Nun werkel ich am Code rum und ich habe keinen Peil, wie ich da ansetzen soll.
Ich habe bereits das Flag "a" für die aktive Kategorie. Aber ich bekomme das nicht mit der Ausgabe der Ebenen verknüpft ...
Konfiguriere ich im Input am besten die Anzeige auf drei Ebenen und zeige bei nicht-akiven kategorien nur zwei an?
Konfiguriere ich auf zwei Ebenen, mache in der aktiven Kategorie eine Extra-Abfrage?
Wo muss ich überhaupt ansetzen? In der zweiten DB-Abfrage, ganz unten im Code?:
Code: Alles auswählen
$sql = "SELECT
level
FROM
".$cfg["tab"]["cat_tree"]."
WHERE
idcat=$startkategorie";
$db->query($sql);
$db->next_record();
$startEbene = $db->f("level") + 1;
$anzahlEbenen += $startEbene;
if ($startkategorie==0) {
if ($ebeneNullAnzeigen) $anzahlEbenen--;
$startEbene--;
}
echo vpSitemap($startkategorie, $startEbene);
Ich verstehe leider nichtmal den Unterschied zwischen ersten und zweiten SQL-Block (wird der zweite Block entfernt, wird nur Level 1 angezeigt), aber ich versteh das Zusammenspiel nicht.
Hat jemand vielleicht einen Tipp? Danke!
Verfasst: Mi 23. Jan 2008, 17:16
von kloevekorn
Mein Basteln hat leider noch keinen Erfolg gezeigt. Theoretisch erscheint mir am erfolgversprechendsten, bzw. meinen PHP-Fähigkeiten angepasst, folgendes zu sein:
Um die aktive Kategorie zu kennzeichnen, vergebe ich bereits der aktiven Kategorie ein Flag "a". In dem gleichen Block habe ich eine DB-Abfrage eingebaut, die mit ein wenig Glück alle Level der aktuellen Kategorie ausgeben sollte.
Tut sie aber nicht, Syntax ist okay, im Frontend gibt es aber eine Memory-Fehlermeldung:
Fatal error: Out of memory (allocated 6815744) (tried to allocate 786466 bytes) in /home/..../cms/front_content.php(882) : eval()'d code on line 163
Klingt für mich nach bösem Programmierfehler und Ärger mit dem Hoster.
Kann jemand einen Tipp geben, wie es besser geht?
Danke!
Code: Alles auswählen
/*sollte es mit Sprachen Probleme geben, dann ggfls. idcat mit idcatlang vertauschen?*/
if ($db->f("idcat")==$idcat)
{$id=' id="active"';
$flag="a";
/* Anfang query2 - weitere Ebenen der _aktuellen_ Kategorie abfragen*/
$db2 = new DB_Contenido;
$sql2 = "SELECT
*
FROM
".$cfg["tab"]["cat_tree"]." AS A,
".$cfg["tab"]["cat"]." AS B,
".$cfg["tab"]["cat_lang"]." AS C
WHERE
B.parentid=$idcat
AND C.visible=1
ORDER by A.idtree";
$db2->query($sql2);
$treffer2 = $db2->num_rows();
/*Ende query2*/}
Verfasst: Mo 4. Feb 2008, 16:49
von kloevekorn
Mein Wunsch ist zu kompliziert für mich - ich bekomme es nicht hin.
Ich habe folgende Seitenstruktur:
Code: Alles auswählen
Level0
Level1.1
Level1.2
Level1.3
Level2.1
Level2.2
Level3.1
Level3.2
Level1.4
Level2.3
Level3.3
Level4.1
Level4.2
Level3.4
Level2.4
Level1.5
- Ich möchte immer Level 1+2 anzeigen.
- Wenn aktuelles Level 2, dann die Unterkategorien Level3, die diesen Parent haben (diese Option als optional einrichten).
- wenn aktuelles Level 3, Anzeige der Kategorien Level 3 mit dem selben direkten Parent
- wenn aktuelles Level 4, Anzeige der Kategorien Level 3 mit gleichem Parent und Level 4 mit dem selben direkten Parent.
Es handelt sich um also um eine Kombination aus Sitemap und herkömmlicher Aufklappnavigation für die Ebenen (2), 3+4. Unterschiedliche Konfiguration der vpSitemap geht nicht, weil die angezeigten Ebenen 3+4 die Bedingung des selben Parent haben sollen.
Kann das möglicherweise jemand für mich (gg. Bezahlung) fachgerecht umsetzen? Geht das überhaupt fachgerecht mit einem vernünftigen Maß an DB-Abfragen?
Kommentare, Fragen, Vorschläge, Angebote gerne hier in die Box.
Verfasst: Mo 4. Feb 2008, 22:34
von tono
Ist zwar keine VP-Sitemap mehr, ist aber als Navigation besser geeignet, weil keine SQL-Statements in der Rekursion mehr ausgeführt werden.
Code: Alles auswählen
<?php
$db2 = new DB_contenido();
$sql = "
SELECT cat.idcat, cat.parentid, tree.level, lang.name
FROM `con_cat` AS cat
JOIN `con_cat_tree` AS tree ON ( cat.idcat = tree.idcat )
JOIN `con_cat_lang` AS lang ON ( lang.idcat = tree.idcat
AND lang.idlang =$lang
AND lang.visible = 1
AND lang.public = 1)
WHERE cat.idclient =$client
AND (
tree.level <3
)
OR (
tree.level =3
AND cat.parentid =$idcat
)
OR (
(
tree.level =3
OR tree.level =4
)
AND cat.parentid = (
SELECT parentid
FROM `con_cat` AS cat2
WHERE cat2.idcat =$idcat )
)
OR (
tree.level =3
AND cat.parentid = (
SELECT cat4.parentid
FROM `con_cat` AS cat3, `con_cat` AS cat4
WHERE cat3.idcat =$idcat
AND cat4.idcat = cat3.parentid )
) ORDER BY tree.level;
";
$db2->query($sql);
$nav=array();
while ($db2->next_record())
{
$nav[$db2->f('parentid')][$db2->f('idcat')]=$db2->f('name');
}
//echo "<pre>"; #Debugoutput
//print_r($nav);
//echo "</pre>";
function output($parentid)
{
global $nav;
if (is_array($nav[$parentid]))
{
echo "\n<ul>\n";
foreach ($nav[$parentid] as $id => $name)
{
echo "<li><a href=\"front_content.php?idcat=$id\">$name</a>";
output($id);
echo "</li>\n";
}
echo "</ul>\n";
}
}
output (1);
?>
Die id des Baumes, für den die Navigation erstellt werden soll übergibst Du in der letzten Zeile dem Aufruf für Output.
Da Subselects verwendet werden,
könnte es Probleme mit Mysql 3.23 geben
Verfasst: Di 5. Feb 2008, 10:25
von kloevekorn
Das ist echt der Hammer! Funktioniert!
Ich staune und bedanke mich herzlich.
Verfasst: Di 5. Feb 2008, 15:35
von kloevekorn
Du fragst im ersten SQL-Statement auch das Level ab. Dieses würde ich gerne jedem einzelnen Navi-Eintrag hinzufügen (class="level1" zum Beispiel).
Die Abfrage des Levels gelingt auch ($db2->f('level')]) aber dann muss man doch wohl das Array mit dem Level füllen.
Ich vermute hier ein "Array von Arrays" ??:
Code: Alles auswählen
$nav[$db2->f('parentid')][$db2->f('idcat')]=$db2->f('name');
Ich finde es von der Klammersetzung und dem "="-Zeichen äußerst kurios

- wie bekomme ich denn nun das level in das Array?
Vielen Dank nochmal für diese Klasseumsetzung!
Verfasst: Di 5. Feb 2008, 15:46
von tono
So:
Code: Alles auswählen
$nav=array();
while ($db2->next_record())
{
$nav[$db2->f('parentid')][$db2->f('idcat')]['name']=$db2->f('name');
$nav[$db2->f('parentid')][$db2->f('idcat')]['level']=$db2->f('level');
}
function output($parentid)
{
global $nav;
if (is_array($nav[$parentid]))
{
echo "\n<ul>\n";
foreach ($nav[$parentid] as $id => $cat)
{
echo "<li class=\"$cat['level']\"><a href=\"front_content.php?idcat=$id\">$cat['name']</a>";
output($id);
echo "</li>\n";
}
echo "</ul>\n";
}
}
Verfasst: Di 5. Feb 2008, 17:24
von kloevekorn
Unglaublich - ich bewundere das! Du hast ja noch eine Menge umgeschrieben.
Vielen, vielen Dank! Funktioniert super!
Verfasst: Di 5. Feb 2008, 17:36
von kloevekorn
doch ein kleines Problem?
bei Reload ändert sich alle paarmal die Reihenfolge der Kategorien, nicht immer, aber immer mal wieder. Manchmal richtig sortiert (mit Ausnahme genau einer, der ersten Kategorie), im Wechsel dann wieder wirrer.
Das Muster der Sortierung ist nicht einfach zu erkennen, es scheint, dass Level1 wirr sortiert wird.
Eine Idee?