[ Milan Kragujevic @ 07.10.2013. 00:14 ] @
Napisao sam sinoć jednu malu klasu koja služi kao example routing sistem za moj blog jer nisam zadovoljan trenutnim rešenjem, pa me zanimaju kritike i analiza iskusnijih od mene.

Pattern delovi
- :m{NESTO}: - možda operator, string mora biti eskejpovan
- :>1a: slova, više od jednog
- :a: slova
- :>1an: slova i brojevi, više od jednog
- :an: slova i brojevi
- :>1n: brojevi, više od jednog
- :n: brojevi
- |i (na kraju) - case-insensitive operator

Primer koda
Code (php):

Class Example {
     public function hello($what) {
          echo "Hello, $what!";
     }
}
$router = new Router;
try {
     $router->bind('hello/:an::m{/}:', 'Example->hello'); // u slucaju pozivanja funkcije stavite naziv funkcije, a ako se funkcija nalazi u klasi stavite ImeKlase->ImeMetodeKlase. Metoda klase [b]mora biti[/b] public.
} catch (Exception $e) {
     echo "<b>An error occurred!</b><br/><pre>$e</pre>";
}
 
Taj primer će izbaciti Hello, [nešto] kada mu se pristupi sa adrese [putanja_do_web_roota]index.php/hello/[nešto]

Važno: Na početku index.php fajla pre include-ovanja ili require-ovanja svih ostalih fajlova morate definisati __INDEX__ sa vrednošću __FILE__.
Primer: const __INDEX__ = __FILE__;.

Izvorni kod klase
Code (php):

<?php
Class Router {
     private $request_uri;
     private $self;
     private $request_params;
     private $params;
     private $bundles;
     
     public function __construct() {
          $this->request_uri = $_SERVER['REQUEST_URI'];
          $this->self = basename(__INDEX__);
          $request_uri_array = explode($this->self, $this->request_uri);
          $this->request_params = end($request_uri_array);
          $this->request_params = rtrim(ltrim($this->request_params, '/'), '/');
     }
     
     private function call_function($func, $args = array()) {
          if(!is_array($args)) {
               throw new Exception("call_function expects second parameter to be an array, ".gettype($args)." given");
          } else {
               if(!preg_match('/\->/ism', $func)) {
                    if(is_callable($func)) {
                         call_user_func_array($func, $args);
                    } else {
                         throw new Exception("Can't call the function $func");
                    }
               } else {
                    $func_data = explode('->', $func);
                    $class_name = $func_data[0];
                    $function_in_class = $func_data[1];
                    if(class_exists($class_name)) {
                         $class_instance = new $class_name;
                         if(method_exists($class_instance, $function_in_class)) {
                              call_user_func_array(array($class_instance, $function_in_class), $args);
                         } else {
                              throw new Exception("Can't call the method $function_in_class in class $class_name because the class' method doesn't exist.");
                         }
                    } else {
                         throw new Exception("Can't call the method $function_in_class in class $class_name because the class doesn't exist.");
                    }
               }
          }
     }
     
     private function pattern2regex($pattern) { //[0-9] |i
          $ins = false; // case insensitive
          if(preg_match('/|i/ism', $pattern)) {
               $ins = true;
               $pattern = str_replace('|i', '', $pattern);
          }
          $dictionary = array(
               '(' => '\(',
               '[' => '\[',
               ']' => '\]',
               '*' => '\*',
               '?' => '\?',
               ')' => '\)',
               '/' => '\/',
               '$' => '\$',
               '+' => '\+',
               '^' => '\^',
               '{' => '\{',
               '}' => '\}',
               '|' => '\|'
          );
          $quick_syntax = array(
               ':>1an:' => '((?:[a-z][a-z0-9_\-]*))', // alphanumerical, more than one
               ':an:' => '((?:[a-z0-9_\-]*))', // alphanumerical
               ':n:' => '(\d+)', //numerical
               ':>1n:' => '(\\d+)', //numerical, more than one
               ':>1a:' => '((?:[a-z][a-z]+))', // alpha only, more than one
               ':a:' => '((?:[a-z]+))' // alpha only
          );
          $pattern = str_replace(array_keys($dictionary), array_keys(array_flip($dictionary)), $pattern);
          $pattern = str_replace(array_keys($quick_syntax), array_keys(array_flip($quick_syntax)), $pattern);
          $pattern = preg_replace('/\:m\\\{([^\}]*?)\\\}:/ism', '([$1]?)', $pattern); // maybe block
          $pattern = '/'.$pattern.'/'.($ins?'i':'').'sm';
          return $pattern;
     }
     
     private function pattern_match($pattern) {
          $pattern_regex = $this->pattern2regex($pattern);
          return @preg_match($pattern_regex, $this->request_params);
     }
     
     private function get_url_values($pattern) {
          $pattern_regex = $this->pattern2regex($pattern);
          $url_values = array();
          if(preg_match_all($pattern_regex, $this->request_params, $values)) {
               foreach($values as $id => $value) {
                    if($id !== 0) {
                         $value1 = $value[0];
                         $url_values[] = $value1;
                    }
               }
          }
          return $url_values;
     }
     
     public function bind($pattern, $function, $params = array()) {
          $pattern = rtrim(ltrim($pattern, '/'), '/');
          extract($params, EXTR_PREFIX_SAME, "copy");
          if($this->pattern_match($pattern)) {
               $this->call_function($function, $this->get_url_values($pattern));
          }
     }
}
 


[Ovu poruku je menjao Milan Kragujevic dana 07.10.2013. u 22:03 GMT+1]

[Ovu poruku je menjao Milan Kragujevic dana 07.10.2013. u 22:13 GMT+1]
[ Milan Kragujevic @ 10.10.2013. 16:18 ] @
Bilo ko? :/