[PHP] Verifieren van pad in de url

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik bouw een cms met behulp van mod_rewrite url's. Het principe is als volgt:

http://www.website.com/fruit/appels/rood wordt omgezet naar
http://www.website.com/index.php?q=fruit/appels/rood
• ik explode $_GET['q'] naar een array: $array[0] = 'fruit'; $array[1] = 'appels'; $array[2] = 'rood'
• ik ga in de database op zoek naar het id van de gevraagde pagina (in dit geval "rood")

Bij het laatste punt heb ik een probleem. Stel de volgende tabel "nodes":
code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
+---------+----------------+-------------------+
| node_id | parent_id      | node_name         |
+---------+----------------+-------------------+
| 1       |                | home              |
+---------+----------------+-------------------+
| 2       | 1              | schoenen          |
+---------+----------------+-------------------+
| 3       | 2              | sportief          |
+---------+----------------+-------------------+
| 4       | 3              | rood              |
+---------+----------------+-------------------+
| 5       | 1              | fruit             |
+---------+----------------+-------------------+
| 6       | 5              | appels            |
+---------+----------------+-------------------+
| 7       | 6              | rood              |
+---------+----------------+-------------------+

Zie hier het probleem: ik heb de mogelijke paden

• schoenen/sportief/rood en
• fruit/appels/rood

Het probleem zit hier: hoe bepaal ik nu of ik de pagina met node_id 4 of node_id 7 moet laten zien? Antwoord: ik moet niet alleen kijken naar het laatste item in de querystring (in dit geval "rood") maar moet het gehele pad ("fruit/appels/rood") nalopen om uit te vinden welke pagina bedoeld wordt. Met andere woorden: "bestaat het gevraagde pad wel in de database?"

Tot nu toe heb ik dit (pseudo):
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
function check_pad($array, $i=0)
{
  db_query('SELECT node_id FROM nodes WHERE node_name = "'.$array[0].'"');

  // array[0] = 'fruit' -> resultaat van query = 5

  db_query('SELECT node_id FROM nodes WHERE parent_id = 5 and node_name = "'.$array[1].'"');

  // array[1] = 'appels' -> resultaat van query = 6

  db_query('SELECT node_id FROM nodes WHERE parent_id = 6 and node_name = "'.$array[2].'"');

  /* array[2] = 'rood' -> resultaat van query = 7
   * we zijn nu aan het einde van de array (die was count($array) = 3 groot)
   * en moeten nu node_id 7 retourneren */

  return 7;
}

Vragen:

• Is dit een goede manier om te verifieren met welke pagina ik van doen heb?
• Hoe verwerk ik dit in een recursieve functie?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • NMe
  • Registratie: Februari 2004
  • Laatst online: 09-09 13:58

NMe

Quia Ego Sic Dico.

Reveller schreef op maandag 22 november 2004 @ 23:13:
• Is dit een goede manier om te verifieren met welke pagina ik van doen heb?
Waarom niet? Het werkt, en zit simpel in elkaar.
• Hoe verwerk ik dit in een recursieve functie?
Ik heb een paar topics van je gevolgd. Waarom wil je zo graag alles recursief doen? Het staat intelligent, maar soms is een 'normaal' stuk code net zo goed of zelfs beter. :P

'E's fighting in there!' he stuttered, grabbing the captain's arm.
'All by himself?' said the captain.
'No, with everyone!' shouted Nobby, hopping from one foot to the other.


Acties:
  • 0 Henk 'm!

  • T-MOB
  • Registratie: Maart 2001
  • Laatst online: 22:34
Als het je om performance gaat zou ik het niet zo doen. Ik heb me laten vertellen dat queries nogal zwaar wegen. Een alternatief is om één maal alle "path-data" uit je database te halen en vervolgens je functies rond zo'n array opbouwen...
* T-MOB gaat even code opsnuffelen

O ja, $_URL komt overeen met de explode van jouw $_GET['q'].. :)
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
/**
 * In the codeblock, the node information is gathered. The output is as follows
 *
 * array $catNames (id => name) for all available categories/nodes
 * array $catParents (id => parent) for all available categories/nodes
 * array $namepath (0,1,2,3 => names) for the path to the relevant node
 * array $idPath (0,1,2,3 => id's) for the path in id's to the relevant node
 * 
 * int $lastnode is the relevant node. With this node all lower categories and files can be fetched.
 */

//treedata
$catData = catData(); // functie die alle node data uit de DB trekt
$catNames = $catData['name'];
$catParents = $catData['parent'];
unset ($catData);

//path
foreach ($_URL as $index => $node){ if($index) { $namePath[] = stripslashes(rawurldecode($node)); }}

if (!isset($namePath[0])) { $namePath[0] = $catNames[1]; }

