ФорумСообществоПрофессиональная деятельностьВзаимопомощь → Нужен разбор URL как в WP

Нужен разбор URL как в WP

  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 13:26, спустя 4 минуты 16 секунд

    ну вобщем зачет. свой вариант я выложу позже. он пока только вызревает в голове
    ιιlllιlllι унц-унц
  • Givi

    Сообщения: 2284 Репутация: N Группа: Адекваты

    Spritz 29 апреля 2009 г. 14:11, спустя 45 минут 19 секунд

    phpdude, я уже привел свои доводы, что в полные условия для универсального модуля вписаться невозможно, если не менять моск на два полужопия (в смысле, если писать так, чтоб оно работало и быстро и корректно и чтоб потом можно было поправить что-то). А твой пример вполне понятен. Хотя я сам делал все по-другому (у меня была четкая привязка к структуре движка, и ниипет).
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 14:36, спустя 24 минуты 57 секунд

    Givi, ну обрисуй как у тебя работает, хотя тема про настраиваемые правила, можно сравнить для полноты картины с жесткими.
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 14:39, спустя 2 минуты 25 секунд

    <?
    $url = "/archive/2009/27/08/256/buy viagra.html";
    $pattern = "/archive/%date%/%id%/%title%";

    class WPUrls
    {
    private $_groups;
    private $_params;

    public function parse($url,$pattern)
    {
    if(!preg_match("#^".$this->compileRegexp($pattern)."#ism",$url,$m))
    {
    return false;
    }

    $return = array();
    foreach($this->_groups as $group=>$null)
    {
    $return[$group] = $m[++$i];
    }
    return $return;
    }

    public function addParam($name,$regexp)
    {
    $this->_params[$name] = $regexp;
    }

    private function compileRegexp($pattern)
    {
    $this->_groups = array();
    if(!$this->_params)
    {
    return $pattern;
    }

    foreach($this->_params as $i=>$reg)
    {
    if(($pos = stripos($pattern,"%$i")) !== false)
    {
    $this->_groups[$i] = $pos;
    $pattern = str_ireplace("%$i%",$reg,$pattern,$replaced);
    }
    }
    asort($this->_groups);
    return $pattern;
    }
    }

    $wpurls = new WPUrls();
    $wpurls->addParam('date','(\d{4}/\d{2}/\d{2})');
    $wpurls->addParam('title','(.*?)(?:\.html)?$');
    $wpurls->addParam('id','(\d+)');

    $params = $wpurls->parse($url,$pattern);
    print_r($params);


    как вам такой классец? ;)

    имхо ахуеннее в разы :)
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 14:45, спустя 6 минут 35 секунд

    рано плюсанул чтоли? :)
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 14:47, спустя 1 минуту 19 секунд


    рано плюсанул чтоли? :)
    + реализация значительно пооптимизированнее ))) ибо выкинул лишние регулярки.
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 29 апреля 2009 г. 14:58, спустя 11 минут 38 секунд

    я бы чуть подправил:

    $wpurls = new WPUrls($url);

    foreach($patterns as $p)
    if ($result = $wpurls->parse($p))
    break;

    ιιlllιlllι унц-унц
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:02, спустя 19 дней 18 часов 3 минуты

    helldude, я тебя боюсь :) еще раз спасибо за код. я на его основе сделал себе такой класс:

    <?php

    class QB_Url
    {
    public static
    $controller = NULL,
    $params = NULL;

    public static function lookupRoute($uri = NULL)
    {
    if (is_null($uri))
    {
    /*
    // IIS is troublemaker
    if (!isset($_SERVER['REQUEST_URI']))
    {
    // for IIS7
    if (isset($_SERVER['HTTP_X_ORIGINAL_URL']))
    {
    $_SERVER['REQUEST_URI'] = $_SERVER['HTTP_X_ORIGINAL_URL'];
               }
    // for IIS6                                                /
    else
    {
    $_SERVER['REQUEST_URI'] = $_SERVER['PHP_SELF'];
    if (isset($_SERVER['QUERY_STRING']) && !empty($_SERVER['QUERY_STRING']))
    $_SERVER['REQUEST_URI'] .=  '?'.$_SERVER['QUERY_STRING'];
    }
    }
    */
    $uri = $_SERVER['REQUEST_URI'];
    }

    if (!isset(QB::$config['routes']) || !isset(QB::$config['route_tokens']))
    trigger_error('Routes are not set', E_USER_ERROR);

    $basePath = QB::$config['path'];
    if (($len = strlen($basePath)) > 0 && strpos($uri, $basePath) === 0)
    $uri = substr($uri, $len);

    $routes = QB::$config['routes'];
    self::$_tokens = QB::$config['route_tokens'];

    /*
    echo 'uri="'.$uri.'"<br /><br />'."\n";
    */
    foreach ($routes as $routeId => $pattern)
    {
    $compiled = self::compileRoute($pattern);
    /*
    echo '<i>'.$routeId.'</i>: "'.$pattern.' => "'.$compiled.'", ';
    print_r(self::$_vars);
    echo "<br />\n";
    */
    if(preg_match('#^'.$compiled.'#ism', $uri, $matches))
    {
    self::$params = array();
    $i = 0;
    foreach(array_keys(self::$_vars) as $id)
    self::$params[$id] = $matches[++$i];

    return self::$controller = $routeId;
    }
    }

    return self::$controller = FALSE;

    }


    /* — private section – */

    private static
    $_vars,
    $_tokens;

    private static function compileRoute($pattern)
       {
           self::$_vars = array();
           if(empty(self::$_tokens))
               return $pattern;

           foreach(self::$_tokens as $id => $reg)
           {
               if(($pos = stripos($pattern, '%'.$id)) !== FALSE)
               {
                   self::$_vars[$id] = $pos;
                   $pattern = str_ireplace('%'.$id.'%', $reg, $pattern);
               }
           }

           asort(self::$_vars);
           return $pattern;
       }
    }

    как видно из текста, класс "статический".
    вызываю вот так:

    $ctrl = QB_Url::lookupRoute();
    if ($ctrl)
    {

    if (file_exists(QB::$appDir.'ctrl/'.$ctrl.'.php'))
    include QB::$appDir.'ctrl/'.$ctrl.'.php';
    else
    include QB::$appDir.'ctrl/default.php';

    }
    else
    trigger_error('No route for this URL', E_USER_ERROR);

    здесь неявно присутствует еще один "статический" класс QB. я использую его в качестве namespace для базовых параметров системы, в т.ч. таблицы маршрутов.
    пример маршрутов и токенов для подстановки в них:

    array(
    'base_url' => 'http://test1.ru/minimal',
    'path' => '/minimal',
    'profiler' => 1,

    'route_tokens' => array(
    'date' => '(\d{4}/\d{2}/\d{2})',
    'title' => '(.*?)(?:\.html)?$',
    'id' => '(\d+)',
    'kind' => '(forum|gallery|blog)'
    ),

    'routes' => array(
    'post_new' => '/topic/%id%/new_post.html',
    'post_edit' => '/post/%id%/edit.html',
    'topic' => '/topic/%id%.html',
    'new_topic' => '/%kind%/%id%/new_topic.html',
    'board' => '/%kind%/%id%.html',
    'board_list' => '/%kind%/',
    'index' => '/$',
    )

    );

    работает всё в-целом так:
    если найден подходяший маршрут из таблицы маршрутов, то либо подключаем соответствующий модуль, либо модуль по-умолчанию. если соответствие URL и маршрута не найдено, генерируем ошибку.
    ιιlllιlllι унц-унц
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:08, спустя 6 минут 23 секунды

    а вот как выглядит "контроллер по умолчанию" /ctrl/default.php:

    <?php

    function dump()
    {
    ob_start();
    $num = func_num_args();
    for ($i = 0; $i < $num; ++$i)
    {
    print_r(func_get_arg($i));
    echo "\n\n";
    }
    $ret = trim(ob_get_contents());
    ob_end_clean();
    return $ret;
    }


    $view = QB::$appDir.'view/'.QB_Url::$controller.'.tpl';
    if (file_exists($view))
    {
    $data = array(
    'base_url' => QB::$config['base_url'],
    );
    QB_Template::out($view, $data);
    }
    else
    {
    $vars = dump(QB_Url::$controller, QB_Url::$params);

    echo <<<EOT

    <pre>
    Default controller
    no assotiated view
    ==================
    {$vars}
    </pre>

    EOT;

    }

    чисто отладочный вариант. если для вычисленного маршрута есть соответствующий шаблон, то выводим его. если нет — выводим дамп результатов рабора URL.

    перекликается с темой "сначала пишем вью, потом модель"
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:17, спустя 9 минут 28 секунд

    ухахахахахаха!!!!!!!!

    БОЙСЯ МЕНЯ
    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:19, спустя 1 минуту 32 секунды

    function dump()
    {
    ob_start();
    $num = func_num_args();
    for ($i = 0; $i < $num; ++$i)
    {
    print_r(func_get_arg($i));
    echo "\n\n";
    }
    $ret = trim(ob_get_contents());
    ob_end_clean();
    return $ret;
    }



    function debug()
    {
    $params = func_get_args();

    echo "<pre>";
    foreach($params as $param)
    {
    print_r($param);
    echo "<hr/>";
    }
    global $start;

    echo "generation time: ".(microtime(1)-$start);
    die();
    }
    и вот более разумный вариант. ошибка не в <pre> или тп, а в том, что ob_start(); = print_r($var,true);

    УХАХАХАХА!!! БОЙСЯ МЕНЯ!!!!
    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:21, спустя 1 минуту 47 секунд

    да, чтото подобное я хотел организовать в бесплатном SMCMS Portal.
    Сапожник без сапог
  • artoodetoo

    Сообщения: 5147 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:30, спустя 9 минут 16 секунд

    а, про print_r(…, true) я как-то не знал :) пару строк можно сэкономить
    ошибка - громко сказано, неоптимально, согласен.
    исправил на

    function dump()
    {
    for ($ret = '', $num = func_num_args(), $i = 0; $i < $num; ++$i)
    $ret .= print_r(func_get_arg($i), true) . "\n\n";
    return $ret;
    }
    ιιlllιlllι унц-унц
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:35, спустя 5 минут


    а, про print_r(…, true) я как-то не знал :) пару строк можно сэкономить
    ошибка - громко сказано, неоптимально, согласен.
    исправил на

    function dump()
    {
    for ($ret = '', $num = func_num_args(), $i = 0; $i < $num; ++$i)
    $ret .= print_r(func_get_arg($i), true) . "\n\n";
    return $ret;
    }

    уху :)
    Сапожник без сапог
  • phpdude

    Сообщения: 26646 Репутация: N Группа: в ухо

    Spritz 19 мая 2009 г. 9:36, спустя 32 секунды

    QB - что за сокращение, не подскажешь? должно же это чтото значить? ;)
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!