<rmcreative>

RSS

Yii, параметры action-а

4 августа 2011

В Yii есть приятная возможность: все $_GET-параметры автоматом передаются как аргументы метода.

public function actionView($id)
{
    echo $id == $_GET['id'];
}

Можно расширить возможность, например, на POST как показал helmut в топике:

class MyPostAwareController extends CController
{
    public function getActionParams()
    {
      return array_merge($_GET, $_POST);
    }
}

Комментарии RSS

  1. №5112
    OZ
    OZ 04 авг. 2011 г., 1:00:48

    "все $_GET-параметры автоматом передаются как аргументы метода" - отключены register_globals? Настоящего говнокодера это не остановит!

  2. №5113
    Sam
    Sam 04 авг. 2011 г., 1:11:26

    OZ, э, нее. Тут не объявишь аргумент — ничего не передастся.

  3. №5121
    biakaveron
    biakaveron 04 авг. 2011 г., 9:44:46

    ИМХО, в Kohana удобнее. Там имеется отдельный класс Request, в котором и хранятся его собственные GET/POST, а также сегменты УРЛа, полученные на основе разобранного Route. Естественно, если внутри него запускается HMVC-запрос, то в его объекте Request будут свои GET/POST/сегменты.

    В итоге экшены вообще не содержат параметры (ранее в них указывались сегменты роута).

  4. №5122
    OZ
    OZ 04 авг. 2011 г., 9:54:49

    Sam, текст заметки эту информацию преподнозит неоднозначно. То, что показал helmut, недалеко ушло от $_REQUEST (и точно также позволяет получить конфликт имён аргументов).

  5. №5125
    Sam
    Sam 04 авг. 2011 г., 17:30:32

    biakaveron, вариант Koahana удобен, если используется HMVC. Всегда можно родительский запрос получить (если я с Fuel не путаю). В случае когда HMVC не является основной фишкой фреймворка, необходимость дополнительной обёртки, как мне кажется, сомнительна. Ну и сегменты использовать напрямую — большое зло. Потом URL не заменить прозрачно через конфиг роутера.

    OZ, в REQUEST ещё по дефолту попадают куки, поэтому с ним и опасно работать, если не понимать, что делаешь :)

    В Yii из коробки работает исключительно с GET как раз по причине конфликта имён и неоднозначности в случае намешивания туда чего-либо ещё.

  6. №5150
    Vladimir
    Vladimir 06 авг. 2011 г., 20:45:19

    С точки зрения безопасности $_GET и $_POST в одну кучу всё же лучше не мешать — если приложение не использует одноразовые токены при обработке запросов, которые изменяют внутреннее состояние приложения, получим потенциальные уязвимости типа CSRF (cross site request forgery).

  7. №5547
    Андрей
    Андрей 25 окт. 2011 г., 23:28:39

    А нельзя сделать чтобы при отсутствии входных параметров в action выдавалась 404 ошибка? Т.е.: http://site.ru/news/123 - http 200 http://site.ru/news/123?param=value - http 404

  8. №5548
    Sam
    Sam 26 окт. 2011 г., 1:36:43

    Может всё-таки при наличии?

  9. №5549
    Андрей
    Андрей 26 окт. 2011 г., 11:42:13

    Сорри, не совсем удачно объяснил.

    public function actionShow($id)
    {
         News::model()->findByPk($id);
         ...
    }
    http://site.ru/news/123 - выдает 200, как и предполагалось
    http://site.ru/news/123?param=value - выдает 200, а хочется 404 чтобы не получались дубли страниц
  10. №5550
    Sam
    Sam 26 окт. 2011 г., 13:47:58

    Вроде вот это должно помочь. Единственное, придётся правила прописать для всего руками.

  11. №5551
    Андрей
    Андрей 26 окт. 2011 г., 14:01:11

    Правила во фронтенде и так руками прописаны для повышения безопасности. Я тоже надеялся, что должно помочь, а не помогает.

    'urlManager'=>array(
        'urlFormat'=>'path',
        'useStrictParsing'=>true,
        'showScriptName'=>false,
        'rules'=>array(
            ''=>'page/main',
            'news/page<News_page:\d+>'=>'news/page',
            'news/<url:>'=>'news/view',
    public function actionView($url)
    {
        $model=News::model()->findByAttributes(array('n_url'=>$url));
    http://site.ru/news/Apple-wholesale - 200
    http://site.ru/news/Apple-wholesale?pp=zz - 200
  12. №5552
    Sam
    Sam 26 окт. 2011 г., 23:39:56

    Хм… попробуйте на форуме спросить, возможно там кто сталкивался именно с такой задачей. Сейчас, к сожалению, не смогу заняться.

  13. №6623
    karpo518
    karpo518 11 сент. 2012 г., 0:55:13

    Андрей, на SEO влияют только дубли в индексе ПС. В индекс страницы попадают после считывания ссылок. Если сайт спроектирован верно и на нём нет кривых ссылок (ссылок на дубли), то дубли никогда не попадут в индекс. Для остальных случаев существуют robots.txt, webmaster.yandex.ru/delurl.xml и rel="canonical". Когда я не знал об этом, я создавал функцию- валидатор, реализованную в базовом контроллере, в которую передавались минимально и максимально возможное количество параметров для действия. В случае не соответствия границам функция завершала действие и возвращала 404-ый ответ. В Yii это можно сделать, задав абстрактный метод в базовом контроллере, который должен возвращать массив с количеством параметров для каждого действия контроллера. Проверять количество параметров можно в beforeAction того же базового контроллера. Опять-таки повторюсь, что смысл в такой проверке отсутствует, так как поисковые роботы не используют рандомные урлы.

  14. №7956
    Igo
    Igo 13 мая 2013 г., 9:42:01

    На одном проекте решил задачу, которую описал Андрей следующим способом - переделал метод в классе /framework/web/actions/CAction

    protected function runWithParamsInternal($object, $method, $params)
        {
            $ps=array();
            $methodParams = array();
            foreach($method->getParameters() as $i=>$param)
            {
                $methodParams[] = $name = $param->getName();
                if(isset($params[$name])) 
                {
                    if($param->isArray())
                        $ps[]=is_array($params[$name]) ? $params[$name] : array($params[$name]);
                    elseif(!is_array($params[$name]))
                        $ps[]=$params[$name];
                    else
                        return false;
                }
                elseif($param->isDefaultValueAvailable())
                    $ps[]=$param->getDefaultValue();
                else
                    return false;
            }
     
        foreach ($params as $name=>$value) {
          if (!in_array($name, $methodParams)) {
            return false;
          }
        }
     
            $method->invokeArgs($object,$ps);
            return true;
        }

    И хочу спросить совета у Sam: как лучше всего поступать в таких случаях, когда вносятся свои изменения в код фреймфорка? Я понимаю что это не очень хорошо, т.к. возникают проблемы с обновлением версии фреймворка - после обновления надо не забыть внести в код свои правки.

  15. №7958
    Sam
    Sam 13 мая 2013 г., 12:35:18

    Igo, сделать универсальный pull-request в ядро на github, приложив объяснения, почему оно нужно.

  16. №9833
    Виталий
    Виталий 05 июня 2015 г., 11:38:16

    Привет.А если в url передается массив, например, так site.com/section/block?perpage=4&color=2&style%5B%5D=1&style%5B%5D=1

    а в action как принять массив значений style?

  17. №9834
    Виталий
    Виталий 05 июня 2015 г., 12:00:27

    уже знаю, просто написать так actionBlock($color=NULL, array $style = array()), то есть указать, что $style - это массив

  1. Почта опубликована не будет.

  2. Можно использовать синтаксис Markdown или HTML.

  3. Введите ответ в поле. Щёлкните, чтобы получить другую задачу.