//fetch id's with path
foreach ($namePath as $node)
{
    foreach($catNames as $nodeid => $nodename)
    {
        $FIRST = (!isset($lastnode));
    
        if ($node == $nodename && ($FIRST || $catParents[$nodeid] == $lastnode))
        {
            $idPath[] = $lastnode = $nodeid;
        }   
    }
    unset($lastnode);
}

//determine relevant node
$lastnode = end($idPath);

[ Voor 76% gewijzigd door T-MOB op 23-11-2004 00:20 ]

Regeren is vooruitschuiven


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
@NMe84 - ik doe het niet expres om intelligent over te komen :+ In veel kwesties zie ik geen andere oplossing dan recursief. Ook hier weer - omdat de lengte van het pad niet vastligt, moet ik volgens mij recursief werken. Mogelijke url's zijn:

www.site.com/autos/sportief/duits/bmw/m3
www.site.com/eten/brood/bolletjes/wit
www.site.com/producten/product_a

het is een cms...weet ik veel wat mijn (toekomstige ;) ) klanten ervan maken...(!)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Knutselsmurf
  • Registratie: December 2000
  • Laatst online: 17:10

Knutselsmurf

LED's make things better

TS, Ik denk dat je met je oorspronkelijke opzet behoorlijk in de richting zit. Je moet dan weliswaar voor ieder niveau 1 query uitvoeren, maar die zullen waarschijnlijk niet de bottlenek van je systeem zijn. Als je de queries die je uitvoert bekijkt, lijken ze wel erg op elkaar. Dat vraagt om een while-lusje, waarmee je je hele pad controleert. Het verschil tussen de eerste query en de andere twee is dat je bij de eerste geen parent invult. Om het helemaal goed te laten verlopen zou ik daar ook op een parent checken, namelijk of je eerste element wel netjes onder 'home' valt.

- This line is intentionally left blank -


Acties:
  • 0 Henk 'm!

  • Eärendil
  • Registratie: Februari 2002
  • Laatst online: 22:34
Reveller schreef op dinsdag 23 november 2004 @ 00:45:
@NMe84 - ik doe het niet expres om intelligent over te komen :+ In veel kwesties zie ik geen andere oplossing dan recursief. Ook hier weer - omdat de lengte van het pad niet vastligt, moet ik volgens mij recursief werken. Mogelijke url's zijn:
In plaats van recursief kan je het ook gewoon in een for-loop zetten, die net zo vaak doorlopen wordt als je items in je array hebt...

Acties:
  • 0 Henk 'm!

  • _js_
  • Registratie: Oktober 2002
  • Laatst online: 18-08 21:31
Als je bang bent dat veel queries te zwaar zijn kun je je pad ook in één dynamisch opgebouwde query controleren, met iets als:
SQL:
1
2
3
4
5
6
7
SELECT n3.node_id
FROM nodes n1
INNER JOIN nodes n2 ON n1.node_id = n2.parent_id 
INNER JOIN nodes n3 ON n2.node_id = n3.parent_id
WHERE n1.parent_id IS NULL
AND n2.node_name = 'fruit'
AND n3.node_name = 'appel'


Als je een dieper pad wilt controleren moet je extra joins en where voorwaarden toevoegen

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
_js_ schreef op dinsdag 23 november 2004 @ 09:21:
SQL:
1
2
3
4
5
6
7
SELECT n3.node_id
FROM nodes n1
INNER JOIN nodes n2 ON n1.node_id = n2.parent_id 
INNER JOIN nodes n3 ON n2.node_id = n3.parent_id
WHERE n1.parent_id IS NULL
AND n2.node_name = 'fruit'
AND n3.node_name = 'appel'


Die is origineel :) Ik vraag me af wat sneller is - een for of while loop, recursie met telkens een enkele query of deze laatste oplossing. Zijn er, buiten persoonlijke voorkeur, nog argumenten voor of tegen een bepaalde methode? Ik ben een hobbyist en nog nooit professioneel met PHP bezig geweest. Heb dus ook geen kennis over "best practices" of wat gewoon "not done" is. Vandaar deze vraag.

@T-MOB: ook ontzettend bedankt voor deze inbreng :) Ik ben nog even benieuwd naar de eventuele reakties over mijn laatste vraag, maar ga anders zeker met jouw voorbeeld aan de slag. Tot nu toe trok ik ook in het begin alle node info uit de database en ging met die array aan de slag. Gisteren ben ik echter gaan twijfelen aan deze werkwijze: wellicht is het uitvoeren van een reeks relatief eenvoudige queries beter (lees: sneller) dan het telkens doorlopen van een relatief grote array. Immers: het uitvoeren van een query kost maar ongeveer 0,0015 seconden...

[ Voor 42% gewijzigd door Reveller op 23-11-2004 10:13 ]

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

Verwijderd

@Reveller: Ik denk dat wanneer je CMS veel geupdated wordt het veel 'handiger' is om idd per pagina gewoon 1 kleine query te doen. En dan met de query die _JS_ genoemd heeft.
Pagina: 1