Yii2: 希望控制器动作能根据类型提示自动注入该类实例

Created on 29 Oct 2016  ·  14Comments  ·  Source: yiisoft/yii2

关于语言

我的英文水平有限,是不可能用英文来表达出我的意思的,所以请原谅我写下的中文。

关于我

我是一名中国的 yii 使用者和关注者。

关于这次的 issue

我个人比较喜欢 yii,所以冒昧地写下这个 issue。

我结合我的使用情况,说说我的看法,以及提出几点改进建议。

  • 我希望控制器的动作方法,能根据类型提示自动注入这个类型的实例,如下:
<?php

namespace allowing\test\controller;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex(\yii\web\Request $request)
    {
        // 这样可以轻松访问到 \yii\web\Request 的实例
        print_r($request->requestParams);
    }
}

因为我觉得这样的做法,在实际开发中是很方便的,虽然 \Yii::$app->request 能轻松访问到 \yii\web\Request 实例,但是 \Yii::$app 的侵入性太强了。我和我的朋友们也这样讨论过。

暂时只想到这一点。感谢。

under discussion

Most helpful comment

Here's the translation for the issue

Title

Automatic Injection required

Body

Sorry for using Chinese to submit this issue. My English is not very well so that I can't describe my problems clearly.

I'm a Chinese developer using yii, and I'm really enjoy developing things with it.

Now I have some suggestions to you.

I hope it is possible to let yii inject dependance automatically.
_like Laravel (added by translator)_

For example

<?php

namespace allowing\test\controller;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex(\yii\web\Request $request)
    {
        print_r($request->requestParams);
    }
}

Thank you.

All 14 comments

translated from Chinese:

He suggests to inject Yii::$app->request as first parameter in the Action parameter binding.

I kinda agree on this one. Magic like argument injection looks nice at first hand, but from an inheritance perspective you will encouter issues on long term. Its way more comfortable to have the full $request object available with typehinting & POST information. Of course this is BC break, but this definately is something to discuss for future releases. If you'd ask me, I would go for less magic and more OO.

This is how it works in Django. request is a first parameter of action (it's called view according to their terms). I think doing this for request only doesn't make much sense. In this case components like user (Yii::$app->user) also should be refactored. In Django user belongs to request and can be accessed as request.user. Yii has its own philosophy and I think developers have spent enough time to think and create application architechture what they think is right. I guess OP came from Django or framework with similar approach to write controller actions and it's uncomfortable to him to write the code in different way. You need to adapt to framework principles and philosophy you are using.

Again, this is not bad idea, but doing it for request only doesn't make much sense in my opinion.

Sounds like PSR-7.

I like the approach of Django

在实际的使用中,\Yii::$app->request 这样访问实例是真的不方便,如果多处需要这个实例一般还要赋值给一个变量,比如像下面这样:

<?php

namespace allowing\test\controller;

use Yii;
use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex()
    {
        // 要赋值给一个变量,才方便多处使用
        $request = Yii::$app->request;
        $request->get('name');
        $request->get('age');
        $request->get('page');

        // 这样感觉怪怪的
        Yii::$app->request->get('name');
        Yii::$app->request->get('age');
        Yii::$app->request->get('page');
    }
}

要是能像这样就不同了,你会发现简洁很多:

<?php

namespace allowing\test\controller;

use yii\web\Controller;
use yii\web\Request;

class SiteController extends Controller
{
    public function actionIndex(Request $request)
    {
        $request->get('name');
        $request->get('age');
        $request->get('page');
    }
}

Right? 其实,方便使用也是一种程序设计该考虑的事情。

yes. We are talking about the same thing.

虽然在控制器的构造器里能实现自动注入,我现在就是这样使用的。

首先在入口脚本 index.php 里注册一个单例:

Yii::$container->setSingleton(\yii\web\Request::class);
Yii::$container->setSingleton(\yii\web\Response::class);

然后我再在我的控制器的构造器里声明依赖:

class SiteController extends Controller
{
    private $_request;

    public function __construct($id, $module, Request $request, array $config = [])
    {
        $this->_request = $request;

        parent::__construct($id, $module, $config);
    }

    public function actionIndex()
    {
        // 这样我就可以使用了
        $this->_request->get('foo');
    }
}

^_^ ,感觉这样使用挺方便。所以今天才来提建议的。

Yes. It is handy.

@allowing 兄弟,你觉得自己的中文让老外看懂了吗?(Foreigners understand what you say Chinese?)^_^

Here's the translation for the issue

Title

Automatic Injection required

Body

Sorry for using Chinese to submit this issue. My English is not very well so that I can't describe my problems clearly.

I'm a Chinese developer using yii, and I'm really enjoy developing things with it.

Now I have some suggestions to you.

I hope it is possible to let yii inject dependance automatically.
_like Laravel (added by translator)_

For example

<?php

namespace allowing\test\controller;

use yii\web\Controller;

class SiteController extends Controller
{
    public function actionIndex(\yii\web\Request $request)
    {
        print_r($request->requestParams);
    }
}

Thank you.

for people struggling with those impressive chinese symbols. These are actually quite easy to process in Google Chromes page translation tool. Right mouse -> translate to English.

in my project,I use some behaviors to deal with this problem
for example, In a controller ,

class TestController extend Controller
{
    public $user;

    public function behaviors()
    {
        return [
            [
                'class' => AuthFilter::className(),
            ],
        ];
    }
}

and in the AuthFilter

if ($action->controller->canSetProperty('user')) {
                $action->controller->user = $user;
}

if you have declare a $user property in your controller, you will get the $user instance by $this->user; look like some kind of auto inject.

no no no.....

你这个毕竟不是真正利用反射自动注入所需实例,这样存在强耦合。

其实很多时候,类的方法都不是我们自己手动调用的,都是框架回调的,比如控制器方法,既然是回调方法,就可以好好利用反射技术。

You're talking about auto-wiring of dependencies for controller method calls. Here it is: https://github.com/yiisoft/yii2/issues/9476

Was this page helpful?
0 / 5 - 0 ratings

Related issues

Mirocow picture Mirocow  ·  56Comments

SamMousa picture SamMousa  ·  55Comments

vercotux picture vercotux  ·  47Comments

schmunk42 picture schmunk42  ·  125Comments

AstRonin picture AstRonin  ·  49Comments