Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Expression du Pattern de routage #11

Closed
marc38gt opened this Issue · 35 comments

3 participants

@marc38gt

Dans ta fonction de parsage pour simplifier le pattern tu utilises :
$this->_pattern = '`^' . $this->_pattern . '$`'; ^ permet de dire que c'est le début de la chaîne et $ la fin de la chaîne.
Le problème c'est que dans ta fonction 'match()' pour croiser $_requestUri tu utilises :
preg_match($this->_pattern, $_requestUri, $matches, PREG_OFFSET_CAPTURE);

Alors à moins de spécifier une route du genre
'test' => new \Routing\Route('test', 'index', '/Taluu-Talus-Works/public/test.php'),
$matches sera vide

Du coup j'ai enlevé le ^ et le $ et je peux mettre ma route
'test' => new \Routing\Route('test', 'index', '/test),

Voilà j'espère que j'ai pas trop dit de conneries ^^

@Taluu
Owner

Justement, faire comme tu fais admettrais "/une/route/test" comme étant valide, et c'est pas le but recherché... seul "/test" doit convenir.

Libre à toi après de rajouter un marqueur :any devant...

Je considère ici que apache (ou autres) a bien été configuré, comme quoi le document root du projet soit bien attaché à /, et non pas devoir taper /public/index.php. Je devrais, je pense, insérer une config pour qu'on puisse déterminer le root (/Taluu-Talus-Works/public/ par exemple)...

@Taluu Taluu closed this
@Taluu Taluu was assigned
@Taluu Taluu reopened this
@CapMousse

Sinon, au lieux de faire une config, tu peux essayer de faire un script pour choper le root. (facilement faisable avec une comparaison de l'uri et du path du index.php je pense)

@Taluu
Owner

Oui, il est vrai. Je peux tenter de le devinner par la présence ou non d'un "index.php" dans l'url... Mais s'moche :s

@Taluu Taluu closed this
@Taluu Taluu reopened this
@CapMousse

Non non, pas utiliser le index.php.

Tu prend le pathinfo de ton index.php et l'uri actuelle.
Si tu te trouve avec /var/www/siteA/test/ et www.machin.com/siteA/test/module/truc tu peux déduire que le root est www.machin.com/siteA/test/
Par contre, dans le cas /var/www/siteB/root/ et www.machin.com/module/truc, le root est bien /

@Taluu
Owner

Moui je vois. Je peux en effet tenter un truc dans le routing pour le déterminer...

@CapMousse

Je déterre le topik !

Pour trouver le path du root, je fais comme ça:

<?php
 $doc_root = explode('/', $_SERVER['DOCUMENT_ROOT']);
 $web_dir = explode('/', WEB_DIR);
 $web_root = "/".implode('/' , array_diff($web_dir, $doc_root))."/";

voilou !

@Taluu
Owner
@Taluu
Owner

Après quelques tests, il en sort quelques problèmes qu'il faudra que je regarde un peu plus tard... En effet, si par exemple le root est /home/talus/talus-framework/, et que dans la requête on veut pouvoir intercepter une url /talus-framework/talus-works/quelque-chose, est interprété non pas en /talus-framework/quelque-chose, mais en quelque-chose, ce qui n'est pas vraiment le résultat attendu, qui devrait être /talus-framework/quelque-chose...

Il faut donc que je vois un peu le array_diff en profondeur.

edit testé pour twk.localhost/talus-framework/talus-framework/is/great, avec twk.localhost pointant vers /home/talus/web/Talus-Framework/public

Avec :

<?php
$server = array(
    'DOCUMENT_ROOT' => $_SERVER['DOCUMENT_ROOT'] . '/talus-framework',
    'REQUEST_URI' => $_SERVER['REQUEST_URI']
  );

$doc_root = explode('/', $server['DOCUMENT_ROOT']);
$web_dir = explode('/', $server['REQUEST_URI']);
$web_diff = array_diff($web_dir, $doc_root);
$web_root = implode('/' , array_filter($web_diff));

$web_root = preg_replace('`/{2,}`', '/', '/' . $web_root . '/');

var_dump($server, $doc_root, $web_dir, $web_diff, $web_root);

Résultat attendu :

array
  'DOCUMENT_ROOT' => string '/home/talus/web/Talus-Framework/public/talus-framework' (length=60)
  'REQUEST_URI' => string '/talus-framework/talus-framework/is/great' (length=41)

array
  0 => string '' (length=2)
  1 => string 'home' (length=5)
  2 => string 'talus' (length=8)
  3 => string 'web' (length=3)
  4 => string 'Talus-Framework' (length=15)
  5 => string 'public' (length=6)
  6 => string 'talus-framework' (length=15)

array
  0 => string '' (length=0)
  1 => string 'talus-framework' (length=15)
  2 => string 'talus-framework' (length=15)
  3 => string 'is' (length=2)
  4 => string 'great' (length=5)

array
  0 => string '' (length=0)
  2 => string 'talus-framework' (length=15)
  3 => string 'is' (length=2)
  4 => string 'great' (length=5)

string '/talus-framework/is/great/' (length=26)

Résultat obtenu :

array
  'DOCUMENT_ROOT' => string '/home/talus/web/Talus-Framework/public/talus-framework' (length=60)
  'REQUEST_URI' => string '/talus-framework/talus-framework/is/great' (length=41)

array
  0 => string '' (length=2)
  1 => string 'home' (length=5)
  2 => string 'talus' (length=8)
  3 => string 'web' (length=3)
  4 => string 'Talus-Framework' (length=15)
  5 => string 'public' (length=6)
  6 => string 'talus-framework' (length=15)

array
  0 => string '' (length=0)
  1 => string 'talus-framework' (length=15)
  2 => string 'talus-framework' (length=15)
  3 => string 'is' (length=2)
  4 => string 'great' (length=5)

array
  0 => string '' (length=0)
  3 => string 'is' (length=2)
  4 => string 'great' (length=5)

string '/is/great/' (length=10)
@CapMousse

Ah oui, je vois ton problème !

C'est le array_diff qui fait sauter ton talus-framework...
Personnellement, j'en ai pas besoin pour mon système de routing, le root (ici talus-framework) n'étant pas nécessaire.

Peut être voir avec une Regexp pour faire sortir le root ?

@Taluu
Owner

Ben t'y es pas, ca te concerne aussi en fait. Imagine, le guguss a une racine /talus-framework/... et veut avoir une route dont le pattern est /talus-framework/quelque-chose... Le routeur doit donc pouvoir identifier, sur /talus-framework/talus-framework/quelque-chose la partie qui l'intéresse, et sur laquelle il doit tester la validitié de /talus-framework/quelque-chose... !

Le problème c'est array_diff en fait, qui enleve TOUTES les occurrences qui s'entrecroisent... Soit, si dans un array j'ai array('blue', 'yellow'); et dans un autre j'ai array('blue', 'yellow', 'yellow', 'red');, mon résultat sera... array('red'), et non pas array('yellow', 'red'); ! Tu vois le problème ?

Mais l'idée de comparer avec $_SERVER['DOCUMENT_ROOT'] est quand même pas mal...

@CapMousse

Non justement, moi ça passe bien !

Pourquoi, parce que si le gugusse veut taper sur /shwaarkFramework/article/1/bidule, la route associée c'est article/[id]:num/[title]:any donc le routeur va valider la section /article/1/bidule.

Enfin, d’après tout mes test en local, ça marche bien avec ma méthode mais c'est peut être pas la meilleur ;)
(je bosse actuellement sur localhost/framework/web)

@Taluu
Owner

Et si il veut taper sur /framework/web/framework/web/article/1/bidule, tu fais quoi ? :) La route /framework/web/article/1/bidule ne sera pas validée, alors que /article/1/bidule le sera...

@Taluu
Owner

Après d'autres tests, avec non pas array_diff mais une fonction perso :

<?php
function myDiff(array $a, array $b) {
  foreach ($b as &$item) {
    $s = array_search($item, $a, true);

    if ($s !== false) {
      unset($a[$s]);
    }
  }

  return $a;
}

Ca marche.... Plus qu'a mettre en application. :)

@CapMousse

Niquel !

Sinon, pour ton exemple, j'ai poussé le vice un peu plus loin :
J'ai mon domaine local framework.loc avec une app framework et une route framework/test
L'url finale est donc : framework.loc/framework/framework/test
Après test, j'obtiens:
Routed url framework/test :\Dropbox\projets\framework\core\router.php at line 48 (0.012563)

It's work for me ! \ò/

@Taluu
Owner

Par contre, autre problème de taille, toujours avec ta méthode... Imaginons que je travaille sur twk.localhost/talus/framework/... Et que l'url entrée est twk.localhost/talus/talus/framework/is/great... Ben ca devient twk.localhost/talus/framework/is/great/ au lieu de twk.localhost/talus/talus/framework/is/great !

@CapMousse

En fait, le truc, ça serrait de parcourir à l'envers le tableau. Donc faire un array_reverse. Je sais pas si tu saisis mon idée...

@Taluu
Owner

Ben non, le problème serait toujours le même... Si il voit la valeur dans l'array, il la supprime... que ce soit au début ou à la fin. C'est le principe d'array diff, peu importe la position de la valeur...

Il faudrait perfectionner la fonction que j'ai posté, pour faire en sorte que ca regarde au début... Si y'a une vraisemblance au tout début (en gros, si dans talus/talus/framework, au début on a quelque chose comme /home/talus/web/talus-framework/, alors on filtre...)

@Taluu
Owner

D'ailleurs, je viens de tester sur localhost/Talus-Framework/public/... le problème, c'est que le DOCUMENT_ROOT ne pointe pas vers /home/talus/web/Talus-Framework/public/mais... /home/talus/web/ ! Donc du coup, ma route /Talus-Framework/public/ est invalide...

@CapMousse

Oh le fuu..

@Taluu
Owner

.. tout comme le htaccess est pas vraiment reconnu (normalement, si la root est sur /Talus-Framework/public/, avec le .htaccess dans public, si on y accède directement depuis localhost, ca merde... il est pas chargé, du coup il reconnaît pas /Talus-Framework/public/test/...

@Taluu
Owner

OK j'ai rien dit, c'est le htaccess qui foutait la merde (pas autorisé sur mon localhost). Sinon, je pense qu'on peut essayer de fonctionner avec PHP_SELF... En effet, il devrait toujours pointer vers le index.php !

Par exemple, si j'accède vers twk.localhost/test/it/belongs, et donc localhost/Talus-Framework/public/test/where/it/belongs, en travaillant avec un dirname sur $_SERVER['PHP_SELF'], j'ai toujours... '/test/where/it/belongs`. :)

Et, je pense que ca devrait également résoudre le problème du "talus/talus/framework/". :)

@Taluu
Owner

Script final :

<?php
function myDiff(array $a, array $b) {
  foreach ($b as &$item) {
    $s = array_search($item, $a, true);

    if ($s !== false) {
      unset($a[$s]);
    }
  }

  return $a;
}

$server = array(
    'DOCUMENT_ROOT' => $_SERVER['DOCUMENT_ROOT'],
    'REQUEST_URI' => $_SERVER['REQUEST_URI'],
    'PHP_SELF' => $_SERVER['PHP_SELF']
  );

$doc_root = array_filter(explode('/', $server['PHP_SELF']));
$web_dir = array_filter(explode('/', $server['REQUEST_URI']));
$web_diff = array('native' => array_diff($web_dir, $doc_root), 'php' => myDiff($web_dir, $doc_root));
$web_root = array();

foreach ($web_diff as $k => $v) {
  $web_root[$k] = preg_replace('`/{2,}`', '/', '/' . implode('/' , $web_diff[$k]) . '/');
}

var_dump($server, $doc_root, $web_dir, $web_diff, $web_root);

Retour :

array
  'DOCUMENT_ROOT' => string '/home/talus/web/Talus-Framework/public' (length=44)
  'REQUEST_URI' => string '/public/test/where/i/belong' (length=27)
  'PHP_SELF' => string '/index.php' (length=10)

array
  1 => string 'index.php' (length=9)

array
  1 => string 'public' (length=6)
  2 => string 'test' (length=4)
  3 => string 'where' (length=5)
  4 => string 'i' (length=1)
  5 => string 'belong' (length=6)

array
  'native' => 
    array
      1 => string 'public' (length=6)
      2 => string 'test' (length=4)
      3 => string 'where' (length=5)
      4 => string 'i' (length=1)
      5 => string 'belong' (length=6)

  'php' => 
    array
      1 => string 'public' (length=6)
      2 => string 'test' (length=4)
      3 => string 'where' (length=5)
      4 => string 'i' (length=1)
      5 => string 'belong' (length=6)

array
  'native' => string '/public/test/where/i/belong/' (length=28)
  'php' => string '/public/test/where/i/belong/' (length=28)

et sur localhost :

array
  'DOCUMENT_ROOT' => string '/home/talus/web/' (length=22)
  'REQUEST_URI' => string '/Talus-Framework/public/test/where/i/belong' (length=43)
  'PHP_SELF' => string '/Talus-Framework/public/index.php' (length=33)

array
  1 => string 'Talus-Framework' (length=15)
  2 => string 'public' (length=6)
  3 => string 'index.php' (length=9)

array
  1 => string 'Talus-Framework' (length=15)
  2 => string 'public' (length=6)
  3 => string 'test' (length=4)
  4 => string 'where' (length=5)
  5 => string 'i' (length=1)
  6 => string 'belong' (length=6)

array
  'native' => 
    array
      3 => string 'test' (length=4)
      4 => string 'where' (length=5)
      5 => string 'i' (length=1)
      6 => string 'belong' (length=6)

  'php' => 
    array
      3 => string 'test' (length=4)
      4 => string 'where' (length=5)
      5 => string 'i' (length=1)
      6 => string 'belong' (length=6)

array
  'native' => string '/test/where/i/belong/' (length=21)
  'php' => string '/test/where/i/belong/' (length=21)

... :)

