CodeIgniter PHP Framework - необходимо получить строку запроса

Это связано с требованием отдельной компиляции и потому, что шаблоны являются полиморфизмом типа создания экземпляров.

Давайте немного приблизимся к конкретному для объяснения. Скажем, у меня есть следующие файлы:

  • foo.h объявляет интерфейс class MyClass<T>
  • foo.cpp определяет реализацию class MyClass<T>
  • bar.cpp использует MyClass<int>

. Отдельное средство компиляции. Я должен скомпилировать foo.cpp независимо от bar.cpp. Компилятор полностью выполняет всю сложную работу по анализу, оптимизации и генерации кода на каждом модуле компиляции; нам не нужно анализировать целую программу. Только компоновщик должен обрабатывать всю программу одновременно, и задача компоновщика значительно упрощается.

bar.cpp даже не нужно существовать при компиляции foo.cpp, но я все равно должен быть в состоянии связать foo.o Я уже имел вместе с bar.o Я только что выпустил, не перекомпилируя foo.cpp. foo.cpp может даже быть скомпилирован в динамическую библиотеку, распределенную где-то в другом месте без foo.cpp, и связан с кодом, который они пишут спустя годы после того, как я написал foo.cpp.

«Полиморфизм в стиле объектов» означает, что template MyClass<T> не является общим классом, который может быть скомпилирован в код, который может работать для любого значения T. Это добавит накладные расходы, такие как бокс, необходимо передать указатели на функции для распределителей и конструкторов и т. Д. Намерение шаблонов C ++ состоит в том, чтобы избежать необходимости писать почти идентичные class MyClass_int, class MyClass_float и т. Д., Но все же быть в состоянии закончить с компилируемым кодом, который в основном выглядит так, как если бы мы имели каждую версию отдельно. Таким образом, шаблон является буквально шаблоном; шаблон класса не класс, это рецепт создания нового класса для каждого T, с которым мы сталкиваемся. Шаблон не может быть скомпилирован в код, только результат создания экземпляра шаблона может быть скомпилирован.

Итак, когда foo.cpp скомпилирован, компилятор не может видеть bar.cpp, чтобы знать, что MyClass<int> необходимо. Он может видеть шаблон MyClass<T>, но он не может испускать код для этого (это шаблон, а не класс). И когда компилируется bar.cpp, компилятор может видеть, что ему нужно создать MyClass<int>, но он не может видеть шаблон MyClass<T> (только его интерфейс в foo.h), поэтому он не может его создать.

Если foo.cpp сам использует MyClass<int>, тогда код для него будет сгенерирован при компиляции foo.cpp, поэтому, когда bar.o связан с foo.o, они могут быть подключены и будут работать. Мы можем использовать этот факт, чтобы позволить конечный набор экземпляров шаблонов быть реализован в .cpp-файле, написав один шаблон. Но bar.cpp не может использовать шаблон в качестве шаблона и создавать его на всех типах, которые ему нравятся; он может использовать только ранее существовавшие версии шаблона, которые автор foo.cpp думал предоставить.

Вы можете подумать, что при компиляции шаблона компилятор должен «сгенерировать все версии», с теми, которые никогда не используются, отфильтровываются во время связывания. Помимо огромных накладных расходов и экстремальных трудностей, с которыми сталкивался такой подход, поскольку «модификаторы типа», такие как указатели и массивы, позволяют даже встроенным типам создавать бесконечное количество типов, что происходит, когда я расширяю свою программу добавив:

  • baz.cpp объявляет и реализует class BazPrivate и использует MyClass<BazPrivate>

Невозможно, чтобы это могло работать, если мы либо

  1. Необходимо перекомпилировать foo.cpp каждый раз, когда мы меняем любой другой файл в программе , в случае, если он добавил новый романный экземпляр MyClass<T>
  2. Требовать, чтобы baz.cpp содержал (возможно, через заголовок) полный шаблон MyClass<T>, чтобы компилятор мог генерировать MyClass<BazPrivate> во время компиляции baz.cpp.

Никто не любит (1), потому что системы компиляции целых программ принимают forever для компиляции и потому что это делает невозможным распространение компилированных библиотек без исходного кода. Итак, у нас есть (2).

