Laravel по-русски

Русское сообщество разработки на PHP-фреймворке Laravel.

Ты не вошёл. Вход тут.

#1 17.10.2012 13:27:07

JSONP через роутер и контроллер

Добрый день.

Подсобите советом, пожалуйста.
Есть запрос, который идет из JS, вида:

xml$.getJSON('http://domain.com/en/graph?callback=?', function(data) {
  alert(data);
});

соответственно jQuery сам подставляет что нужно в параметр callback (что то вида jQueryBlablalba…)
есть описание маршрута в routes.php

PHP
Route::get('graph/(:any?)(=.*)', function($action null) {
  return 
Controller::call('graph@index', array($action));
});
Route::controller(Controller::detect());

и сам контроллер:

PHP
class Graph_Controller extends Base_Controller
{
  public function 
action_index() {
    
$data "...";
    return 
Input::get('/en/graph/callback') . '('.$data.')';
  }
}

В таком варианте во всяком случае работает, но вот как то жутко мне не нравится Input::get('/en/graph/callback')
Есть ли более кошерный путь?

Изменено John (17.10.2012 13:29:47)

Не в сети

#2 17.10.2012 15:37:33

Re: JSONP через роутер и контроллер

  1. PHPInput::get('/en/graph/callback')

Ого! Я такого ещё не видел. А почему не работает (ли?) просто PHPInput::get('callback')? Ведь приходит обычный GET-запрос, в нём передаётся обычный параметр callback. Я удивлён, что твой код работает.

Не в сети

#3 17.10.2012 15:52:08

Re: JSONP через роутер и контроллер

echo Input::get('callback'); точно не работает, а вот var_dump(Input::all()); выдает презабавную штуку:

PHP
array(1) {
  [
"en/graph/callback"]=>
  
string(9"blablalba"
}

Не в сети

#4 17.10.2012 18:14:55

Re: JSONP через роутер и контроллер

Вероятнее всего все дело в маршрутизации, в определении языка в первом сегменте URI, я делаю вот так:

PHP
Route::filter('before', function () {
    
$langUri URI::segment(1);
    if (
strlen($langUri) === 2) {
        if (
$langUri == 'en' || $langUri == 'ru') {
            
Cookie::forever('language'$langUri);
        }
    } else {
        
$browserLang Session::get('user.lang');
        if (
$browserLang == 'en' || $browserLang == 'ru') {
            
Cookie::forever('language'$browserLang);
            return 
Redirect::to(URL::base() . "/" $browserLang);
        } else {
            ....
        }
    }
});

в Session::get('user.lang') содержится язык браузера.
вроде все ездит как надо, кроме пока с непонятной проблемой в Input::all()
насколько я понял, последний релиз Ларавела сам следит за первым сегментом с языком, потому как маршруты у меня ездят без каких либо танцев с бубном:

PHP
Route::get('aboutus''home@aboutus');

и он всегда приезжает сюда при запросах http://domain.com/en/aboutus, http://domain.com/fr/aboutus

Не в сети

#5 17.10.2012 20:32:03

Re: JSONP через роутер и контроллер

Да, в последней версии (3.2.10) добавилось автоопределение языка и настройка application.languages:

PHP
// laravel/laravel.php
$uri URI::current();
$languages Config::get('application.languages', array());
$languages[] = Config::get('application.language');

foreach (
$languages as $language) {
    if (
preg_match("#^{$language}(?:$|/)#i"$uri))     {
        
Config::set('application.language'$language);
        
$uri trim(substr($uristrlen($language)), '/');
        break;
    }
}

if (
$uri == ''$uri '/';
URI::$uri $uri;

Ошибка может быть в настройках среды/переадресации URL в public/index.php через .htaccess. PHPInput::get('/en/graph/callback') — это проблема только конкретного какого-то маршрута или вообще любого, даже PHPRoute::get('/', function () { dd(Input::all()); });?

Не в сети

#6 17.10.2012 21:15:07

Re: JSONP через роутер и контроллер

Любого маршрута, вот к примеру:

PHP
Route::get('news/(:num)''home@news');

вызов:
http://domain.com/en/news/2
контроллер:

PHP
public function action_news() {
        echo 
"<pre>\n";
        
var_dump(Input::all());
        echo 
"<pre>\n";
        exit;
}

на выходе:

PHP
array(1) {
  [
"en/news/2"]=>
  
string(0""
}

ездит все под .htaccess

xml<IfModule mod_rewrite.c>
    Options -Indexes +FollowSymLinks
    RewriteEngine On

    RewriteCond %{REQUEST_FILENAME} !-f
    RewriteCond %{REQUEST_FILENAME} !-d
    RewriteRule ^(.*)$ index.php?$1 [L] # default: index.php/$1 article: http://forums.laravel.com/viewtopic.php?id=1508
</IfModule>

PS: /public/index.php и остальные настройки среды /config — дефолтные (т.е. ничего не добавлялось, менялись только app ключ, база и добавил 'languages' => array('en', 'ru'), в application.php)

Изменено John (17.10.2012 21:29:04)

Не в сети

#7 18.10.2012 08:55:55

Re: JSONP через роутер и контроллер

Похоже это проблема текущей версии (3.2.10) фреймворка, только что сделал следующее:
1. скачал с сайта дистрибутив
2. установил локально, прописал виртуалку в httpd.conf Апачи
3. поменял в application.php строку 'index' => '', (убрал с нее index.php)
4. поменял в нем же строку 'languages' => array('en','ru'),
5. заремарил в routes.php строки:

PHP
Route::get('/', function()
{
    return 
View::make('home.index');
});

6. заместо этого прописал:

PHP
Route::get('home/(:any?)''home@index');
Route::controller(Controller::detect());

7. запустил и обломался, при переходе на http://domain.com/home вылетает No input file specified.
проблема была описана в статье про .htaccess
8. меняю в нем строку RewriteRule ^(.*)$ index.php/$1 [L] на RewriteRule ^(.*)$ index.php$1 [L]
9. запускаю — все поехало, спокойно едет на http://domain.com/home и на http://domain.com/en/home
10. вот только при http://domain.com/en/home/1 выдает:

xmlarray(1) {
  ["/en/home/1"]=>
  string(0) ""
}

:D

Не в сети

#8 18.10.2012 09:17:22

Re: JSONP через роутер и контроллер

В общем обошел пока эту фигню через финт ушами:
маршрут прописываю как:

PHP
Route::get('home/(:any?)', function($param null) {
        return 
Controller::call('home@index', array($param));
});
Route::controller(Controller::detect());

в контроллере:

PHP
public function action_index($param) {
    echo 
"$param<br>";
}

собственно получаю что нужно, без грязи

Не в сети

#9 19.10.2012 09:05:12

Re: JSONP через роутер и контроллер

С такой проблемой не сталкивался и не могу придумать, что может её вызывать. index.php$1 или index.php?$1 — довольно странное решение, но раз только оно работает… А index.php у вас вписан в DirectoryIndex?

Если в изначальном .htaccess поменять index.php?$1 на index.php/$1, но без имени хоста, тоже будет No input file specified?

Я бы прошёл отладчиком и посмотрел, что делает Laravel — часто это быстрее, чем разбираться методом тыка.

Не в сети

#10 21.10.2012 10:47:56

Re: JSONP через роутер и контроллер

index.php в DirectoryIndex вписан. Замена ? на / выдает все тот же No input file specified. Пока остановился на вышеозвученном решении, вроде все работает.

Не в сети

#11 21.10.2012 18:15:26

Re: JSONP через роутер и контроллер

  1. No input file specified

А как вообще выглядит эта ошибка? Кто её генерирует? В Laravel я такой не видел.

Не в сети

#12 22.10.2012 08:26:36

Re: JSONP через роутер и контроллер

Это ошибка с кодом 404, а выдает эту надпись походу сам PHP. У народа, согласно гуглу, таки штуки вылазят при проблемах в связках CMS (различных видов) + mod_rewrite. Как то так.

Не в сети

#13 07.11.2012 15:21:31

Re: JSONP через роутер и контроллер

{=John} В общем обошел пока эту фигню через финт ушами:
маршрут прописываю как:

PHP
Route::get('home/(:any?)', function($param null) {
        return 
Controller::call('home@index', array($param));
});
Route::controller(Controller::detect());

в контроллере:

PHP
public function action_index($param) {
    echo 
"$param<br>";
}

собственно получаю что нужно, без грязи

Что же происходит на самом деле?
На самом деле в routes.php, естественно, команды (инструкции) выполняются последовательно.
Поэтому, после формирования всех маршрутов у нас есть массив последних.
Если Route::controller(Controller::detect()); указан первым маршрутом, то в массиве маршрутов первым будет маршрут вида
/home/(:any?)/(:any?)/(:any?)/(:any?)/(:any?) , где (:any?) будет повторен 5 раз, согласно переменной $segments.
Цитата из router.php

PHP
...
/**
     * The number of URI segments allowed as method arguments.
     *
     * @var int
     */
    
public static $segments 5;
...
            
// The number of method arguments allowed for a controller is set by a
            // "segments" constant on this class which allows for the developer to
            // increase or decrease the limit on method arguments.
            
echo "<pre>".print_r(static::$segments,true)."</pre>";
exit;
            
$wildcards = static::repeat('(:any?)', static::$segments);

В итоге, маршрут .home/(:any?) функцией match (там же), идентифицируется как /home/(:any?)/(:any?)/(:any?)/(:any?)/(:any?), который и выдается, после чего получаем ’404’. Все.
Вывод: или прописывать все роуты вручную, или ставить Route::controller(Controller::detect()); в конце.
Что и сделал John.
Если использовать detect, тогда всю маршрутизацию нужно согласовать с соглашениями Laravel.
И обработка Route::get(’home/(:any?)’,… только через Closure.

Изменено oleg578 (07.11.2012 15:47:30)

Не в сети

#14 07.11.2012 15:37:52

Re: JSONP через роутер и контроллер

С такой проблемой не сталкивался и не могу придумать, что может её вызывать. index.php$1 или index.php?$1 — довольно странное решение, но раз только оно работает… А index.php у вас вписан в DirectoryIndex?

Если в изначальном .htaccess поменять index.php?$1 на index.php/$1, но без имени хоста, тоже будет No input file specified?

Я бы прошёл отладчиком и посмотрел, что делает Laravel — часто это быстрее, чем разбираться методом тыка.

Потому что тогда у вас в mod_rewrite (при index.php$1)на выходе (причем промежуточном) получиться:

вход: mysite/home/1
после RewriteRule index.phphome/1 (именно так) и пошли по кругу. в бесконечный цикл. Флаг [L] не спасет, т.к. в htacces он не работает. поэтому ловим ’500’.

Так что в документации указан правильный файл. Практически… ☺

Не в сети

Подвал раздела