@Taluu
Owner

Méthode plus rapide (près de 5/6 fois plus rapide... voir même 10 !) :

<?php

$server['REQUEST_URI'] = $_SERVER['REQUEST_URI'];
$server['PHP_SELF'] = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/') + 1);

if (strpos($server['REQUEST_URI'], $server['PHP_SELF']) === 0) {
  $server['REQUEST_URI'] = substr($server['REQUEST_URI'], strlen($server['PHP_SELF']));
}

var_dump($server['REQUEST_URI']);

Les résultats sont là... alors que la méthode avec le diff personnalisé met entre 0,00005s et 0,00016s, la méthode avec le strpos met 0,00002s à tout casser... le choix est vite fait :-°

@CapMousse

You just win the game !

@CapMousse

Et si tu veux extraire le root pour que l'utilisateur y ai facilement accès via une constante ou autre, tu peux faire :

<?php

$server['PHP_SELF'] = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/') + 1);

$web_root = '/';
if(($left = strpos($server['PHP_SELF'], 'index.php')) !== 0) {
    $web_root = substr($server['PHP_SELF'], 0, $left);
}

var_dump($web_root);

Dans mon cas, si je tape sur framework.loc/web/test/api/machin, mon root est bien /web/

@Taluu
Owner

Tu t'es planté, c'est === 0 et pas !== 0. Sinon, c'est si le root à enlever n'est pas au début de la chaine à vérifier :)