33
задан Michael Myers 26 July 2010 в 14:52
поделиться

8 ответов

Вы можете получить вот так:

$this->input->get('some_variable', TRUE);

Смотрите это для дополнительной информации.

57
ответ дан 27 November 2019 в 17:31
поделиться

Если вы хотите, чтобы не разобрать строку запроса:

$this->input->server('QUERY_STRING');
16
ответ дан 27 November 2019 в 17:31
поделиться

Вы можете создать правило в вашем .htaccess, чтобы предотвратить обстрел MOD_REWRITE на этой конкретной странице. Это позволит вам использовать _GET.

0
ответ дан 27 November 2019 в 17:31
поделиться

Откройте application / config / config.php и установите следующие значения:

$config['uri_protocol'] = "PATH_INFO";

$config['enable_query_strings'] = TRUE; 

Теперь строки запроса должны работать нормально.

5
ответ дан 27 November 2019 в 17:31
поделиться

Я использую CodeIgniter уже больше года. По большей части мне это очень нравится (я участвую в форуме и использую его во всех случаях, когда могу), но я НЕНАВИЖУ ГОРДЕННОСТЬ этого утверждения в руководстве:

Уничтожает глобальный массив GET. Поскольку CodeIgniter не использует строки GET , нет причин разрешать это.

Предположение, что вам никогда не понадобится GET в приложении CodeIgniter, бессмысленно! Уже через несколько дней мне пришлось иметь дело с обратными страницами из PayPal и ClickBank (я уверен, что есть миллион других). Угадайте, что они используют GET !!!

Есть способы остановить это раздавливание GET, но они имеют тенденцию портить другие вещи. Чего вы не хотите слышать, так это того, что вам нужно перекодировать все свои представления, потому что вы включили строки запроса, а теперь ваши ссылки не работают! Внимательно прочтите руководство по этой опции!

Один, который мне нравится (но не сработал, потому что установка REQUEST_URI в config.php сломала мой сайт), расширяет класс Input:

class MY_Input extends CI_Input
{
        function _sanitize_globals()
        {
            $this->allow_get_array = TRUE;
            parent::_sanitize_globals();
        }
}

Но лучший серьезный способ - протестировать с помощью print_r ($ _ SERVER) на URL-адрес, по которому вам нужны переменные GET. Посмотрите, какая опция протокола URI показывает ваши переменные GET, и используйте ее.

В моем случае я вижу, что мне нужно, в REQUEST_URI

// defeat stupid CI GET squashing!
parse_str($_SERVER['REQUEST_URI'], $_GET);

. Это возвращает строку запроса в суперглобальный объект $ _GET для этого экземпляра страницы (вам не нужно использовать $ _GET, это может быть любая переменная.)

EDIT

После публикации этого сообщения я обнаружил, что при использовании REQUEST_URI вы потеряете свой первый ключ массива строки запроса, если не удалите все, что находится перед?. Например, URL-адрес типа / controller / method? One = 1 & two = 2 заполнит массив $ _GET в этом примере массивом ('method? One' => 1, 'two' => 2). Чтобы обойти это, я использовал следующий код:

parse_str(substr(strrchr($_SERVER['REQUEST_URI'], "?"), 1), $_GET);

Полагаю, мне следовало предоставить пример, поэтому здесь:

class Pgate extends Controller {
   function postback() {
      parse_str(substr(strrchr($_SERVER['REQUEST_URI'], "?"), 1), $_GET);
      $receipt = $this->input->xss_clean($_GET['receipt']);
   }
}
22
ответ дан 27 November 2019 в 17:31
поделиться

Вы можете создать ловушку pre_system. В создаваемом вами классе перехвата вы можете получить нужные параметры запроса и добавить их в $ _POST для нормальной обработки CI. Я сделал это для помощника jQuery Ajax.

Например:

(Назовите этот файл autocomplete.php или как угодно, что вы указали в качестве имени файла в ловушке)

<?php

/*
By Brodie Hodges, Oct. 22, 2009.
*/

