允许解析类似文件的URL路由

时间:2016-08-01 05:14:47

标签: yii2 url-routing yii-url-manager

每当我尝试处理看起来像controller/foo.xtn的路线时,Yii就会抱怨Unable to determine the path info of the current request.。我想通过将xtn转换为操作参数(即调用actionFoo($xtn))来处理这些路线,但也允许controller/foo?type=xtn。我的计划是编写一个UrlRule来定义这种行为,但是我如何解决路径信息解析失败?

我正在使用enablePrettyUrl,并希望enableStrictParsing但是现在我无需处理它。

编辑:什么有效,什么无效

controller/foo/abc?type=xtn ---> actionFoo('abc', 'xtn') # works
controller/foo/abc/xtn ---> actionFoo('abc', 'xtn') # works
controller/foo/abc.xtn ---> actionFoo('abc', 'xtn') # doesn't work

getPathInfo()尝试解析controller/foo/abc.xtn时会抛出此错误,因此网络服务器会将其路由到Yii。

路由配置(暂时使用PHP内部网络服务器):

<?php
// www/routing.php
if (preg_match('/\.(?:png|jpg|jpeg|gif)$/', $_SERVER["REQUEST_URI"])) {
    return false;
} else {
    include __DIR__ . '/../web/index.php';
}

使用上面的配置,我可以看到PHP服务器设置了Yii正在读取的REQUEST_URI变量。

'REQUEST_URI' => '/controller/foo/abc.xtn?app=4'

所以我不相信这是一个网络服务器问题。这是$ _SERVER数组中唯一的重要区别:

# fails in getPathInfo()
'REQUEST_URI' => '/feeds/strings/en.json?app=4',
'SCRIPT_NAME' => '/feeds/strings/en.json',
'SCRIPT_FILENAME' => '/Users/darvids0n/NetBeansProjects/php-web-services/web/www/routing.php',
'PHP_SELF' => '/feeds/strings/en.json',

# works
'REQUEST_URI' => '/feeds/strings/en?app=4',
'SCRIPT_NAME' => '/index.php',
'SCRIPT_FILENAME' => '/Users/darvids0n/NetBeansProjects/php-web-services/web/index.php',
'PATH_INFO' => '/feeds/strings/en',
'PHP_SELF' => '/index.php/feeds/strings/en',

但是,如果您阅读Yii的source code,您会发现缺少PATH_INFO实际上并未考虑到未能确定路径信息&#39;。

2 个答案:

答案 0 :(得分:2)

未知路径应该以404结尾。尝试重定向它可能会很棘手,你必须小心不要陷入循环。

您可以在列表中添加最后一条规则,即“最后的”路径,例如

'<controller>/<action>' => '<controller>/<action>',

任何控制器和操作都可以在这里工作。

对于文件扩展名,您可以为规则使用后缀参数。

[
    'pattern' => 'posts',
    'route' => 'post/index',
    'suffix' => '.json',
],

如果要将扩展名传递给操作,我会坚持使用一个参数名称:

'controller/foo/<type:\w+>' => 'controller/foo'

所以你需要采取以下行动:

public function actionFoo($type)

答案 1 :(得分:0)

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Button storeBTN = (Button) findViewById(R.id.button);
    storeBTN.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View v) {
            EditText et = (EditText) findViewById(R.id.editText);
            int i = Integer.parseInt(et.getText().toString());
            store(i);
        }
    });
    Button retrieveBTN = (Button) findViewById(R.id.button2);
    retrieveBTN.setOnClickListener(new View.OnClickListener(){

        @Override
        public void onClick(View v) {
            retrieve();
        }
    });

}
public void store(int newHighScore){
    Log.d("Meeeeee", "store: "+newHighScore);
    setContentView(R.layout.activity_main);
    SharedPreferences sharedPref = this.getPreferences(this.MODE_APPEND);
    SharedPreferences.Editor editor = sharedPref.edit();
    editor.putInt(getString(R.string.saved_high_score), newHighScore);
    boolean b = editor.commit();
    Log.d("Meeee", "store: commited? "+b);
    retrieve();
    return;
}
public void retrieve(){
    SharedPreferences sharedPref = this.getPreferences(this.MODE_APPEND);
    int defaultValue = getResources().getInteger(R.integer.saved_high_score_default);
    long highScore = sharedPref.getInt(getString(R.string.saved_high_score), defaultValue);
    Log.d("meeee", "retrieve: "+highScore+" in mode: "+this.MODE_APPEND);
    TextView scoreTV = (TextView) findViewById(R.id.textView);
    scoreTV.setText(highScore+"");
    return;
}

}