@CapMousse

Non justement, si par exemple index.php est en début de chaîne, ça veut dire que le root est bien /.

Par contre, si le PHP_SELF retourne un truc du style /machin/truc/index.php alors le root correspond à /machin/truc/. Il faut donc faire un substr sur toutes les valeur différente de 0

@Taluu
Owner

Ah j'avais pas vu que tu regardais sur "index.php". Externaliser le web_root... Ouais, ca peut être une idée, j'en prendrai compte.

enfin, ca reste des opérations un peu en trop je pense... pour ce qu'on cherche à faire. OSEF du root, le dév est censé le savoir... Au pire, il utilise PHP_SELF qui lui donne (et c'est ce qui est utilisé par la manip)

@CapMousse

Je pense plus aux intés qui bossent sur les vues ;)

Si t'es en local/test/recette... le root change, ça permet de le faire automatiquement.

@Taluu Taluu closed this in ddbf636
@Taluu Taluu closed this issue from a commit
@Taluu fixes #11 : enhance the request support for the routing part
fixes other things regarding accessors
5d6cc80
@Taluu Taluu closed this in 5d6cc80
@Taluu
Owner

Done :)

@Taluu
Owner

Hum j'y pense : PHP_SELF ne renvoit pas index.php, mais /index.php (ou /root/index.php). ton code sera donc toujours faux. :)

D'où le besoin de regarder le dernier /.... Si sa position est 0, alors pas de web root, sinon oui. C'est comme ca que je procède...

@CapMousse

Dans ce cas :

<?php

$server['PHP_SELF'] = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/') + 1);

if(($left = strpos($server['PHP_SELF'], 'index.php')) === 0) {
    $server['URL'] = $server['PHP_SELF'];
}else{
    $server['URL'] = substr($server['PHP_SELF'], 0, $left);
}
@Taluu
Owner

Pourquoi tu t'emmerdes... Un simple

<?php

$phpSelf = substr($_SERVER['PHP_SELF'], 0, strrpos($_SERVER['PHP_SELF'], '/') + 1);

suffit ! Pour /index.php, tu as /, pour /quelque/chose/index.php, tu as /quelque/chose/, ... C'est ce que tu veux, non ? Et Si tu veux vraiment avoir accès à l'url entière, tu ajoute HTTP_HOST devant...

@CapMousse

Je vais dormir moi.

@CapMousse
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.