if (!defined('BASEPATH')) exit('No direct script access allowed');
/**
*   Make sure this file is placed in your application/hooks/ folder.
*
*   jQuery autocomplete plugin uses query string.  Autocomplete class slightly modified from excellent blog post here:
*   http://czetsuya-tech.blogspot.com/2009/08/allowing-url-query-string-in.html 
*   Ajax autocomplete requires a pre_system hook to function correctly.  Add to your 
*   application/config/hooks.php if not already there:

    $hook['pre_system'][] = array(
        'class'    => 'Autocomplete',
                'function' => 'override_get',
                                'filename' => 'autocomplete.php',
                                'filepath' => 'hooks',
                                'params'   => array()
                                );

*                               
* 
*/

class Autocomplete {
    function override_get() {
        if (strlen($_SERVER['QUERY_STRING']) > 0) {
            $temp = @array();
            parse_str($_SERVER['QUERY_STRING'], $temp);
            if (array_key_exists('q', $temp) && array_key_exists('limit', $temp) && array_key_exists('timestamp', $temp)) {
                $_POST['q'] = $temp['q'];
                $_POST['limit'] = $temp['limit'];
                $_POST['timestamp'] = $temp['timestamp'];
                $_SERVER['QUERY_STRING'] = "";
                $_SERVER['REDIRECT_QUERY_STRING'] = "";
                $_GET = @array();
                $url = strpos($_SERVER['REQUEST_URI'], '?');
                if ($url > -1) {
                    $_SERVER['REQUEST_URI'] = substr($_SERVER['REQUEST_URI'], 0, $url);
                }
            }
        }
    }
}

?>
0
ответ дан 27 November 2019 в 17:31
поделиться

Спасибо всем другим плакатам. Вот что пришло мне в голову:

    $qs = $_SERVER['QUERY_STRING'];
    $ru = $_SERVER['REQUEST_URI'];
    $pp = substr($ru, strlen($qs)+1);
    parse_str($pp, $_GET);

    echo "<pre>";
    print_r($_GET);
    echo "</pre>";

То есть, теперь я мог делать:

$token = $_GET['token'];

В .htaccess мне пришлось изменить:

RewriteRule ^(.*)$ /index.php/$1 [L]

на:

RewriteRule ^(.*)$ /index.php?/$1 [L]
1
ответ дан 27 November 2019 в 17:31
поделиться

Если вы используете mod_rewrite для удаления файла index.php, вы можете использовать следующий код для получения переменных GET (через $ this-> input-> get ()). Предполагая конфигурацию по умолчанию, назовите файл MY_Input.php и поместите его в каталог приложений / библиотек.

Использование: $ this-> input-> get ()

class MY_Input extends CI_Input {

    function My_Input()
    {
        parent::CI_Input();

        // allow GET variables if using mod_rewrite to remove index.php
        $CFG =& load_class('Config');
        if ($CFG->item('index_page') === "" && $this->allow_get_array === FALSE)
        {
            $_GET = $this->_get_array();
        }

    }

    /**
     * Fetch an item from the GET array
     * 
     * @param string $index
     * @param bool   $xss_clean
     */
    function get($index = FALSE, $xss_clean = FALSE)
    {
        // get value for supplied key
        if ($index != FALSE)
        {
            if (array_key_exists(strval($index), $_GET))
            {
                // apply xss filtering to value
                return ($xss_clean == TRUE) ? $this->xss_clean($_GET[$index]) : $_GET[$index];
            }
        }
        return FALSE;
    }

    /**
     * Helper function
     * Returns GET array by parsing REQUEST_URI
     * 
     * @return array
     */
    function _get_array()
    {           
        // retrieve request uri
        $request_uri = $this->server('REQUEST_URI');

        // find query string separator (?)
        $separator = strpos($request_uri, '?');
        if ($separator === FALSE)
        {
            return FALSE;
        }

        // extract query string from request uri
        $query_string = substr($request_uri, $separator + 1);

        // parse query string and store variables in array
        $get = array();
        parse_str($query_string, $get);

        // apply xss filtering according to config setting
        if ($this->use_xss_clean === TRUE)
        {
            $get = $this->xss_clean($get);
        }

        // return GET array, FALSE if empty
        return (!empty($get)) ? $get : FALSE;
    }


}
2
ответ дан 27 November 2019 в 17:31
поделиться
Другие вопросы по тегам:

Похожие вопросы: